Replace hotkey scopes by focus stack (Part 1 - Dropdowns and Side Panel) (#12673)

This PR is the first part of a refactoring aiming to deprecate the
hotkey scopes api in favor of the new focus stack api which is more
robust.

The refactored components in this PR are the dropdowns and the side
panel/command menu.

- Replaced `useScopedHotkeys` by `useHotkeysOnFocusedElement` for all
dropdown components, selectable lists and the command menu
- Introduced `focusId` for all dropdowns and created a common hotkey
scope `DropdownHotkeyScope` for backward compatibility
- Replaced `setHotkeyScopeAndMemorizePreviousScope` occurrences with
`usePushFocusItemToFocusStack` and `goBackToPreviousHotkeyScope` with
`removeFocusItemFromFocusStack`

Note: Test that the shorcuts and arrow key navigation still work
properly when interacting with dropdowns and the command menu.

Bugs that I have spotted during the QA but which are already present on
main:
- Icon picker select with arrow keys doesn’t work inside dropdowns
- Some dropdowns are not selectable with arrow keys (no selectable list)
- Dropdowns in dropdowns don’t reset the hotkey scope correctly when
closing
- The table click outside is not triggered after closing a table cell
and clicking outside of the table
This commit is contained in:
Raphaël Bosi
2025-06-19 14:53:18 +02:00
committed by GitHub
parent 6dd3a71497
commit cbc0d06a2f
155 changed files with 977 additions and 845 deletions

View File

@ -29,7 +29,6 @@ export const AdvancedFilterDropdownButton = () => {
dropdownId={ADVANCED_FILTER_DROPDOWN_ID}
clickableComponent={<AdvancedFilterChip />}
dropdownComponents={<AdvancedFilterRootRecordFilterGroup />}
dropdownHotkeyScope={{ scope: ADVANCED_FILTER_DROPDOWN_ID }}
dropdownOffset={{ y: 8, x: 0 }}
dropdownPlacement="bottom-start"
onOpen={handleOpenAdvancedFilterDropdown}

View File

@ -3,7 +3,6 @@ import { useCallback } from 'react';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { EditableFilterChip } from '@/views/components/EditableFilterChip';
import { ObjectFilterDropdownFilterInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput';
@ -13,12 +12,10 @@ import { useSetEditableFilterChipDropdownStates } from '@/views/hooks/useSetEdit
type EditableFilterDropdownButtonProps = {
recordFilter: RecordFilter;
hotkeyScope: HotkeyScope;
};
export const EditableFilterDropdownButton = ({
recordFilter,
hotkeyScope,
}: EditableFilterDropdownButtonProps) => {
const { closeDropdown } = useDropdown(recordFilter.id);
@ -59,7 +56,6 @@ export const EditableFilterDropdownButton = ({
dropdownComponents={
<ObjectFilterDropdownFilterInput filterDropdownId={recordFilter.id} />
}
dropdownHotkeyScope={hotkeyScope}
dropdownOffset={{ y: 8, x: 0 }}
dropdownPlacement="bottom-start"
onClose={onFilterDropdownClose}

View File

@ -34,9 +34,7 @@ export type UpdateViewButtonGroupProps = {
hotkeyScope: HotkeyScope;
};
export const UpdateViewButtonGroup = ({
hotkeyScope,
}: UpdateViewButtonGroupProps) => {
export const UpdateViewButtonGroup = () => {
const { saveCurrentViewFilterAndSorts } = useSaveCurrentViewFiltersAndSorts();
const { setViewPickerMode } = useViewPickerMode();
@ -109,7 +107,6 @@ export const UpdateViewButtonGroup = ({
<Button title="Update view" onClick={handleUpdateViewClick} />
<Dropdown
dropdownId={UPDATE_VIEW_BUTTON_DROPDOWN_ID}
dropdownHotkeyScope={hotkeyScope}
clickableComponent={
<IconButton
size="small"

View File

@ -8,10 +8,8 @@ import { QueryParamsFiltersEffect } from '@/views/components/QueryParamsFiltersE
import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle';
import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader';
import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown';
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope';
import { VIEW_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ViewSortDropdownId';
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
import { ViewBarFilterDropdown } from '@/views/components/ViewBarFilterDropdown';
@ -59,17 +57,9 @@ export const ViewBar = ({
<ObjectFilterDropdownComponentInstanceContext.Provider
value={{ instanceId: VIEW_BAR_FILTER_DROPDOWN_ID }}
>
<ViewBarFilterDropdown
hotkeyScope={{
scope: FiltersHotkeyScope.ObjectFilterDropdownButton,
}}
/>
<ViewBarFilterDropdown />
</ObjectFilterDropdownComponentInstanceContext.Provider>
<ObjectSortDropdownButton
hotkeyScope={{
scope: FiltersHotkeyScope.ObjectSortDropdownButton,
}}
/>
<ObjectSortDropdownButton />
{optionsDropdownButton}
</>
}
@ -78,13 +68,7 @@ export const ViewBar = ({
hasFilterButton
viewBarId={viewBarId}
objectNamePlural={objectNamePlural}
rightComponent={
<UpdateViewButtonGroup
hotkeyScope={{
scope: ViewsHotkeyScope.UpdateViewButtonDropdown,
}}
/>
}
rightComponent={<UpdateViewButtonGroup />}
/>
}
/>

View File

@ -229,12 +229,7 @@ export const ViewBarDetails = ({
value={{ instanceId: recordFilter.id }}
>
<DropdownScope dropdownScopeId={recordFilter.id}>
<EditableFilterDropdownButton
recordFilter={recordFilter}
hotkeyScope={{
scope: recordFilter.id,
}}
/>
<EditableFilterDropdownButton recordFilter={recordFilter} />
</DropdownScope>
</ObjectFilterDropdownComponentInstanceContext.Provider>
))}

View File

@ -1,26 +1,13 @@
import { useResetFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useResetFilterDropdown';
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { Trans } from '@lingui/react/macro';
export const ViewBarFilterButton = () => {
const { resetFilterDropdown } = useResetFilterDropdown();
const { toggleDropdown, isDropdownOpen } = useDropdown(
VIEW_BAR_FILTER_DROPDOWN_ID,
);
const handleClick = () => {
toggleDropdown();
resetFilterDropdown();
};
const { isDropdownOpen } = useDropdown(VIEW_BAR_FILTER_DROPDOWN_ID);
return (
<StyledHeaderDropdownButton
onClick={handleClick}
isUnfolded={isDropdownOpen}
>
<StyledHeaderDropdownButton isUnfolded={isDropdownOpen}>
<Trans>Filter</Trans>
</StyledHeaderDropdownButton>
);

View File

@ -1,6 +1,5 @@
import { useResetFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useResetFilterDropdown';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { useVectorSearchFilterActions } from '@/views/hooks/useVectorSearchFilterActions';
@ -13,13 +12,7 @@ import { ViewBarFilterDropdownContent } from '@/views/components/ViewBarFilterDr
import { isDefined } from 'twenty-shared/utils';
import { ViewBarFilterButton } from './ViewBarFilterButton';
type ViewBarFilterDropdownProps = {
hotkeyScope: HotkeyScope;
};
export const ViewBarFilterDropdown = ({
hotkeyScope,
}: ViewBarFilterDropdownProps) => {
export const ViewBarFilterDropdown = () => {
const { resetFilterDropdown } = useResetFilterDropdown();
const { removeEmptyVectorSearchFilter } = useVectorSearchFilterActions();
const { removeRecordFilter } = useRemoveRecordFilter();
@ -47,13 +40,17 @@ export const ViewBarFilterDropdown = ({
removeEmptyVectorSearchFilter();
};
const handleDropdownOpen = () => {
resetFilterDropdown();
};
return (
<Dropdown
dropdownId={VIEW_BAR_FILTER_DROPDOWN_ID}
onClose={handleDropdownClose}
onOpen={handleDropdownOpen}
clickableComponent={<ViewBarFilterButton />}
dropdownComponents={<ViewBarFilterDropdownContent />}
dropdownHotkeyScope={hotkeyScope}
dropdownOffset={{ y: 8 }}
onClickOutside={handleDropdownClickOutside}
excludedClickOutsideIds={[OPERAND_DROPDOWN_CLICK_OUTSIDE_ID]}

View File

@ -119,9 +119,7 @@ export const ViewBarFilterDropdownAdvancedFilterButton = () => {
}
closeObjectFilterDropdown();
openAdvancedFilterDropdown({
scope: ADVANCED_FILTER_DROPDOWN_ID,
});
openAdvancedFilterDropdown();
};
return (

View File

@ -10,15 +10,16 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl
import { FILTER_FIELD_LIST_ID } from '@/object-record/object-filter-dropdown/constants/FilterFieldListId';
import { useFilterDropdownSelectableFieldMetadataItems } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownSelectableFieldMetadataItems';
import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuSectionLabel } from '@/ui/layout/dropdown/components/DropdownMenuSectionLabel';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { ViewBarFilterDropdownBottomMenu } from '@/views/components/ViewBarFilterDropdownBottomMenu';
import { ViewBarFilterDropdownFieldSelectMenuItem } from '@/views/components/ViewBarFilterDropdownFieldSelectMenuItem';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS } from '@/views/constants/ViewBarFilterBottomMenuItemIds';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { useLingui } from '@lingui/react/macro';
export const StyledInput = styled.input`
@ -92,9 +93,10 @@ export const ViewBarFilterDropdownFieldSelectMenu = () => {
}
/>
<SelectableList
hotkeyScope={FiltersHotkeyScope.ObjectFilterDropdownButton}
selectableItemIdArray={selectableFieldMetadataItemIds}
selectableListInstanceId={FILTER_FIELD_LIST_ID}
focusId={VIEW_BAR_FILTER_DROPDOWN_ID}
hotkeyScope={DropdownHotkeyScope.Dropdown}
>
{shouldShowVisibleFields && (
<>

View File

@ -15,16 +15,20 @@ import { RecordFiltersComponentInstanceContext } from '@/object-record/record-fi
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
import { getMockPersonObjectMetadataItem } from '~/testing/mock-data/people';
const mockSetHotkeyScope = jest.fn();
const mockPushFocusItemToFocusStack = jest.fn();
jest.mock('@/ui/utilities/hotkey/hooks/useSetHotkeyScope', () => ({
useSetHotkeyScope: () => mockSetHotkeyScope,
jest.mock('@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack', () => ({
usePushFocusItemToFocusStack: () => ({
pushFocusItemToFocusStack: mockPushFocusItemToFocusStack,
}),
}));
const peopleObjectMetadataItemMock = getMockPersonObjectMetadataItem();
@ -109,7 +113,7 @@ describe('useInitializeFilterOnFieldMetadataItemFromViewBarFilterDropdown', () =
);
expect(result.current.objectFilterDropdownFilterIsSelected).toBe(true);
expect(result.current.selectedOperandInDropdown).toBe(defaultOperand);
expect(mockSetHotkeyScope).not.toHaveBeenCalled();
expect(mockPushFocusItemToFocusStack).not.toHaveBeenCalled();
});
it('should initialize filter with a relation field', () => {
@ -161,9 +165,17 @@ describe('useInitializeFilterOnFieldMetadataItemFromViewBarFilterDropdown', () =
);
expect(result.current.objectFilterDropdownFilterIsSelected).toBe(true);
expect(result.current.selectedOperandInDropdown).toBe(defaultOperand);
expect(mockSetHotkeyScope).toHaveBeenCalledWith(
SingleRecordPickerHotkeyScope.SingleRecordPicker,
);
expect(mockPushFocusItemToFocusStack).toHaveBeenCalledWith({
focusId: VIEW_BAR_FILTER_DROPDOWN_ID,
component: {
type: FocusComponentType.DROPDOWN,
instanceId: personCompanyFieldMetadataItemMock.id,
},
hotkeyScope: {
scope: DropdownHotkeyScope.Dropdown,
},
memoizeKey: personCompanyFieldMetadataItemMock.id,
});
});
it('should initialize filter with a duplicate field on city', () => {

View File

@ -10,9 +10,11 @@ import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-record/record-filter/utils/findDuplicateRecordFilterInNonAdvancedRecordFilters';
import { getDateFilterDisplayValue } from '@/object-record/record-filter/utils/getDateFilterDisplayValue';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
@ -24,8 +26,6 @@ export const useInitializeFilterOnFieldMetadataItemFromViewBarFilterDropdown =
selectedOperandInDropdownComponentState,
);
const setHotkeyScope = useSetHotkeyScope();
const currentRecordFiltersCallbackState = useRecoilComponentCallbackStateV2(
currentRecordFiltersComponentState,
);
@ -48,6 +48,8 @@ export const useInitializeFilterOnFieldMetadataItemFromViewBarFilterDropdown =
const { upsertObjectFilterDropdownCurrentFilter } =
useUpsertObjectFilterDropdownCurrentFilter();
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
const initializeFilterOnFieldMetataItemFromViewBarFilterDropdown =
useRecoilCallback(
({ set, snapshot }) =>
@ -66,7 +68,17 @@ export const useInitializeFilterOnFieldMetadataItemFromViewBarFilterDropdown =
);
if (filterType === 'RELATION' || filterType === 'SELECT') {
setHotkeyScope(SingleRecordPickerHotkeyScope.SingleRecordPicker);
pushFocusItemToFocusStack({
focusId: VIEW_BAR_FILTER_DROPDOWN_ID,
component: {
type: FocusComponentType.DROPDOWN,
instanceId: fieldMetadataItem.id,
},
hotkeyScope: {
scope: DropdownHotkeyScope.Dropdown,
},
memoizeKey: fieldMetadataItem.id,
});
}
set(objectFilterDropdownFilterIsSelectedCallbackState, true);
@ -130,11 +142,11 @@ export const useInitializeFilterOnFieldMetadataItemFromViewBarFilterDropdown =
},
[
fieldMetadataItemUsedInDropdownCallbackState,
currentRecordFiltersCallbackState,
objectFilterDropdownFilterIsSelectedCallbackState,
pushFocusItemToFocusStack,
objectFilterDropdownCurrentRecordFilterCallbackState,
selectedOperandInDropdownCallbackState,
setHotkeyScope,
objectFilterDropdownFilterIsSelectedCallbackState,
currentRecordFiltersCallbackState,
upsertObjectFilterDropdownCurrentFilter,
],
);

View File

@ -1,4 +0,0 @@
export enum ViewsHotkeyScope {
ListDropdown = 'views-list-dropdown',
UpdateViewButtonDropdown = 'update-view-button-dropdown',
}

View File

@ -10,18 +10,18 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenu
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState';
import { ViewType, viewTypeIconMapping } from '@/views/types/ViewType';
import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope';
import { ViewPickerCreateButton } from '@/views/view-picker/components/ViewPickerCreateButton';
import { ViewPickerIconAndNameContainer } from '@/views/view-picker/components/ViewPickerIconAndNameContainer';
import { ViewPickerSaveButtonContainer } from '@/views/view-picker/components/ViewPickerSaveButtonContainer';
import { ViewPickerSelectContainer } from '@/views/view-picker/components/ViewPickerSelectContainer';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerKanbanFieldDropdownId';
import { VIEW_PICKER_TYPE_SELECT_OPTIONS } from '@/views/view-picker/constants/ViewPickerTypeSelectOptions';
import { VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerViewTypeDropdownId';
@ -78,15 +78,13 @@ export const ViewPickerContentCreateMode = () => {
viewPickerTypeComponentState,
);
const setHotkeyScope = useSetHotkeyScope();
const { createViewFromCurrentState } = useCreateViewFromCurrentState();
const { availableFieldsForKanban } = useGetAvailableFieldsForKanban();
useScopedHotkeys(
Key.Enter,
async () => {
useHotkeysOnFocusedElement({
keys: [Key.Enter],
callback: async () => {
if (viewPickerIsPersisting) {
return;
}
@ -100,8 +98,15 @@ export const ViewPickerContentCreateMode = () => {
await createViewFromCurrentState();
},
ViewsHotkeyScope.ListDropdown,
);
focusId: VIEW_PICKER_DROPDOWN_ID,
scope: DropdownHotkeyScope.Dropdown,
dependencies: [
viewPickerIsPersisting,
createViewFromCurrentState,
viewPickerType,
availableFieldsForKanban,
],
});
const defaultIcon = viewTypeIconMapping(viewPickerType).displayName;
@ -141,11 +146,7 @@ export const ViewPickerContentCreateMode = () => {
</DropdownMenuHeader>
<DropdownMenuItemsContainer>
<ViewPickerIconAndNameContainer>
<IconPicker
onChange={onIconChange}
selectedIconKey={selectedIcon}
onClose={() => setHotkeyScope(ViewsHotkeyScope.ListDropdown)}
/>
<IconPicker onChange={onIconChange} selectedIconKey={selectedIcon} />
<TextInputV2
value={viewPickerInputName}
onChange={(value) => {

View File

@ -7,15 +7,15 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenu
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope';
import { ViewPickerEditButton } from '@/views/view-picker/components/ViewPickerEditButton';
import { ViewPickerIconAndNameContainer } from '@/views/view-picker/components/ViewPickerIconAndNameContainer';
import { ViewPickerSaveButtonContainer } from '@/views/view-picker/components/ViewPickerSaveButtonContainer';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { useUpdateViewFromCurrentState } from '@/views/view-picker/hooks/useUpdateViewFromCurrentState';
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState';
@ -39,21 +39,21 @@ export const ViewPickerContentEditMode = () => {
viewPickerIsDirtyComponentState,
);
const setHotkeyScope = useSetHotkeyScope();
const { updateViewFromCurrentState } = useUpdateViewFromCurrentState();
useScopedHotkeys(
Key.Enter,
async () => {
useHotkeysOnFocusedElement({
keys: [Key.Enter],
callback: async () => {
if (viewPickerIsPersisting) {
return;
}
await updateViewFromCurrentState();
},
ViewsHotkeyScope.ListDropdown,
);
focusId: VIEW_PICKER_DROPDOWN_ID,
scope: DropdownHotkeyScope.Dropdown,
dependencies: [viewPickerIsPersisting, updateViewFromCurrentState],
});
const onIconChange = ({ iconKey }: { iconKey: string }) => {
setViewPickerIsDirty(true);
@ -83,7 +83,6 @@ export const ViewPickerContentEditMode = () => {
<IconPicker
onChange={onIconChange}
selectedIconKey={viewPickerSelectedIcon}
onClose={() => setHotkeyScope(ViewsHotkeyScope.ListDropdown)}
/>
<TextInputV2
value={viewPickerInputName}

View File

@ -6,7 +6,6 @@ import { StyledDropdownButtonContainer } from '@/ui/layout/dropdown/components/S
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useGetRecordIndexTotalCount } from '@/views/hooks/internal/useGetRecordIndexTotalCount';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope';
import { ViewPickerContentCreateMode } from '@/views/view-picker/components/ViewPickerContentCreateMode';
import { ViewPickerContentEditMode } from '@/views/view-picker/components/ViewPickerContentEditMode';
import { ViewPickerContentEffect } from '@/views/view-picker/components/ViewPickerContentEffect';
@ -71,7 +70,6 @@ export const ViewPickerDropdown = () => {
return (
<Dropdown
dropdownId={VIEW_PICKER_DROPDOWN_ID}
dropdownHotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }}
dropdownOffset={{ x: 0, y: 8 }}
dropdownPlacement="bottom-start"
onClickOutside={handleClickOutside}