Skip to content

Commit 4a56286

Browse files
authored
fix(Menu): show checkboxes for selected items with ContextualHelpTrigger isUnavailable={false} (#8921)
* fix selection state in Menu items with ContextualHelpTrigger and isUnavailable={false} * cleanup test
1 parent 4a7d563 commit 4a56286

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

packages/@react-spectrum/menu/src/MenuItem.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ export function MenuItem<T>(props: MenuItemProps<T>): JSX.Element {
6464
}
6565

6666
let isDisabled = state.disabledKeys.has(key);
67-
let isSelectable = !isSubmenuTrigger && state.selectionManager.selectionMode !== 'none';
67+
let isContextualHelpTrigger = isSubmenuTrigger && isUnavailable !== undefined;
68+
let isSelectable = (
69+
(isContextualHelpTrigger ? !isUnavailable : !isSubmenuTrigger) &&
70+
state.selectionManager.selectionMode !== 'none'
71+
);
6872
let isSelected = isSelectable && state.selectionManager.isSelected(key);
6973
let itemref = useRef<any>(null);
7074
let ref = useObjectRef(useMemo(() => mergeRefs(itemref, triggerRef), [itemref, triggerRef]));

packages/@react-spectrum/menu/stories/MenuTrigger.stories.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,41 @@ export let MenuItemUnavailable: StoryObj<typeof Menu> = {
786786
)
787787
};
788788

789+
export let MenuItemUnavailableWithSelection: StoryObj<typeof Menu> = {
790+
render: () => render(
791+
<Menu selectionMode="multiple">
792+
<Item key="1">One</Item>
793+
<ContextualHelpTrigger isUnavailable>
794+
<Item key="foo">Two</Item>
795+
<Dialog>
796+
<Heading>hello</Heading>
797+
<Content>Is it me you're looking for?</Content>
798+
</Dialog>
799+
</ContextualHelpTrigger>
800+
<ContextualHelpTrigger isUnavailable={false}>
801+
<Item key="baz">Two point five</Item>
802+
<Dialog>
803+
<Heading>hello</Heading>
804+
<Content>Is it me you're looking for?</Content>
805+
</Dialog>
806+
</ContextualHelpTrigger>
807+
<Item key="3">Three</Item>
808+
<ContextualHelpTrigger isUnavailable={false}>
809+
<Item key="bar" textValue="Four">
810+
<Text>Four</Text>
811+
<Text slot={'description'}>Shut the door</Text>
812+
</Item>
813+
<Dialog>
814+
<Heading>hello</Heading>
815+
<Content>Is it me you're looking for?</Content>
816+
<Footer><Link>Learn more</Link></Footer>
817+
</Dialog>
818+
</ContextualHelpTrigger>
819+
<Item key="5">Five</Item>
820+
</Menu>
821+
)
822+
};
823+
789824
export let MenuItemUnavailableDynamic: StoryObj<typeof Menu> = {
790825
render: () => render(
791826
<Menu items={flatMenu} onAction={action('onAction')}>

packages/@react-spectrum/menu/test/MenuTrigger.test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,42 @@ describe('MenuTrigger', function () {
617617
expect(tree.queryByRole('dialog')).toBeNull();
618618
});
619619

620+
it('shows selection state for available ContextualHelpTrigger items', async function () {
621+
render(
622+
<Provider theme={theme}>
623+
<MenuTrigger defaultOpen>
624+
<ActionButton>Menu</ActionButton>
625+
<Menu selectionMode="single">
626+
<Item key="1">One</Item>
627+
<ContextualHelpTrigger>
628+
<Item key="foo" textValue="Hello">
629+
<Text>Hello</Text>
630+
<Text slot="description">Is it me you're looking for?</Text>
631+
</Item>
632+
<Dialog>
633+
<Heading>Lionel Richie says:</Heading>
634+
<Content>I can see it in your eyes</Content>
635+
</Dialog>
636+
</ContextualHelpTrigger>
637+
</Menu>
638+
</MenuTrigger>
639+
</Provider>
640+
);
641+
642+
act(() => {jest.runAllTimers();});
643+
644+
let menu = screen.getByRole('menu');
645+
let availableItem = within(menu).getByRole('menuitemradio', {name: 'Hello'});
646+
647+
expect(availableItem).toBeVisible();
648+
expect(availableItem).toHaveAttribute('aria-checked', 'false');
649+
fireEvent.click(availableItem);
650+
act(() => {jest.runAllTimers();});
651+
652+
expect(availableItem).toHaveAttribute('aria-checked', 'true');
653+
expect(availableItem).not.toHaveAttribute('aria-haspopup', 'dialog');
654+
});
655+
620656
it('can open a sub dialog with keyboard', async function () {
621657
renderTree();
622658
let menu = await openMenu();

0 commit comments

Comments
 (0)