From 0c13ce1a11aa3d60596a5ec555965b892107b369 Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Thu, 5 May 2022 17:58:15 +0800 Subject: [PATCH 1/5] feat: focus item when focusing menu --- src/Menu.tsx | 9 ++++++++- tests/Menu.spec.js | 7 ++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Menu.tsx b/src/Menu.tsx index 37bcb9c0..25d27ac4 100644 --- a/src/Menu.tsx +++ b/src/Menu.tsx @@ -238,7 +238,14 @@ const Menu = React.forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ list: containerRef.current, focus: (options?: FocusOptions) => { - containerRef.current?.focus(options); + const shouldFocusIndex = childList.findIndex( + node => !node.props.disabled, + ); + if (shouldFocusIndex > 0) { + containerRef.current + ?.querySelectorAll('li') + [shouldFocusIndex]?.focus(options); + } }, })); diff --git a/tests/Menu.spec.js b/tests/Menu.spec.js index d5e2d047..6d273125 100644 --- a/tests/Menu.spec.js +++ b/tests/Menu.spec.js @@ -663,14 +663,15 @@ describe('Menu', () => { const menuRef = React.createRef(); const wrapper = mount( + + Disabled child + Light , ); menuRef.current?.focus(); - expect(document.activeElement).toBe( - wrapper.find('ul').first().getDOMNode(), - ); + expect(document.activeElement).toBe(wrapper.find('li').last().getDOMNode()); }); }); /* eslint-enable */ From 618c8c3da6bd225c29b89c7b0508610ee4d1758f Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Thu, 5 May 2022 18:17:45 +0800 Subject: [PATCH 2/5] chore: update snapshot --- tests/__snapshots__/SubMenu.spec.js.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/__snapshots__/SubMenu.spec.js.snap b/tests/__snapshots__/SubMenu.spec.js.snap index 11f7aaed..ffa2739d 100644 --- a/tests/__snapshots__/SubMenu.spec.js.snap +++ b/tests/__snapshots__/SubMenu.spec.js.snap @@ -84,7 +84,7 @@ Array [
    Date: Fri, 6 May 2022 16:08:14 +0800 Subject: [PATCH 3/5] feat: focus active child --- src/Menu.tsx | 33 +++++++++++++++++++-------------- tests/Menu.spec.js | 13 +++++++++++++ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/Menu.tsx b/src/Menu.tsx index 25d27ac4..9e561970 100644 --- a/src/Menu.tsx +++ b/src/Menu.tsx @@ -235,20 +235,6 @@ const Menu = React.forwardRef((props, ref) => { const containerRef = React.useRef(); - useImperativeHandle(ref, () => ({ - list: containerRef.current, - focus: (options?: FocusOptions) => { - const shouldFocusIndex = childList.findIndex( - node => !node.props.disabled, - ); - if (shouldFocusIndex > 0) { - containerRef.current - ?.querySelectorAll('li') - [shouldFocusIndex]?.focus(options); - } - }, - })); - const uuid = useUUID(id); const isRtl = direction === 'rtl'; @@ -367,6 +353,25 @@ const Menu = React.forwardRef((props, ref) => { setMergedActiveKey(undefined); }); + useImperativeHandle(ref, () => ({ + list: containerRef.current, + focus: options => { + let shouldFocusIndex = -1; + if (mergedActiveKey) { + shouldFocusIndex = childList.findIndex( + node => node.key === mergedActiveKey, + ); + } else { + shouldFocusIndex = childList.findIndex(node => !node.props.disabled); + } + if (shouldFocusIndex > 0) { + containerRef.current + ?.querySelectorAll('li') + [shouldFocusIndex]?.focus(options); + } + }, + })); + // ======================== Select ======================== // >>>>> Select keys const [mergedSelectKeys, setMergedSelectKeys] = useMergedState( diff --git a/tests/Menu.spec.js b/tests/Menu.spec.js index 6d273125..eb45d2df 100644 --- a/tests/Menu.spec.js +++ b/tests/Menu.spec.js @@ -673,5 +673,18 @@ describe('Menu', () => { expect(document.activeElement).toBe(wrapper.find('li').last().getDOMNode()); }); + + it('should focus active item through ref', () => { + const menuRef = React.createRef(); + const wrapper = mount( + + Light + Cat + , + ); + menuRef.current?.focus(); + + expect(document.activeElement).toBe(wrapper.find('li').last().getDOMNode()); + }); }); /* eslint-enable */ From 32a9e7dbd1302b60ad8a1cc1cce1ab6de4916f2f Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Fri, 6 May 2022 16:13:26 +0800 Subject: [PATCH 4/5] fix: index > -1 --- src/Menu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Menu.tsx b/src/Menu.tsx index 9e561970..df439cd8 100644 --- a/src/Menu.tsx +++ b/src/Menu.tsx @@ -364,7 +364,7 @@ const Menu = React.forwardRef((props, ref) => { } else { shouldFocusIndex = childList.findIndex(node => !node.props.disabled); } - if (shouldFocusIndex > 0) { + if (shouldFocusIndex > -1) { containerRef.current ?.querySelectorAll('li') [shouldFocusIndex]?.focus(options); From 8df0ee3577f3fd970879ebf429727b10610078e3 Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Fri, 6 May 2022 16:26:12 +0800 Subject: [PATCH 5/5] fix: use querySelecor instead --- src/Menu.tsx | 20 ++++++++------------ src/interface.ts | 4 ++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Menu.tsx b/src/Menu.tsx index df439cd8..2f1bf9fb 100644 --- a/src/Menu.tsx +++ b/src/Menu.tsx @@ -27,7 +27,7 @@ import useAccessibility from './hooks/useAccessibility'; import useUUID from './hooks/useUUID'; import { PathRegisterContext, PathUserContext } from './context/PathContext'; import useKeyRecords, { OVERFLOW_KEY } from './hooks/useKeyRecords'; -import { IdContext } from './context/IdContext'; +import { getMenuId, IdContext } from './context/IdContext'; import PrivateContext from './context/PrivateContext'; import { useImperativeHandle } from 'react'; @@ -356,18 +356,14 @@ const Menu = React.forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ list: containerRef.current, focus: options => { - let shouldFocusIndex = -1; - if (mergedActiveKey) { - shouldFocusIndex = childList.findIndex( - node => node.key === mergedActiveKey, - ); - } else { - shouldFocusIndex = childList.findIndex(node => !node.props.disabled); - } - if (shouldFocusIndex > -1) { + const shouldFocusKey = + mergedActiveKey ?? childList.find(node => !node.props.disabled)?.key; + if (shouldFocusKey) { containerRef.current - ?.querySelectorAll('li') - [shouldFocusIndex]?.focus(options); + ?.querySelector( + `li[data-menu-id='${getMenuId(uuid, shouldFocusKey as string)}']`, + ) + ?.focus?.(options); } }, })); diff --git a/src/interface.ts b/src/interface.ts index ef74ae8a..2158e64c 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -120,6 +120,10 @@ export type SelectEventHandler = (info: SelectInfo) => void; export type MenuClickEventHandler = (info: MenuInfo) => void; export type MenuRef = { + /** + * Focus active child if any, or the first child which is not disabled will be focused. + * @param options + */ focus: (options?: FocusOptions) => void; list: HTMLUListElement; };