diff --git a/packages/@headlessui-react/src/components/menu/menu.test.tsx b/packages/@headlessui-react/src/components/menu/menu.test.tsx index 61dba9ff76..2a26ef11aa 100644 --- a/packages/@headlessui-react/src/components/menu/menu.test.tsx +++ b/packages/@headlessui-react/src/components/menu/menu.test.tsx @@ -448,6 +448,47 @@ describe('Rendering', () => { assertMenu({ state: MenuState.InvisibleUnmounted }) }) ) + + it('should not override an explicit disabled prop on MenuItems child', async () => { + render( + + Trigger + + {({ disabled }) => } + {({ disabled }) => } + + {({ disabled }) => } + + + + ) + + 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: { 'data-focus': '' }, + }) + 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 () => { diff --git a/packages/@headlessui-vue/CHANGELOG.md b/packages/@headlessui-vue/CHANGELOG.md index 278a69d020..8c5d8fc19d 100644 --- a/packages/@headlessui-vue/CHANGELOG.md +++ b/packages/@headlessui-vue/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Expose `disabled` state on `` 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 `` ([#2929](https://github.com/tailwindlabs/headlessui/pull/2929)) ## [1.7.17] - 2024-01-08 diff --git a/packages/@headlessui-vue/src/components/menu/menu.test.tsx b/packages/@headlessui-vue/src/components/menu/menu.test.tsx index 9fc698e9da..314ccdb44f 100644 --- a/packages/@headlessui-vue/src/components/menu/menu.test.tsx +++ b/packages/@headlessui-vue/src/components/menu/menu.test.tsx @@ -686,6 +686,53 @@ describe('Rendering', () => { }) }) + it('should not override an explicit disabled prop on MenuItems child', async () => { + renderTemplate(jsx` + + Trigger + + + + + + + + + + + + + `) + + 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() @@ -712,7 +759,6 @@ describe('Rendering', () => { 'The current component is rendering a "template".', 'However we need to passthrough the following props:', ' - aria-disabled', - ' - disabled', ' - id', ' - onClick', ' - onFocus', diff --git a/packages/@headlessui-vue/src/components/menu/menu.ts b/packages/@headlessui-vue/src/components/menu/menu.ts index 39fc6ddee2..e6fa936b90 100644 --- a/packages/@headlessui-vue/src/components/menu/menu.ts +++ b/packages/@headlessui-vue/src/components/menu/menu.ts @@ -563,16 +563,14 @@ export let MenuItem = defineComponent({ } return () => { - let { disabled } = props + let { id, disabled, ...theirProps } = props let slot = { active: active.value, disabled, close: api.closeMenu } - let { id, ...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,