Command menu refactoring (#9257)
Refactored the `CommandMenu` component to make it more readable and easier to refactor. The file was way too big so I introduced a few hooks and eliminated code duplication. Introduced: - `useMatchCommands` hook to match commands with the search - `useCommandMenuCommands` which returns all command menu commands - `useMatchingCommandMenuCommands` to return the commands matched with the search - `CommandMenuContainer` to simplify the `DefaultLayout` - Unmounted the `CommandMenu` when it wasn't opened to improve performances I also introduced a new behavior: Automatically select the first item when opening the command menu: https://github.com/user-attachments/assets/4b683d49-570e-47c9-8939-99f42ed8691c
This commit is contained in:
@ -1,12 +1,5 @@
|
||||
import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
|
||||
import { RecordAgnosticActionsSetterEffect } from '@/action-menu/actions/record-agnostic-actions/components/RecordAgnosticActionsSetterEffect';
|
||||
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
|
||||
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { AuthModal } from '@/auth/components/AuthModal';
|
||||
import { CommandMenu } from '@/command-menu/components/CommandMenu';
|
||||
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { CommandMenuContainer } from '@/command-menu/components/CommandMenuContainer';
|
||||
import { AppErrorBoundary } from '@/error-handler/components/AppErrorBoundary';
|
||||
import { KeyboardShortcutMenu } from '@/keyboard-shortcut-menu/components/KeyboardShortcutMenu';
|
||||
import { AppNavigationDrawer } from '@/navigation/components/AppNavigationDrawer';
|
||||
@ -18,8 +11,7 @@ import { SignInBackgroundMockPage } from '@/sign-in-background-mock/components/S
|
||||
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
|
||||
import { NAV_DRAWER_WIDTHS } from '@/ui/navigation/navigation-drawer/constants/NavDrawerWidths';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { css, Global, useTheme } from '@emotion/react';
|
||||
import { Global, css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { AnimatePresence, LayoutGroup, motion } from 'framer-motion';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
@ -77,9 +69,6 @@ export const DefaultLayout = () => {
|
||||
const theme = useTheme();
|
||||
const windowsWidth = useScreenSize().width;
|
||||
const showAuthModal = useShowAuthModal();
|
||||
const { toggleCommandMenu } = useCommandMenu();
|
||||
|
||||
const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED');
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -93,25 +82,7 @@ export const DefaultLayout = () => {
|
||||
<StyledLayout>
|
||||
{!showAuthModal && (
|
||||
<>
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'command-menu' }}
|
||||
>
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'command-menu' }}
|
||||
>
|
||||
<ActionMenuContext.Provider
|
||||
value={{
|
||||
isInRightDrawer: false,
|
||||
onActionExecutedCallback: toggleCommandMenu,
|
||||
}}
|
||||
>
|
||||
<RecordActionMenuEntriesSetter />
|
||||
{isWorkflowEnabled && <RecordAgnosticActionsSetterEffect />}
|
||||
<ActionMenuConfirmationModals />
|
||||
<CommandMenu />
|
||||
</ActionMenuContext.Provider>
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
<CommandMenuContainer />
|
||||
<KeyboardShortcutMenu />
|
||||
</>
|
||||
)}
|
||||
|
||||
@ -26,7 +26,7 @@ export const SelectableList = ({
|
||||
}: SelectableListProps) => {
|
||||
useSelectableListHotKeys(selectableListId, hotkeyScope);
|
||||
|
||||
const { setSelectableItemIds, setSelectableListOnEnter } =
|
||||
const { setSelectableItemIds, setSelectableListOnEnter, setSelectedItemId } =
|
||||
useSelectableList(selectableListId);
|
||||
|
||||
useEffect(() => {
|
||||
@ -47,7 +47,12 @@ export const SelectableList = ({
|
||||
if (isDefined(selectableItemIdArray)) {
|
||||
setSelectableItemIds(arrayToChunks(selectableItemIdArray, 1));
|
||||
}
|
||||
}, [selectableItemIdArray, selectableItemIdMatrix, setSelectableItemIds]);
|
||||
}, [
|
||||
selectableItemIdArray,
|
||||
selectableItemIdMatrix,
|
||||
setSelectableItemIds,
|
||||
setSelectedItemId,
|
||||
]);
|
||||
|
||||
return (
|
||||
<SelectableListScope selectableListScopeId={selectableListId}>
|
||||
|
||||
@ -33,11 +33,23 @@ export const useSelectableList = (selectableListId?: string) => {
|
||||
[selectedItemIdState, isSelectedItemIdSelector],
|
||||
);
|
||||
|
||||
const setSelectedItemId = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(itemId: string) => {
|
||||
resetSelectedItem();
|
||||
set(selectedItemIdState, itemId);
|
||||
set(isSelectedItemIdSelector(itemId), true);
|
||||
},
|
||||
[resetSelectedItem, selectedItemIdState, isSelectedItemIdSelector],
|
||||
);
|
||||
|
||||
return {
|
||||
selectableListId: scopeId,
|
||||
setSelectableItemIds,
|
||||
isSelectedItemIdSelector,
|
||||
setSelectableListOnEnter,
|
||||
resetSelectedItem,
|
||||
setSelectedItemId,
|
||||
selectedItemIdState,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user