diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md index 16cb82d..9396e06 100644 --- a/packages/@headlessui-react/CHANGELOG.md +++ b/packages/@headlessui-react/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ensure the caret is in a consistent position when syncing the `Combobox.Input` value ([#2568](https://github.com/tailwindlabs/headlessui/pull/2568)) - Improve "outside click" behaviour in combination with 3rd party libraries ([#2572](https://github.com/tailwindlabs/headlessui/pull/2572)) - Ensure IME works on Android devices ([#2580](https://github.com/tailwindlabs/headlessui/pull/2580)) +- Calculate `aria-expanded` purely based on the open/closed state ([#2610](https://github.com/tailwindlabs/headlessui/pull/2610)) ## [1.7.15] - 2023-06-01 diff --git a/packages/@headlessui-react/src/components/combobox/combobox.tsx b/packages/@headlessui-react/src/components/combobox/combobox.tsx index 7b288ad..c7839d3 100644 --- a/packages/@headlessui-react/src/components/combobox/combobox.tsx +++ b/packages/@headlessui-react/src/components/combobox/combobox.tsx @@ -1020,7 +1020,7 @@ function InputFn< role: 'combobox', type, 'aria-controls': data.optionsRef.current?.id, - 'aria-expanded': data.disabled ? undefined : data.comboboxState === ComboboxState.Open, + 'aria-expanded': data.comboboxState === ComboboxState.Open, 'aria-activedescendant': data.activeOptionIndex === null ? undefined : data.options[data.activeOptionIndex]?.id, 'aria-labelledby': labelledby, @@ -1152,7 +1152,7 @@ function ButtonFn( tabIndex: -1, 'aria-haspopup': 'listbox', 'aria-controls': data.optionsRef.current?.id, - 'aria-expanded': data.disabled ? undefined : data.comboboxState === ComboboxState.Open, + 'aria-expanded': data.comboboxState === ComboboxState.Open, 'aria-labelledby': labelledby, disabled: data.disabled, onClick: handleClick, diff --git a/packages/@headlessui-react/src/components/disclosure/disclosure.tsx b/packages/@headlessui-react/src/components/disclosure/disclosure.tsx index 22f9329..4a7687d 100644 --- a/packages/@headlessui-react/src/components/disclosure/disclosure.tsx +++ b/packages/@headlessui-react/src/components/disclosure/disclosure.tsx @@ -340,9 +340,7 @@ function ButtonFn( ref: buttonRef, id, type, - 'aria-expanded': props.disabled - ? undefined - : state.disclosureState === DisclosureStates.Open, + 'aria-expanded': state.disclosureState === DisclosureStates.Open, 'aria-controls': state.linkedPanel ? state.panelId : undefined, onKeyDown: handleKeyDown, onKeyUp: handleKeyUp, diff --git a/packages/@headlessui-react/src/components/listbox/listbox.tsx b/packages/@headlessui-react/src/components/listbox/listbox.tsx index db46522..8b11271 100644 --- a/packages/@headlessui-react/src/components/listbox/listbox.tsx +++ b/packages/@headlessui-react/src/components/listbox/listbox.tsx @@ -680,7 +680,7 @@ function ButtonFn( type: useResolveButtonType(props, data.buttonRef), 'aria-haspopup': 'listbox', 'aria-controls': data.optionsRef.current?.id, - 'aria-expanded': data.disabled ? undefined : data.listboxState === ListboxStates.Open, + 'aria-expanded': data.listboxState === ListboxStates.Open, 'aria-labelledby': labelledby, disabled: data.disabled, onKeyDown: handleKeyDown, diff --git a/packages/@headlessui-react/src/components/menu/menu.tsx b/packages/@headlessui-react/src/components/menu/menu.tsx index 24769a5..e829ce0 100644 --- a/packages/@headlessui-react/src/components/menu/menu.tsx +++ b/packages/@headlessui-react/src/components/menu/menu.tsx @@ -400,7 +400,7 @@ function ButtonFn( type: useResolveButtonType(props, state.buttonRef), 'aria-haspopup': 'menu', 'aria-controls': state.itemsRef.current?.id, - 'aria-expanded': props.disabled ? undefined : state.menuState === MenuStates.Open, + 'aria-expanded': state.menuState === MenuStates.Open, onKeyDown: handleKeyDown, onKeyUp: handleKeyUp, onClick: handleClick, diff --git a/packages/@headlessui-react/src/components/popover/popover.tsx b/packages/@headlessui-react/src/components/popover/popover.tsx index a094d5f..b911d3f 100644 --- a/packages/@headlessui-react/src/components/popover/popover.tsx +++ b/packages/@headlessui-react/src/components/popover/popover.tsx @@ -591,7 +591,7 @@ function ButtonFn( ref: buttonRef, id: state.buttonId, type, - 'aria-expanded': props.disabled ? undefined : state.popoverState === PopoverStates.Open, + 'aria-expanded': state.popoverState === PopoverStates.Open, 'aria-controls': state.panel ? state.panelId : undefined, onKeyDown: handleKeyDown, onKeyUp: handleKeyUp, diff --git a/packages/@headlessui-react/src/test-utils/accessibility-assertions.ts b/packages/@headlessui-react/src/test-utils/accessibility-assertions.ts index a1797fd..dba8da4 100644 --- a/packages/@headlessui-react/src/test-utils/accessibility-assertions.ts +++ b/packages/@headlessui-react/src/test-utils/accessibility-assertions.ts @@ -62,20 +62,12 @@ export function assertMenuButton( case MenuState.InvisibleHidden: expect(button).toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break case MenuState.InvisibleUnmounted: expect(button).not.toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break default: @@ -352,20 +344,12 @@ export function assertComboboxInput( case ComboboxState.InvisibleHidden: expect(input).toHaveAttribute('aria-controls') - if (input.hasAttribute('disabled')) { - expect(input).not.toHaveAttribute('aria-expanded') - } else { - expect(input).toHaveAttribute('aria-expanded', 'false') - } + expect(input).toHaveAttribute('aria-expanded', 'false') break case ComboboxState.InvisibleUnmounted: expect(input).not.toHaveAttribute('aria-controls') - if (input.hasAttribute('disabled')) { - expect(input).not.toHaveAttribute('aria-expanded') - } else { - expect(input).toHaveAttribute('aria-expanded', 'false') - } + expect(input).toHaveAttribute('aria-expanded', 'false') break default: @@ -458,20 +442,12 @@ export function assertComboboxButton( case ComboboxState.InvisibleHidden: expect(button).toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break case ComboboxState.InvisibleUnmounted: expect(button).not.toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break default: @@ -798,20 +774,12 @@ export function assertListboxButton( case ListboxState.InvisibleHidden: expect(button).toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break case ListboxState.InvisibleUnmounted: expect(button).not.toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break default: @@ -1100,20 +1068,12 @@ export function assertDisclosureButton( case DisclosureState.InvisibleHidden: expect(button).toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break case DisclosureState.InvisibleUnmounted: expect(button).not.toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break default: @@ -1232,20 +1192,12 @@ export function assertPopoverButton( case PopoverState.InvisibleHidden: expect(button).toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break case PopoverState.InvisibleUnmounted: expect(button).not.toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break default: diff --git a/packages/@headlessui-vue/CHANGELOG.md b/packages/@headlessui-vue/CHANGELOG.md index e894c1b..75da021 100644 --- a/packages/@headlessui-vue/CHANGELOG.md +++ b/packages/@headlessui-vue/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improve "outside click" behaviour in combination with 3rd party libraries ([#2572](https://github.com/tailwindlabs/headlessui/pull/2572)) - Improve performance of `Combobox` component ([#2574](https://github.com/tailwindlabs/headlessui/pull/2574)) - Ensure IME works on Android devices ([#2580](https://github.com/tailwindlabs/headlessui/pull/2580)) +- Calculate `aria-expanded` purely based on the open/closed state ([#2610](https://github.com/tailwindlabs/headlessui/pull/2610)) ## [1.7.14] - 2023-06-01 diff --git a/packages/@headlessui-vue/src/components/combobox/combobox.ts b/packages/@headlessui-vue/src/components/combobox/combobox.ts index f7e5d7a..8b4b6e6 100644 --- a/packages/@headlessui-vue/src/components/combobox/combobox.ts +++ b/packages/@headlessui-vue/src/components/combobox/combobox.ts @@ -662,9 +662,7 @@ export let ComboboxButton = defineComponent({ tabindex: '-1', 'aria-haspopup': 'listbox', 'aria-controls': dom(api.optionsRef)?.id, - 'aria-expanded': api.disabled.value - ? undefined - : api.comboboxState.value === ComboboxStates.Open, + 'aria-expanded': api.comboboxState.value === ComboboxStates.Open, 'aria-labelledby': api.labelRef.value ? [dom(api.labelRef)?.id, id].join(' ') : undefined, disabled: api.disabled.value === true ? true : undefined, onKeydown: handleKeydown, @@ -980,9 +978,7 @@ export let ComboboxInput = defineComponent({ let { id, displayValue, onChange: _onChange, ...theirProps } = props let ourProps = { 'aria-controls': api.optionsRef.value?.id, - 'aria-expanded': api.disabled.value - ? undefined - : api.comboboxState.value === ComboboxStates.Open, + 'aria-expanded': api.comboboxState.value === ComboboxStates.Open, 'aria-activedescendant': api.activeOptionIndex.value === null ? undefined diff --git a/packages/@headlessui-vue/src/components/disclosure/disclosure.ts b/packages/@headlessui-vue/src/components/disclosure/disclosure.ts index 54529f4..f7bae00 100644 --- a/packages/@headlessui-vue/src/components/disclosure/disclosure.ts +++ b/packages/@headlessui-vue/src/components/disclosure/disclosure.ts @@ -229,9 +229,7 @@ export let DisclosureButton = defineComponent({ id, ref: internalButtonRef, type: type.value, - 'aria-expanded': props.disabled - ? undefined - : api.disclosureState.value === DisclosureStates.Open, + 'aria-expanded': api.disclosureState.value === DisclosureStates.Open, 'aria-controls': dom(api.panel) ? api.panelId.value : undefined, disabled: props.disabled ? true : undefined, onClick: handleClick, diff --git a/packages/@headlessui-vue/src/components/listbox/listbox.ts b/packages/@headlessui-vue/src/components/listbox/listbox.ts index 2fb49ee..89283dc 100644 --- a/packages/@headlessui-vue/src/components/listbox/listbox.ts +++ b/packages/@headlessui-vue/src/components/listbox/listbox.ts @@ -532,9 +532,7 @@ export let ListboxButton = defineComponent({ type: type.value, 'aria-haspopup': 'listbox', 'aria-controls': dom(api.optionsRef)?.id, - 'aria-expanded': api.disabled.value - ? undefined - : api.listboxState.value === ListboxStates.Open, + 'aria-expanded': api.listboxState.value === ListboxStates.Open, 'aria-labelledby': api.labelRef.value ? [dom(api.labelRef)?.id, id].join(' ') : undefined, disabled: api.disabled.value === true ? true : undefined, onKeydown: handleKeyDown, diff --git a/packages/@headlessui-vue/src/components/menu/menu.ts b/packages/@headlessui-vue/src/components/menu/menu.ts index cad0443..719e628 100644 --- a/packages/@headlessui-vue/src/components/menu/menu.ts +++ b/packages/@headlessui-vue/src/components/menu/menu.ts @@ -320,7 +320,7 @@ export let MenuButton = defineComponent({ type: type.value, 'aria-haspopup': 'menu', 'aria-controls': dom(api.itemsRef)?.id, - 'aria-expanded': props.disabled ? undefined : api.menuState.value === MenuStates.Open, + 'aria-expanded': api.menuState.value === MenuStates.Open, onKeydown: handleKeyDown, onKeyup: handleKeyUp, onClick: handleClick, diff --git a/packages/@headlessui-vue/src/components/popover/popover.ts b/packages/@headlessui-vue/src/components/popover/popover.ts index 858e814..ce70985 100644 --- a/packages/@headlessui-vue/src/components/popover/popover.ts +++ b/packages/@headlessui-vue/src/components/popover/popover.ts @@ -438,9 +438,7 @@ export let PopoverButton = defineComponent({ ref: elementRef, id, type: type.value, - 'aria-expanded': props.disabled - ? undefined - : api.popoverState.value === PopoverStates.Open, + 'aria-expanded': api.popoverState.value === PopoverStates.Open, 'aria-controls': dom(api.panel) ? api.panelId.value : undefined, disabled: props.disabled ? true : undefined, onKeydown: handleKeyDown, diff --git a/packages/@headlessui-vue/src/test-utils/accessibility-assertions.ts b/packages/@headlessui-vue/src/test-utils/accessibility-assertions.ts index a1797fd..dba8da4 100644 --- a/packages/@headlessui-vue/src/test-utils/accessibility-assertions.ts +++ b/packages/@headlessui-vue/src/test-utils/accessibility-assertions.ts @@ -62,20 +62,12 @@ export function assertMenuButton( case MenuState.InvisibleHidden: expect(button).toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break case MenuState.InvisibleUnmounted: expect(button).not.toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break default: @@ -352,20 +344,12 @@ export function assertComboboxInput( case ComboboxState.InvisibleHidden: expect(input).toHaveAttribute('aria-controls') - if (input.hasAttribute('disabled')) { - expect(input).not.toHaveAttribute('aria-expanded') - } else { - expect(input).toHaveAttribute('aria-expanded', 'false') - } + expect(input).toHaveAttribute('aria-expanded', 'false') break case ComboboxState.InvisibleUnmounted: expect(input).not.toHaveAttribute('aria-controls') - if (input.hasAttribute('disabled')) { - expect(input).not.toHaveAttribute('aria-expanded') - } else { - expect(input).toHaveAttribute('aria-expanded', 'false') - } + expect(input).toHaveAttribute('aria-expanded', 'false') break default: @@ -458,20 +442,12 @@ export function assertComboboxButton( case ComboboxState.InvisibleHidden: expect(button).toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break case ComboboxState.InvisibleUnmounted: expect(button).not.toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break default: @@ -798,20 +774,12 @@ export function assertListboxButton( case ListboxState.InvisibleHidden: expect(button).toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break case ListboxState.InvisibleUnmounted: expect(button).not.toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break default: @@ -1100,20 +1068,12 @@ export function assertDisclosureButton( case DisclosureState.InvisibleHidden: expect(button).toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break case DisclosureState.InvisibleUnmounted: expect(button).not.toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break default: @@ -1232,20 +1192,12 @@ export function assertPopoverButton( case PopoverState.InvisibleHidden: expect(button).toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break case PopoverState.InvisibleUnmounted: expect(button).not.toHaveAttribute('aria-controls') - if (button.hasAttribute('disabled')) { - expect(button).not.toHaveAttribute('aria-expanded') - } else { - expect(button).toHaveAttribute('aria-expanded', 'false') - } + expect(button).toHaveAttribute('aria-expanded', 'false') break default: