Skip to content

Commit

Permalink
Don’t override explicit disabled prop for components inside `<MenuI…
Browse files Browse the repository at this point in the history
…tem>` (#2929)

* Don’t override explicit disabled prop inside `<MenuItem>`

* Update changelog
  • Loading branch information
thecrypticace authored and RobinMalfait committed Apr 15, 2024
1 parent 39210df commit 46a9b32
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 4 deletions.
41 changes: 41 additions & 0 deletions packages/@headlessui-react/src/components/menu/menu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,47 @@ describe('Rendering', () => {
assertMenu({ state: MenuState.InvisibleUnmounted })
})
)

it('should not override an explicit disabled prop on MenuItems child', async () => {
render(
<Menu>
<Menu.Button>Trigger</Menu.Button>
<Menu.Items>
<Menu.Item>{({ disabled }) => <button disabled={disabled}>Item A</button>}</Menu.Item>
<Menu.Item>{({ disabled }) => <button disabled={disabled}>Item B</button>}</Menu.Item>
<Menu.Item disabled>
{({ disabled }) => <button disabled={disabled}>Item C</button>}
</Menu.Item>
</Menu.Items>
</Menu>
)

assertMenuButton({
state: MenuState.InvisibleUnmounted,
})
assertMenu({ state: MenuState.InvisibleUnmounted })

getMenuButton()?.focus()

await press(Keys.Enter)

assertMenuButton({
state: MenuState.Visible,
})
assertMenu({ state: MenuState.Visible })
assertMenuItem(getMenuItems()[0], {
tag: 'button',
attributes: {},
})
assertMenuItem(getMenuItems()[1], {
tag: 'button',
attributes: {},
})
assertMenuItem(getMenuItems()[2], {
tag: 'button',
attributes: { disabled: '' },
})
})
})

it('should guarantee the order of DOM nodes when performing actions', async () => {
Expand Down
1 change: 1 addition & 0 deletions packages/@headlessui-vue/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Expose `disabled` state on `<Tab />` component ([#2918](https://github.com/tailwindlabs/headlessui/pull/2918))
- Prevent default behaviour when clicking outside of a `DialogPanel` ([#2919](https://github.com/tailwindlabs/headlessui/pull/2919))
- Don’t override explicit `disabled` prop for components inside `<MenuItem>` ([#2929](https://github.com/tailwindlabs/headlessui/pull/2929))

## [1.7.19] - 2024-02-07

Expand Down
48 changes: 47 additions & 1 deletion packages/@headlessui-vue/src/components/menu/menu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,53 @@ describe('Rendering', () => {
})
})

it('should not override an explicit disabled prop on MenuItems child', async () => {
renderTemplate(jsx`
<Menu>
<MenuButton>Trigger</MenuButton>
<MenuItems>
<MenuItem v-slot="{ active, disabled }">
<button :data-active="active" :disabled="disabled">Item A</button>
</MenuItem>
<MenuItem v-slot="{ active, disabled }">
<button :data-active="active" :disabled="disabled">Item B</button>
</MenuItem>
<MenuItem disabled v-slot="{ active, disabled }">
<button :data-active="active" :disabled="disabled">Item C</button>
</MenuItem>
</MenuItems>
</Menu>
`)

assertMenuButton({
state: MenuState.InvisibleUnmounted,
attributes: { id: 'headlessui-menu-button-1' },
})
assertMenu({ state: MenuState.InvisibleUnmounted })

getMenuButton()?.focus()

await press(Keys.Enter)

assertMenuButton({
state: MenuState.Visible,
attributes: { id: 'headlessui-menu-button-1' },
})
assertMenu({ state: MenuState.Visible })
assertMenuItem(getMenuItems()[0], {
tag: 'button',
attributes: { 'data-active': 'true' },
})
assertMenuItem(getMenuItems()[1], {
tag: 'button',
attributes: { 'data-active': 'false' },
})
assertMenuItem(getMenuItems()[2], {
tag: 'button',
attributes: { 'data-active': 'false', disabled: '' },
})
})

it('should yell when we render a MenuItem using a template `as` prop that contains multiple children', async () => {
expect.hasAssertions()

Expand All @@ -712,7 +759,6 @@ describe('Rendering', () => {
'The current component <MenuItem /> is rendering a "template".',
'However we need to passthrough the following props:',
' - aria-disabled',
' - disabled',
' - id',
' - onClick',
' - onFocus',
Expand Down
4 changes: 1 addition & 3 deletions packages/@headlessui-vue/src/components/menu/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,16 +566,14 @@ export let MenuItem = defineComponent({
}

return () => {
let { disabled } = props
let { disabled, ...theirProps } = props
let slot = { active: active.value, disabled, close: api.closeMenu }
let { ...theirProps } = props
let ourProps = {
id,
ref: internalItemRef,
role: 'menuitem',
tabIndex: disabled === true ? undefined : -1,
'aria-disabled': disabled === true ? true : undefined,
disabled: undefined, // Never forward the `disabled` prop
onClick: handleClick,
onFocus: handleFocus,
onPointerenter: handleEnter,
Expand Down

0 comments on commit 46a9b32

Please sign in to comment.