From 9c3b4e8ea81b1172157b8ac92f561c4b8628c0d4 Mon Sep 17 00:00:00 2001 From: mainframev Date: Fri, 13 Dec 2024 10:30:35 +0100 Subject: [PATCH] fix(react-keytips): create alias nodes for persisted keytips --- .../src/components/Keytip/Keytip.types.ts | 6 +- .../src/components/Keytips/useKeytips.tsx | 61 ++++++++----------- .../src/components/Keytips/useKeytipsState.ts | 10 ++- packages/react-keytips/src/constants.ts | 5 -- .../src/hooks/useEventService.ts | 16 ++--- .../react-keytips/src/hooks/useHotkeys.ts | 9 +-- .../react-keytips/src/hooks/useKeytipRef.ts | 32 ++++------ .../react-keytips/src/hooks/useTree.test.ts | 2 +- packages/react-keytips/src/hooks/useTree.ts | 25 +++++--- packages/react-keytips/src/index.ts | 2 + .../src/utilities/createAliasNode.ts | 29 +++++++++ .../react-keytips/src/utilities/createNode.ts | 20 +++--- packages/react-keytips/src/utilities/index.ts | 1 + .../react-keytips/stories/Default.stories.tsx | 4 +- .../react-keytips/stories/OverflowMenu.md | 18 +++--- .../stories/OverflowMenu.stories.tsx | 18 +++--- 16 files changed, 134 insertions(+), 124 deletions(-) create mode 100644 packages/react-keytips/src/utilities/createAliasNode.ts diff --git a/packages/react-keytips/src/components/Keytip/Keytip.types.ts b/packages/react-keytips/src/components/Keytip/Keytip.types.ts index 920831ab..8789c5cf 100644 --- a/packages/react-keytips/src/components/Keytip/Keytip.types.ts +++ b/packages/react-keytips/src/components/Keytip/Keytip.types.ts @@ -60,10 +60,10 @@ export type KeytipProps = ComponentProps & { /** * Whether this Keytip can be accessed at the root level. */ - shortcut?: boolean; + isShortcut?: boolean; /** - * Whether or not this Keytip belongs to a component that has a menu Keytip mode will stay on when a menu is opened, - * even if the items in that menu have no keytips. + * Whether or not this Keytip belongs to a component that has a menu. Keytip mode will stay on when a menu is opened, + * even if the items in that menu have no keytips. If this is */ hasMenu?: boolean; }; diff --git a/packages/react-keytips/src/components/Keytips/useKeytips.tsx b/packages/react-keytips/src/components/Keytips/useKeytips.tsx index 22bec7fd..cb021c13 100644 --- a/packages/react-keytips/src/components/Keytips/useKeytips.tsx +++ b/packages/react-keytips/src/components/Keytips/useKeytips.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { getIntrinsicElementProps, slot, - useIsomorphicLayoutEffect, useFluent, useTimeout, } from '@fluentui/react-components'; @@ -63,7 +62,7 @@ export const useKeytips_unstable = (props: KeytipsProps): KeytipsState => { }, [state.inKeytipMode, onEnterKeytipsMode] ); - // + const handleExitKeytipMode = React.useCallback( (ev: KeyboardEvent) => { if (state.inKeytipMode) { @@ -81,6 +80,7 @@ export const useKeytips_unstable = (props: KeytipsProps): KeytipsState => { (ev: KeyboardEvent) => { if (!state.inKeytipMode) return; const currentKeytip = tree.currentKeytip.current; + if (currentKeytip && currentKeytip.target) { currentKeytip?.onReturn?.(ev, { event: ev, @@ -114,21 +114,14 @@ export const useKeytips_unstable = (props: KeytipsProps): KeytipsState => { invokeEvent ); - useIsomorphicLayoutEffect(() => { + React.useEffect(() => { const handleKeytipAdded = (keytip: KeytipWithId) => { tree.addNode(keytip); - if (keytip.isShortcut) { - dispatch({ - type: ACTIONS.ADD_SHORTCUT, - shortcut: keytip, - }); - } else { - dispatch({ - type: ACTIONS.ADD_KEYTIP, - keytip, - }); - } + dispatch({ + type: ACTIONS.ADD_KEYTIP, + keytip, + }); if (state.inKeytipMode && tree.isCurrentKeytipParent(keytip)) { showKeytips(tree.getChildren()); @@ -138,11 +131,7 @@ export const useKeytips_unstable = (props: KeytipsProps): KeytipsState => { const handleKeytipRemoved = (keytip: KeytipWithId) => { tree.removeNode(keytip.uniqueId); - if (keytip.isShortcut) { - dispatch({ type: ACTIONS.REMOVE_SHORTCUT, id: keytip.uniqueId }); - } else { - dispatch({ type: ACTIONS.REMOVE_KEYTIP, id: keytip.uniqueId }); - } + dispatch({ type: ACTIONS.REMOVE_KEYTIP, id: keytip.uniqueId }); }; const handleKeytipUpdated = (keytip: KeytipWithId) => { @@ -152,17 +141,15 @@ export const useKeytips_unstable = (props: KeytipsProps): KeytipsState => { }; subscribe(EVENTS.KEYTIP_ADDED, handleKeytipAdded); - subscribe(EVENTS.SHORTCUT_ADDED, handleKeytipAdded); subscribe(EVENTS.KEYTIP_UPDATED, handleKeytipUpdated); subscribe(EVENTS.KEYTIP_REMOVED, handleKeytipRemoved); - subscribe(EVENTS.SHORTCUT_REMOVED, handleKeytipRemoved); return () => { reset(); }; }, [state.inKeytipMode]); - useIsomorphicLayoutEffect(() => { + React.useEffect(() => { const controller = new AbortController(); const { signal } = controller; @@ -200,6 +187,7 @@ export const useKeytips_unstable = (props: KeytipsProps): KeytipsState => { dispatchEvent(EVENTS.KEYTIP_EXECUTED, node); } + const currentChildren = tree.getChildren(node); const shouldExitKeytipMode = currentChildren.length === 0 && !node.dynamic; @@ -219,13 +207,11 @@ export const useKeytips_unstable = (props: KeytipsProps): KeytipsState => { // executes keytip that was triggered via shortcut const handleShortcutExecution = React.useCallback( async (ev: KeyboardEvent, node: KeytipTreeNode) => { - const { dependentKeys, keySequences } = node; + const { keySequences } = node; if (!targetDocument) return; - const fullPath = [...dependentKeys, ...node.keySequences].reduce< - string[] - >((acc, key, idx) => { + const fullPath = keySequences.reduce((acc, key, idx) => { if (idx === 0) acc.push(sequencesToID([key])); else acc.push( @@ -234,7 +220,7 @@ export const useKeytips_unstable = (props: KeytipsProps): KeytipsState => { return acc; }, []); - const nodeId = sequencesToID([...dependentKeys, ...keySequences]); + const nodeId = sequencesToID(keySequences); const treeNode = tree.getNode(nodeId); // if the node has menu, trigger overflow keytip and current keytip to show the menu @@ -286,7 +272,7 @@ export const useKeytips_unstable = (props: KeytipsProps): KeytipsState => { } }, []); - useIsomorphicLayoutEffect(() => { + React.useEffect(() => { if (!targetDocument) return; const handleInvokeEvent = (ev: KeyboardEvent) => { @@ -330,15 +316,16 @@ export const useKeytips_unstable = (props: KeytipsProps): KeytipsState => { )); - const hiddenKeytips = Object.values(state.keytips).map(({ keySequences }) => ( - - {keySequences.join(', ')} - - )); + const hiddenKeytips = Object.values(state.keytips).map( + ({ keySequences, uniqueId }) => { + const id = sequencesToID(keySequences); + return ( + + {keySequences.join(', ')} + + ); + } + ); return { components: { diff --git a/packages/react-keytips/src/components/Keytips/useKeytipsState.ts b/packages/react-keytips/src/components/Keytips/useKeytipsState.ts index 0a29b1fc..0a379962 100644 --- a/packages/react-keytips/src/components/Keytips/useKeytipsState.ts +++ b/packages/react-keytips/src/components/Keytips/useKeytipsState.ts @@ -3,7 +3,13 @@ import type { KeytipProps, KeytipWithId } from '../Keytip'; import { isTargetVisible, omit } from '../../utilities'; import { ACTIONS } from '../../constants'; -type Keytips = Record; +type Keytips = Record< + string, + KeytipProps & { + visibleInternal?: boolean; + uniqueId: string; + } +>; type KeytipsState = { inKeytipMode: boolean; @@ -17,8 +23,6 @@ type KeytipsAction = | { type: typeof ACTIONS.ADD_KEYTIP; keytip: KeytipWithId } | { type: typeof ACTIONS.UPDATE_KEYTIP; keytip: KeytipWithId } | { type: typeof ACTIONS.REMOVE_KEYTIP; id: string } - | { type: typeof ACTIONS.ADD_SHORTCUT; shortcut: KeytipWithId } - | { type: typeof ACTIONS.REMOVE_SHORTCUT; id: string } | { type: typeof ACTIONS.SET_VISIBLE_KEYTIPS; ids: string[]; diff --git a/packages/react-keytips/src/constants.ts b/packages/react-keytips/src/constants.ts index 2563c9f5..260b6839 100644 --- a/packages/react-keytips/src/constants.ts +++ b/packages/react-keytips/src/constants.ts @@ -2,7 +2,6 @@ import { ArrowLeft, Enter, Space, - Tab, ArrowUp, ArrowDown, ArrowRight, @@ -21,8 +20,6 @@ export const EVENTS = { KEYTIP_REMOVED: 'fui-keytip-removed', KEYTIP_UPDATED: 'fui-keytip-updated', KEYTIP_EXECUTED: 'fui-keytip-executed', - SHORTCUT_ADDED: 'fui-shortcut-added', - SHORTCUT_REMOVED: 'fui-shortcut-removed', SHORTCUT_EXECUTED: 'fui-shortcut-executed', ENTER_KEYTIP_MODE: 'fui-enter-keytip-mode', EXIT_KEYTIP_MODE: 'fui-exit-keytip-mode', @@ -51,9 +48,7 @@ export const ACTIONS = { ENTER_KEYTIP_MODE: 'ENTER_KEYTIP_MODE', EXIT_KEYTIP_MODE: 'EXIT_KEYTIP_MODE', ADD_KEYTIP: 'ADD_KEYTIP', - ADD_SHORTCUT: 'ADD_SHORTCUT', REMOVE_KEYTIP: 'REMOVE_KEYTIP', - REMOVE_SHORTCUT: 'REMOVE_SHORTCUT', UPDATE_KEYTIP: 'UPDATE_KEYTIP', SET_VISIBLE_KEYTIPS: 'SET_VISIBLE_KEYTIPS', SET_SEQUENCE: 'SET_SEQUENCE', diff --git a/packages/react-keytips/src/hooks/useEventService.ts b/packages/react-keytips/src/hooks/useEventService.ts index bed9c327..2a903a7f 100644 --- a/packages/react-keytips/src/hooks/useEventService.ts +++ b/packages/react-keytips/src/hooks/useEventService.ts @@ -1,4 +1,4 @@ -import { useCallback, useRef, useEffect } from 'react'; +import * as React from 'react'; import { useFluent } from '@fluentui/react-components'; import { EVENTS } from '../constants'; import type { KeytipWithId } from '../components/Keytip'; @@ -13,8 +13,6 @@ type PayloadDefinition = { [EVENTS.KEYTIP_ADDED]: KeytipWithId; [EVENTS.KEYTIP_REMOVED]: KeytipWithId; [EVENTS.KEYTIP_EXECUTED]: KeytipTreeNode; - [EVENTS.SHORTCUT_ADDED]: KeytipWithId; - [EVENTS.SHORTCUT_REMOVED]: KeytipWithId; [EVENTS.SHORTCUT_EXECUTED]: KeytipTreeNode; }; @@ -35,9 +33,11 @@ function createEventHandler( export function useEventService() { const { targetDocument } = useFluent(); - const controller = useRef(new AbortController()); + const controller = React.useRef( + new AbortController() + ); - const dispatch = useCallback( + const dispatch = React.useCallback( (eventName: T, payload?: PayloadDefinition[T]) => { const event = payload ? new CustomEvent(eventName, { detail: payload }) @@ -47,7 +47,7 @@ export function useEventService() { [targetDocument] ); - const subscribe = useCallback( + const subscribe = React.useCallback( ( event: T, handler: (payload: PayloadDefinition[T]) => void @@ -69,14 +69,14 @@ export function useEventService() { [targetDocument] ); - const reset = useCallback(() => { + const reset = React.useCallback(() => { if (controller.current) { controller.current.abort(); controller.current = null; } }, []); - useEffect(() => { + React.useEffect(() => { return () => { reset(); }; diff --git a/packages/react-keytips/src/hooks/useHotkeys.ts b/packages/react-keytips/src/hooks/useHotkeys.ts index e6b31533..bc047c23 100644 --- a/packages/react-keytips/src/hooks/useHotkeys.ts +++ b/packages/react-keytips/src/hooks/useHotkeys.ts @@ -1,10 +1,5 @@ import * as React from 'react'; - -import { - useIsomorphicLayoutEffect, - useFluent, - useTimeout, -} from '@fluentui/react-components'; +import { useFluent, useTimeout } from '@fluentui/react-components'; import { KeytipsProps } from '../components/Keytips/Keytips.types'; type Options = { @@ -73,7 +68,7 @@ export const useHotkeys = ( const doc = target ?? targetDocument; const activeKeys = React.useRef>(new Set()); - useIsomorphicLayoutEffect(() => { + React.useEffect(() => { const handleInvokeEvent = (ev: KeyboardEvent) => { hotkeys.forEach( ([hotkey, handler, options = { preventDefault: true }]) => { diff --git a/packages/react-keytips/src/hooks/useKeytipRef.ts b/packages/react-keytips/src/hooks/useKeytipRef.ts index 6935aa12..2601e7b1 100644 --- a/packages/react-keytips/src/hooks/useKeytipRef.ts +++ b/packages/react-keytips/src/hooks/useKeytipRef.ts @@ -11,19 +11,22 @@ const isEqualArray = (a: string[], b: string[]) => { export const useKeytipRef = < T extends HTMLElement = HTMLButtonElement | HTMLAnchorElement ->( - keytip: Omit -): React.Dispatch> => { - const ktpId = React.useId(); - const shortcutId = React.useId(); +>({ + ...keytip +}: KeytipProps): React.Dispatch> => { const [node, setNode] = React.useState(null); const { dispatch } = useEventService(); + const uniqueId = React.useId(); + const keySequences = keytip.keySequences.map((k) => k.toLowerCase()); + const id = sequencesToID(keySequences); + const ktp = React.useMemo( () => ({ ...keytip, - uniqueId: ktpId, - id: sequencesToID(keytip.keySequences), + id, + uniqueId, + keySequences, positioning: { target: node, ...keytip.positioning, @@ -32,18 +35,7 @@ export const useKeytipRef = < [keytip, node] ); - const shortcut = React.useMemo( - () => ({ - uniqueId: shortcutId, - dependentKeys: keytip.keySequences.slice(0, -1), - keySequences: keytip.keySequences.slice(-1), - isShortcut: true, - content: '', - }), - [keytip] - ); - - const prevKeytip = usePrevious(ktp); + const prevKeytip = usePrevious(keytip); // this will run on every render, in order to update the keytip if the keySequences change React.useEffect(() => { @@ -56,11 +48,9 @@ export const useKeytipRef = < React.useEffect(() => { dispatch(EVENTS.KEYTIP_ADDED, ktp); - if (ktp.shortcut) dispatch(EVENTS.SHORTCUT_ADDED, shortcut); return () => { dispatch(EVENTS.KEYTIP_REMOVED, ktp); - if (ktp.shortcut) dispatch(EVENTS.SHORTCUT_REMOVED, shortcut); }; }, [node]); diff --git a/packages/react-keytips/src/hooks/useTree.test.ts b/packages/react-keytips/src/hooks/useTree.test.ts index cbc03d49..e08ffd17 100644 --- a/packages/react-keytips/src/hooks/useTree.test.ts +++ b/packages/react-keytips/src/hooks/useTree.test.ts @@ -117,7 +117,7 @@ describe('useTree', () => { expect(result.current.root).toEqual({ id: KTP_ROOT_ID, children: new Set(), - dependentKeys: [], + isShortcut: false, target: null, hasMenu: false, parent: '', diff --git a/packages/react-keytips/src/hooks/useTree.ts b/packages/react-keytips/src/hooks/useTree.ts index 81e542da..e9d9f0c4 100644 --- a/packages/react-keytips/src/hooks/useTree.ts +++ b/packages/react-keytips/src/hooks/useTree.ts @@ -1,17 +1,20 @@ import type { KeytipProps, KeytipWithId } from '../components/Keytip'; import * as React from 'react'; -import { sequencesToID, createNode } from '../utilities/index'; +import { sequencesToID, createNode, createAliasNode } from '../utilities/index'; import { KTP_ROOT_ID } from '../constants'; import { useFluent } from '@fluentui/react-components'; export type KeytipTreeNode = Pick< KeytipProps, - 'keySequences' | 'onExecute' | 'onReturn' | 'dynamic' | 'hasMenu' + | 'keySequences' + | 'onExecute' + | 'onReturn' + | 'dynamic' + | 'hasMenu' + | 'isShortcut' > & { id: string; uniqueId: string; - isShortcut?: boolean; - dependentKeys: string[]; target: HTMLElement | null; parent: string; children: Set; @@ -29,9 +32,9 @@ export function useTree() { id: KTP_ROOT_ID, uniqueId: KTP_ROOT_ID, children: new Set(), + isShortcut: false, target: null, parent: '', - dependentKeys: [], hasMenu: false, keySequences: [], }), @@ -45,6 +48,14 @@ export function useTree() { const currentKeytip = React.useRef(); const addNode = React.useCallback((newNode: KeytipWithId) => { + // if newNode has isShortcut:true, create alias node under the root + if (newNode.isShortcut) { + const alias = createAliasNode(newNode); + nodeMap.current.set(alias.uniqueId, alias); + const root = nodeMap.current.get(KTP_ROOT_ID); + root?.children.add(alias.uniqueId); + } + const node = createNode({ ...newNode, nodeMap: nodeMap.current, @@ -164,9 +175,9 @@ export function useTree() { const isCurrentKeytipParent = React.useCallback((keytip: KeytipProps) => { if (!currentKeytip.current) return false; - const fullSequence = keytip.keySequences.slice(0, -1); + const sequence = keytip.keySequences.slice(0, -1) ?? []; const parentID = - fullSequence.length === 0 ? KTP_ROOT_ID : sequencesToID(fullSequence); + sequence.length === 0 ? KTP_ROOT_ID : sequencesToID(sequence); return currentKeytip.current.id === parentID; }, []); diff --git a/packages/react-keytips/src/index.ts b/packages/react-keytips/src/index.ts index 609b93b6..d495f4b9 100644 --- a/packages/react-keytips/src/index.ts +++ b/packages/react-keytips/src/index.ts @@ -22,6 +22,8 @@ export { export { EVENTS } from './constants'; +export { sequencesToID } from './utilities'; + export type { KeytipsProps, KeytipsSlots, KeytipsState } from './Keytips'; export { useKeytipRef } from './hooks/useKeytipRef'; diff --git a/packages/react-keytips/src/utilities/createAliasNode.ts b/packages/react-keytips/src/utilities/createAliasNode.ts new file mode 100644 index 00000000..76361d5f --- /dev/null +++ b/packages/react-keytips/src/utilities/createAliasNode.ts @@ -0,0 +1,29 @@ +import { sequencesToID } from './sequencesToID'; +import { KeytipTreeNode } from '../hooks/useTree'; +import { KeytipWithId } from '../components/Keytip/Keytip.types'; +import { KTP_ROOT_ID } from '../constants'; + +export const createAliasNode = ({ + keySequences, + onExecute, + uniqueId, + onReturn, +}: KeytipWithId): KeytipTreeNode => { + const id = sequencesToID(keySequences.slice(-1)); + + const node: KeytipTreeNode = { + target: null, + id, + uniqueId: `${uniqueId}-alias`, + isShortcut: true, + parent: KTP_ROOT_ID, + children: new Set(), + onExecute, + onReturn, + hasMenu: false, + dynamic: false, + keySequences: keySequences, + }; + + return node; +}; diff --git a/packages/react-keytips/src/utilities/createNode.ts b/packages/react-keytips/src/utilities/createNode.ts index 5f96e217..1448d80f 100644 --- a/packages/react-keytips/src/utilities/createNode.ts +++ b/packages/react-keytips/src/utilities/createNode.ts @@ -4,25 +4,20 @@ import { KeytipWithId } from '../components/Keytip/Keytip.types'; export const createNode = ({ keySequences, - uniqueId, onExecute, onReturn, dynamic, - isShortcut, nodeMap, hasMenu, positioning, - dependentKeys = [], + uniqueId, }: KeytipWithId & { nodeMap: Map; - isShortcut?: boolean; - dependentKeys?: string[]; }): KeytipTreeNode => { const id = sequencesToID(keySequences); + const parent = - keySequences.length > 0 - ? sequencesToID(keySequences.slice(0, keySequences.length - 1)) - : ''; + keySequences.length > 0 ? sequencesToID(keySequences.slice(0, -1)) : ''; const children = new Set(); @@ -39,13 +34,12 @@ export const createNode = ({ target: positioning?.target as HTMLElement, parent, children, - dependentKeys, - keySequences: keySequences.map((key) => key.toLowerCase()), - onExecute, - onReturn, + isShortcut: false, hasMenu, dynamic, - isShortcut, + keySequences, + onExecute, + onReturn, }; return node; diff --git a/packages/react-keytips/src/utilities/index.ts b/packages/react-keytips/src/utilities/index.ts index 308ef09f..8d2bb273 100644 --- a/packages/react-keytips/src/utilities/index.ts +++ b/packages/react-keytips/src/utilities/index.ts @@ -1,5 +1,6 @@ export * from './sequencesToID'; export * from './createNode'; +export * from './createAliasNode'; export * from './isTargetVisible'; export * from './isDisabled'; export * from './omit'; diff --git a/packages/react-keytips/stories/Default.stories.tsx b/packages/react-keytips/stories/Default.stories.tsx index 56b26c4a..2e058c6b 100644 --- a/packages/react-keytips/stories/Default.stories.tsx +++ b/packages/react-keytips/stories/Default.stories.tsx @@ -135,13 +135,13 @@ export const DefaultStory = () => { }); const normalButton = useKeytipRef({ - keySequences: ['1C'], + keySequences: ['1c'], content: '1C', onExecute, }); const compoundButton = useKeytipRef({ - keySequences: ['1E'], + keySequences: ['1e'], content: '1E', onExecute, }); diff --git a/packages/react-keytips/stories/OverflowMenu.md b/packages/react-keytips/stories/OverflowMenu.md index 2d97fae4..7c5ebb39 100644 --- a/packages/react-keytips/stories/OverflowMenu.md +++ b/packages/react-keytips/stories/OverflowMenu.md @@ -1,21 +1,23 @@ -Keytips with Overflow require `dynamic` prop to be passed with `useKeytipRef`. You can also register -a `shortcut` keytip, that can be accessed from the top level. A shortcut to a normal Button -will trigger passed callback function, shortcut to a MenuButton will open a menu. In this example, firing `T` and `Y` -will show this functionality. +Keytips with `Overflow` and `Menu` components offer special options, that can be used: + +`isShortcut` - a Keytip can be a shortcut, that can be accessed from the top overflow level. A shortcut to a normal Button will trigger it immediately, +if it's attached to a Menu, it will open a Menu, even if Keytip does not have a child Keytip to show. + +In this example, firing `T`, `Y` and `R` will show this functionality. ```tsx const subMenuRef = useKeytipRef({ - keySequences: ['d', 'y'], + keySequences: ['y'], content: 'Y', hasMenu: true, - shortcut: true, + isShortcut: true, onExecute, }); const subMenuRefItem = useKeytipRef({ - keySequences: ['d', 't'], + keySequences: ['t'], content: 'T', - shortcut: true, + isShortcut: true, onExecute, }); ``` diff --git a/packages/react-keytips/stories/OverflowMenu.stories.tsx b/packages/react-keytips/stories/OverflowMenu.stories.tsx index 81bd4dcd..c8183810 100644 --- a/packages/react-keytips/stories/OverflowMenu.stories.tsx +++ b/packages/react-keytips/stories/OverflowMenu.stories.tsx @@ -57,6 +57,7 @@ const useStyles = makeStyles({ const onExecute: ExecuteKeytipEventHandler = (_, { targetElement }) => { if (targetElement) { + console.info(targetElement); targetElement.focus(); targetElement.click(); } @@ -75,6 +76,7 @@ const OverflowItemWrapper = React.forwardRef< { keytipProps: KeytipProps & { id: string } } >(({ keytipProps }, ref) => { const keytipRef = useKeytipRef(keytipProps); + const mergedRefs = useMergedRefs(ref, keytipRef); return ( @@ -89,15 +91,14 @@ const OverflowMenuItemWrapper = React.forwardRef< { keytipProps: KeytipProps & { id: string } } >(({ keytipProps }, ref) => { const isVisible = useIsOverflowItemVisible(keytipProps.id); - - const sequences = !isVisible - ? ['d', ...keytipProps.keySequences] - : keytipProps.keySequences; + false; const keytipRef = useKeytipRef({ ...keytipProps, - shortcut: !isVisible, - keySequences: sequences, + isShortcut: !isVisible, + keySequences: !isVisible + ? ['d', ...keytipProps.keySequences] + : keytipProps.keySequences, }); const mergedRefs = useMergedRefs(ref, keytipRef); @@ -107,7 +108,7 @@ const OverflowMenuItemWrapper = React.forwardRef< } return ( - + Item {keytipProps.id} ); @@ -145,14 +146,13 @@ const OverflowMenu = ({ const menuRef = useKeytipRef({ keySequences: ['d'], content: 'D', - shortcut: true, onExecute, }); const subMenuRef = useKeytipRef({ keySequences: ['d', 'y'], content: 'Y', - shortcut: true, + isShortcut: true, hasMenu: true, onExecute, });