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:
Raphaël Bosi
2024-12-30 15:22:49 +01:00
committed by GitHub
parent 0fa59d7718
commit 1091bc657d
24 changed files with 827 additions and 980 deletions

View File

@ -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}>

View File

@ -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,
};
};