Skip to content

Commit 4d4a6ad

Browse files
authored
feat: focus item when focusing menu (#464)
* feat: focus item when focusing menu * chore: update snapshot * feat: focus active child * fix: index > -1 * fix: use querySelecor instead
1 parent 51ad071 commit 4d4a6ad

File tree

4 files changed

+37
-11
lines changed

4 files changed

+37
-11
lines changed

src/Menu.tsx

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import useAccessibility from './hooks/useAccessibility';
2727
import useUUID from './hooks/useUUID';
2828
import { PathRegisterContext, PathUserContext } from './context/PathContext';
2929
import useKeyRecords, { OVERFLOW_KEY } from './hooks/useKeyRecords';
30-
import { IdContext } from './context/IdContext';
30+
import { getMenuId, IdContext } from './context/IdContext';
3131
import PrivateContext from './context/PrivateContext';
3232
import { useImperativeHandle } from 'react';
3333

@@ -235,13 +235,6 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
235235

236236
const containerRef = React.useRef<HTMLUListElement>();
237237

238-
useImperativeHandle(ref, () => ({
239-
list: containerRef.current,
240-
focus: (options?: FocusOptions) => {
241-
containerRef.current?.focus(options);
242-
},
243-
}));
244-
245238
const uuid = useUUID(id);
246239

247240
const isRtl = direction === 'rtl';
@@ -360,6 +353,21 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
360353
setMergedActiveKey(undefined);
361354
});
362355

356+
useImperativeHandle(ref, () => ({
357+
list: containerRef.current,
358+
focus: options => {
359+
const shouldFocusKey =
360+
mergedActiveKey ?? childList.find(node => !node.props.disabled)?.key;
361+
if (shouldFocusKey) {
362+
containerRef.current
363+
?.querySelector<HTMLLIElement>(
364+
`li[data-menu-id='${getMenuId(uuid, shouldFocusKey as string)}']`,
365+
)
366+
?.focus?.(options);
367+
}
368+
},
369+
}));
370+
363371
// ======================== Select ========================
364372
// >>>>> Select keys
365373
const [mergedSelectKeys, setMergedSelectKeys] = useMergedState(

src/interface.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ export type SelectEventHandler = (info: SelectInfo) => void;
120120
export type MenuClickEventHandler = (info: MenuInfo) => void;
121121

122122
export type MenuRef = {
123+
/**
124+
* Focus active child if any, or the first child which is not disabled will be focused.
125+
* @param options
126+
*/
123127
focus: (options?: FocusOptions) => void;
124128
list: HTMLUListElement;
125129
};

tests/Menu.spec.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -663,14 +663,28 @@ describe('Menu', () => {
663663
const menuRef = React.createRef();
664664
const wrapper = mount(
665665
<Menu ref={menuRef}>
666+
<SubMenu key="bamboo" title="Disabled" disabled>
667+
<MenuItem key="light">Disabled child</MenuItem>
668+
</SubMenu>
666669
<MenuItem key="light">Light</MenuItem>
667670
</Menu>,
668671
);
669672
menuRef.current?.focus();
670673

671-
expect(document.activeElement).toBe(
672-
wrapper.find('ul').first().getDOMNode(),
674+
expect(document.activeElement).toBe(wrapper.find('li').last().getDOMNode());
675+
});
676+
677+
it('should focus active item through ref', () => {
678+
const menuRef = React.createRef();
679+
const wrapper = mount(
680+
<Menu ref={menuRef} activeKey="cat">
681+
<MenuItem key="light">Light</MenuItem>
682+
<MenuItem key="cat">Cat</MenuItem>
683+
</Menu>,
673684
);
685+
menuRef.current?.focus();
686+
687+
expect(document.activeElement).toBe(wrapper.find('li').last().getDOMNode());
674688
});
675689
});
676690
/* eslint-enable */

tests/__snapshots__/SubMenu.spec.js.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Array [
8484
<div>
8585
<div
8686
class="rc-menu-submenu rc-menu-submenu-popup custom-className"
87-
style="opacity: 0; pointer-events: none;"
87+
style="opacity: 0;"
8888
>
8989
<ul
9090
class="rc-menu rc-menu-sub rc-menu-vertical"

0 commit comments

Comments
 (0)