Replaced useDropdown calls by useCloseDropdown, useOpenDropdown and useToggleDropdown (#12958)

This PR replaces the many calls of useDropdown by the new standalone
hooks : useCloseDropdown, useOpenDropdown and useToggleDropdown.

This will allow to remove useDropdown and then the dropdown recoil
component state v1.

A big round of QA has been made, with some bugs caught along the way.

Closes https://github.com/twentyhq/core-team-issues/issues/1155
Closes https://github.com/twentyhq/core-team-issues/issues/618

## QA

Component|Status|Comment
|---|---|---|
CurrentWorkspaceMemberFavorites|Ok|
FavoriteFolderPickerFooter|Ok|
AdvancedFilterAddFilterRuleSelect|Ok|
AdvancedFilterRecordFilterGroupOptionsDropdown|Ok|
AdvancedFilterRecordFilterOperandSelectContent|Ok|
AdvancedFilterRecordFilterOptionsDropdown|Ok|
useAdvancedFilterFieldSelectDropdown|Ok|
ObjectFilterDropdownBooleanSelect|Ok|
ObjectFilterDropdownOptionSelect|Ok|
ObjectOptionsDropdown|Ok|
ObjectOptionsDropdownLayoutContent|Ok|
ObjectSortDropdownButton|Ok|
useCloseSortDropdown|Ok|
FormDateTimeFieldInput|Ok|Bug detected, cannot select a month or a year,
see issue https://github.com/twentyhq/twenty/issues/12922
FormSingleRecordPicker|Ok|
MultiItemFieldMenuItem|Ok|
RecordDetailRelationRecordsListItem|Ok|
RecordDetailRelationSection|Ok|
RecordDetailRelationSectionDropdownToMany|Ok|
RecordDetailRelationSectionDropdownToOne|Ok|
RecordTableColumnAggregateFooterDropdownSubmenuContent|Ok|
RecordTableColumnAggregateFooterAggregateOperationMenuItems|Ok|
RecordTableColumnAggregateFooterMenuContent|Ok|
RecordTableColumnAggregateFooterValueCell|Ok|
RecordTableColumnHeadDropdownMenu|Ok|
RecordTableHeaderPlusButtonContent|Ok|
useTriggerActionMenuDropdown|Ok|
MultipleSelectDropdown|Ok|
RecordBoardColumnHeaderAggregateDropdownButton|Ok|
SettingsDataModelFieldSelectFormOptionRow|Ok|
SettingsDataModelNewFieldBreadcrumbDropDown|Ok|
SettingsObjectFieldActiveActionDropdown|Ok|
SettingsObjectFieldInactiveActionDropdown|Ok|
SettingsObjectInactiveMenuDropDown|Ok|
SettingsSecurityApprovedAccessDomainRowDropdownMenu|Couldn’t test|
SettingsSecuritySSORowDropdownMenu|Couldn’t test|
SettingsAccountsRowDropdownMenu|Ok|
SettingsRoleAssignment|Ok|
SettingsServerlessFunctionTabEnvironmentVariableTableRow|Couldn’t test|
MatchColumnToFieldSelect|Ok|
SubMatchingSelectDropdownButton|Ok|Removed conflicting duplicate open
dropdown
SubMatchingSelectRowRightDropdown|Ok|
CurrencyPickerDropdownButton|Ok|
IconPicker|Ok|
DateTimePicker|Ok|
PhoneCountryPickerDropdownButton|OK|
Select|Ok|
Dropdown|Ok|Not QAing all dropdowns in the app because the ones of this
QA are enough to show up that Dropdown is behaving correctly on a lot of
use cases
DropdownMenuInnerSelect|Ok|
TabList|Ok|Removed onClickOutside called in dropdown clickable
component, validated with Raph who recently worked on this
DateInput|Ok|
MultiWorkspaceDropdownDefaultComponents|Ok|
AdvancedFilterChip|Ok|
EditableFilterDropdownButton|Ok|
UpdateViewButtonGroup|Ok|
ViewBarDetailsAddFilterButton|Ok|
ViewBarFilterButton|Ok|
ViewBarFilterDropdown|Ok|
ViewBarFilterDropdownAdvancedFilterButton|Ok|
ViewPickerDropdown|Ok|
ViewPickerListContent|Ok|
ViewPickerOptionDropdown|Ok|
WorkflowEditTriggerDatabaseEventForm|Ok|
WorkflowVariablesDropdownWorkflowStepItems|Ok|
AttachmentDropdown|Ok|
SupportDropdown|Ok|

Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Lucas Bordeau
2025-07-02 18:38:45 +02:00
committed by GitHub
parent a19a73a977
commit a7b9a0710e
70 changed files with 352 additions and 426 deletions

View File

@ -2,7 +2,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { import {
IconDotsVertical, IconDotsVertical,
IconDownload, IconDownload,
@ -27,21 +27,21 @@ export const AttachmentDropdown = ({
}: AttachmentDropdownProps) => { }: AttachmentDropdownProps) => {
const dropdownId = `${scopeKey}-settings-field-active-action-dropdown`; const dropdownId = `${scopeKey}-settings-field-active-action-dropdown`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const handleDownload = () => { const handleDownload = () => {
onDownload(); onDownload();
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleDelete = () => { const handleDelete = () => {
onDelete(); onDelete();
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleRename = () => { const handleRename = () => {
onRename(); onRename();
closeDropdown(); closeDropdown(dropdownId);
}; };
return ( return (

View File

@ -10,7 +10,8 @@ import { openFavoriteFolderIdsState } from '@/favorites/states/openFavoriteFolde
import { isLocationMatchingFavorite } from '@/favorites/utils/isLocationMatchingFavorite'; import { isLocationMatchingFavorite } from '@/favorites/utils/isLocationMatchingFavorite';
import { ProcessedFavorite } from '@/favorites/utils/sortFavorites'; import { ProcessedFavorite } from '@/favorites/utils/sortFavorites';
import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem'; import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useModal } from '@/ui/layout/modal/hooks/useModal'; import { useModal } from '@/ui/layout/modal/hooks/useModal';
import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState'; import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
@ -28,6 +29,7 @@ import { useRecoilState } from 'recoil';
import { IconFolder, IconFolderOpen, IconHeartOff } from 'twenty-ui/display'; import { IconFolder, IconFolderOpen, IconHeartOff } from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input'; import { LightIconButton } from 'twenty-ui/input';
import { AnimatedExpandableContainer } from 'twenty-ui/layout'; import { AnimatedExpandableContainer } from 'twenty-ui/layout';
type CurrentWorkspaceMemberFavoritesProps = { type CurrentWorkspaceMemberFavoritesProps = {
folder: { folder: {
folderId: string; folderId: string;
@ -68,10 +70,16 @@ export const CurrentWorkspaceMemberFavorites = ({
const { renameFavoriteFolder } = useRenameFavoriteFolder(); const { renameFavoriteFolder } = useRenameFavoriteFolder();
const { deleteFavoriteFolder } = useDeleteFavoriteFolder(); const { deleteFavoriteFolder } = useDeleteFavoriteFolder();
const {
closeDropdown: closeFavoriteFolderEditDropdown, const dropdownId = `favorite-folder-edit-${folder.folderId}`;
isDropdownOpen: isFavoriteFolderEditDropdownOpen,
} = useDropdown(`favorite-folder-edit-${folder.folderId}`); const isDropdownOpenComponent = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
dropdownId,
);
const { closeDropdown } = useCloseDropdown();
const selectedFavoriteIndex = folder.favorites.findIndex((favorite) => const selectedFavoriteIndex = folder.favorites.findIndex((favorite) =>
isLocationMatchingFavorite(currentPath, currentViewPath, favorite), isLocationMatchingFavorite(currentPath, currentViewPath, favorite),
); );
@ -110,10 +118,10 @@ export const CurrentWorkspaceMemberFavorites = ({
const handleFavoriteFolderDelete = async () => { const handleFavoriteFolderDelete = async () => {
if (folder.favorites.length > 0) { if (folder.favorites.length > 0) {
openModal(modalId); openModal(modalId);
closeFavoriteFolderEditDropdown(); closeDropdown(dropdownId);
} else { } else {
await deleteFavoriteFolder(folder.folderId); await deleteFavoriteFolder(folder.folderId);
closeFavoriteFolderEditDropdown(); closeDropdown(dropdownId);
} }
}; };
@ -126,7 +134,9 @@ export const CurrentWorkspaceMemberFavorites = ({
folderId={folder.folderId} folderId={folder.folderId}
onRename={() => setIsFavoriteFolderRenaming(true)} onRename={() => setIsFavoriteFolderRenaming(true)}
onDelete={handleFavoriteFolderDelete} onDelete={handleFavoriteFolderDelete}
closeDropdown={closeFavoriteFolderEditDropdown} closeDropdown={() => {
closeDropdown(dropdownId);
}}
/> />
); );
@ -159,7 +169,7 @@ export const CurrentWorkspaceMemberFavorites = ({
onClick={handleToggle} onClick={handleToggle}
rightOptions={rightOptions} rightOptions={rightOptions}
className="navigation-drawer-item" className="navigation-drawer-item"
isRightOptionsDropdownOpen={isFavoriteFolderEditDropdownOpen} isRightOptionsDropdownOpen={isDropdownOpenComponent}
triggerEvent="CLICK" triggerEvent="CLICK"
/> />
</FavoritesDroppable> </FavoritesDroppable>

View File

@ -1,6 +1,6 @@
import { isFavoriteFolderCreatingState } from '@/favorites/states/isFavoriteFolderCreatingState'; import { isFavoriteFolderCreatingState } from '@/favorites/states/isFavoriteFolderCreatingState';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection'; import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection';
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded'; import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
import { useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
@ -21,7 +21,7 @@ export const FavoriteFolderPickerFooter = ({
); );
const { openNavigationSection } = useNavigationSection('Favorites'); const { openNavigationSection } = useNavigationSection('Favorites');
const theme = useTheme(); const theme = useTheme();
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
return ( return (
<DropdownMenuItemsContainer scrollable={false}> <DropdownMenuItemsContainer scrollable={false}>
@ -31,7 +31,7 @@ export const FavoriteFolderPickerFooter = ({
setIsNavigationDrawerExpanded(true); setIsNavigationDrawerExpanded(true);
openNavigationSection(); openNavigationSection();
setIsFavoriteFolderCreating(true); setIsFavoriteFolderCreating(true);
closeDropdown(); closeDropdown(dropdownId);
}} }}
text="Add folder" text="Add folder"
LeftIcon={() => <IconPlus size={theme.icon.size.md} />} LeftIcon={() => <IconPlus size={theme.icon.size.md} />}

View File

@ -14,7 +14,7 @@ import { getRecordFilterOperands } from '@/object-record/record-filter/utils/get
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly'; import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
import { IconLibraryPlus, IconPlus } from 'twenty-ui/display'; import { IconLibraryPlus, IconPlus } from 'twenty-ui/display';
@ -44,7 +44,7 @@ export const AdvancedFilterAddFilterRuleSelect = ({
const newPositionInRecordFilterGroup = lastChildPosition + 1; const newPositionInRecordFilterGroup = lastChildPosition + 1;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const { defaultFieldMetadataItemForFilter } = const { defaultFieldMetadataItemForFilter } =
useDefaultFieldMetadataItemForFilter(); useDefaultFieldMetadataItemForFilter();
@ -57,7 +57,7 @@ export const AdvancedFilterAddFilterRuleSelect = ({
throw new Error('Missing default field metadata item for filter'); throw new Error('Missing default field metadata item for filter');
} }
closeDropdown(); closeDropdown(dropdownId);
const filterType = getFilterTypeFromFieldType( const filterType = getFilterTypeFromFieldType(
defaultFieldMetadataItemForFilter.type, defaultFieldMetadataItemForFilter.type,
@ -87,7 +87,7 @@ export const AdvancedFilterAddFilterRuleSelect = ({
}; };
const handleAddFilterGroup = () => { const handleAddFilterGroup = () => {
closeDropdown(); closeDropdown(dropdownId);
if (!isDefined(defaultFieldMetadataItemForFilter)) { if (!isDefined(defaultFieldMetadataItemForFilter)) {
throw new Error('Missing default field metadata item for filter'); throw new Error('Missing default field metadata item for filter');

View File

@ -6,7 +6,7 @@ import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRe
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { IconDotsVertical, IconTrash } from 'twenty-ui/display'; import { IconDotsVertical, IconTrash } from 'twenty-ui/display';
import { IconButton } from 'twenty-ui/input'; import { IconButton } from 'twenty-ui/input';
import { MenuItem } from 'twenty-ui/navigation'; import { MenuItem } from 'twenty-ui/navigation';
@ -20,7 +20,7 @@ export const AdvancedFilterRecordFilterGroupOptionsDropdown = ({
}: AdvancedFilterRecordFilterGroupOptionsDropdownProps) => { }: AdvancedFilterRecordFilterGroupOptionsDropdownProps) => {
const dropdownId = `advanced-filter-record-filter-group-options-${recordFilterGroupId}`; const dropdownId = `advanced-filter-record-filter-group-options-${recordFilterGroupId}`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const { removeRecordFilter } = useRemoveRecordFilter(); const { removeRecordFilter } = useRemoveRecordFilter();
const { removeRecordFilterGroup } = useRemoveRecordFilterGroup(); const { removeRecordFilterGroup } = useRemoveRecordFilterGroup();
@ -40,7 +40,7 @@ export const AdvancedFilterRecordFilterGroupOptionsDropdown = ({
removeRootRecordFilterGroupIfEmpty(); removeRootRecordFilterGroupIfEmpty();
closeDropdown(); closeDropdown(dropdownId);
}; };
return ( return (

View File

@ -10,7 +10,7 @@ import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope'; import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem'; import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
@ -31,13 +31,13 @@ export const AdvancedFilterRecordFilterOperandSelectContent = ({
}: AdvancedFilterRecordFilterOperandSelectContentProps) => { }: AdvancedFilterRecordFilterOperandSelectContentProps) => {
const dropdownId = `advanced-filter-view-filter-operand-${recordFilterId}`; const dropdownId = `advanced-filter-view-filter-operand-${recordFilterId}`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const { applyObjectFilterDropdownOperand } = const { applyObjectFilterDropdownOperand } =
useApplyObjectFilterDropdownOperand(); useApplyObjectFilterDropdownOperand();
const handleOperandChange = (operand: ViewFilterOperand) => { const handleOperandChange = (operand: ViewFilterOperand) => {
closeDropdown(); closeDropdown(dropdownId);
applyObjectFilterDropdownOperand(operand); applyObjectFilterDropdownOperand(operand);
}; };

View File

@ -9,7 +9,7 @@ import { DEFAULT_ADVANCED_FILTER_DROPDOWN_OFFSET } from '@/object-record/advance
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
import { IconDotsVertical, IconTrash } from 'twenty-ui/display'; import { IconDotsVertical, IconTrash } from 'twenty-ui/display';
@ -25,7 +25,7 @@ export const AdvancedFilterRecordFilterOptionsDropdown = ({
}: AdvancedFilterRecordFilterOptionsDropdownProps) => { }: AdvancedFilterRecordFilterOptionsDropdownProps) => {
const dropdownId = `advanced-filter-record-filter-options-${recordFilterId}`; const dropdownId = `advanced-filter-record-filter-options-${recordFilterId}`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const { removeRecordFilter } = useRemoveRecordFilter(); const { removeRecordFilter } = useRemoveRecordFilter();
const { removeRecordFilterGroup } = useRemoveRecordFilterGroup(); const { removeRecordFilterGroup } = useRemoveRecordFilterGroup();
@ -47,7 +47,7 @@ export const AdvancedFilterRecordFilterOptionsDropdown = ({
useRemoveRootRecordFilterGroupIfEmpty(); useRemoveRootRecordFilterGroupIfEmpty();
const handleRemove = async () => { const handleRemove = async () => {
closeDropdown(); closeDropdown(dropdownId);
if (isDefined(currentRecordFilter?.recordFilterGroupId)) { if (isDefined(currentRecordFilter?.recordFilterGroupId)) {
const isOnlyViewFilterInGroup = const isOnlyViewFilterInGroup =

View File

@ -1,11 +1,13 @@
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
export const useAdvancedFilterFieldSelectDropdown = (viewFilterId?: string) => { export const useAdvancedFilterFieldSelectDropdown = (viewFilterId?: string) => {
const advancedFilterFieldSelectDropdownId = `advanced-filter-view-filter-field-${viewFilterId}`; const advancedFilterFieldSelectDropdownId = `advanced-filter-view-filter-field-${viewFilterId}`;
const { closeDropdown: closeAdvancedFilterFieldSelectDropdown } = useDropdown( const { closeDropdown } = useCloseDropdown();
advancedFilterFieldSelectDropdownId,
); const closeAdvancedFilterFieldSelectDropdown = () => {
closeDropdown(advancedFilterFieldSelectDropdownId);
};
return { return {
closeAdvancedFilterFieldSelectDropdown, closeAdvancedFilterFieldSelectDropdown,

View File

@ -8,7 +8,7 @@ import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope'; import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { IconCheck } from 'twenty-ui/display'; import { IconCheck } from 'twenty-ui/display';
@ -41,7 +41,7 @@ export const ObjectFilterDropdownBooleanSelect = () => {
const { applyObjectFilterDropdownFilterValue } = const { applyObjectFilterDropdownFilterValue } =
useApplyObjectFilterDropdownFilterValue(); useApplyObjectFilterDropdownFilterValue();
const { closeDropdown } = useDropdown(); const { closeDropdown } = useCloseDropdown();
const handleOptionSelect = (newValue: boolean) => { const handleOptionSelect = (newValue: boolean) => {
applyObjectFilterDropdownFilterValue( applyObjectFilterDropdownFilterValue(

View File

@ -1,53 +0,0 @@
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
import { ObjectFilterDropdownOperandSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { ClickOutsideListenerContext } from '@/ui/utilities/pointer-event/contexts/ClickOutsideListenerContext';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconChevronDown } from 'twenty-ui/display';
import { getOperandLabel } from '../utils/getOperandLabel';
const StyledDropdownMenuHeader = styled(DropdownMenuHeader)`
cursor: pointer;
`;
export const OPERAND_DROPDOWN_CLICK_OUTSIDE_ID =
'object-filter-dropdown-operand-dropdown-click-outside-id';
export const ObjectFilterDropdownOperandDropdown = ({
filterDropdownId,
}: {
filterDropdownId?: string;
}) => {
const selectedOperandInDropdown = useRecoilComponentValueV2(
selectedOperandInDropdownComponentState,
);
const theme = useTheme();
const dropdownId = `${filterDropdownId}-operand-dropdown`;
return (
<ClickOutsideListenerContext.Provider
value={{ excludedClickOutsideId: OPERAND_DROPDOWN_CLICK_OUTSIDE_ID }}
>
<Dropdown
dropdownId={dropdownId}
clickableComponent={
<StyledDropdownMenuHeader
key={'selected-filter-operand'}
EndComponent={<IconChevronDown />}
>
{getOperandLabel(selectedOperandInDropdown)}
</StyledDropdownMenuHeader>
}
dropdownComponents={<ObjectFilterDropdownOperandSelect />}
dropdownOffset={{ x: parseInt(theme.spacing(2), 10) }}
/>
</ClickOutsideListenerContext.Provider>
);
};

View File

@ -1,65 +0,0 @@
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { useApplyObjectFilterDropdownOperand } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand';
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared/utils';
import { MenuItem } from 'twenty-ui/navigation';
import { getOperandLabel } from '../utils/getOperandLabel';
const StyledDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
background-color: ${({ theme }) => theme.background.primary};
border-radius: ${({ theme }) => theme.border.radius.md};
`;
export const ObjectFilterDropdownOperandSelect = () => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const subFieldNameUsedInDropdown = useRecoilComponentValueV2(
subFieldNameUsedInDropdownComponentState,
);
const { applyObjectFilterDropdownOperand } =
useApplyObjectFilterDropdownOperand();
const { closeDropdown } = useDropdown();
const operandsForFilterType = isDefined(fieldMetadataItemUsedInDropdown)
? getRecordFilterOperands({
filterType: getFilterTypeFromFieldType(
fieldMetadataItemUsedInDropdown.type,
),
subFieldName: subFieldNameUsedInDropdown,
})
: [];
const handleOperandChange = (newOperand: ViewFilterOperand) => {
applyObjectFilterDropdownOperand(newOperand);
};
return (
<DropdownContent widthInPixels={GenericDropdownContentWidth.ExtraLarge}>
<StyledDropdownMenuItemsContainer>
{operandsForFilterType.map((filterOperand, index) => (
<MenuItem
key={`select-filter-operand-${index}`}
onClick={() => {
handleOperandChange(filterOperand);
closeDropdown();
}}
text={getOperandLabel(filterOperand)}
/>
))}
</StyledDropdownMenuItemsContainer>
</DropdownContent>
);
};

View File

@ -4,7 +4,6 @@ import { Key } from 'ts-key-enum';
import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem'; import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem';
import { useOptionsForSelect } from '@/object-record/object-filter-dropdown/hooks/useOptionsForSelect'; import { useOptionsForSelect } from '@/object-record/object-filter-dropdown/hooks/useOptionsForSelect';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
@ -15,6 +14,7 @@ import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-recor
import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState';
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope'; import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement'; import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
@ -64,7 +64,7 @@ export const ObjectFilterDropdownOptionSelect = ({
[objectFilterDropdownCurrentRecordFilter?.value], [objectFilterDropdownCurrentRecordFilter?.value],
); );
const { closeDropdown } = useDropdown(); const { closeDropdown } = useCloseDropdown();
const { resetSelectedItem } = useSelectableList(componentInstanceId); const { resetSelectedItem } = useSelectableList(componentInstanceId);

View File

@ -9,7 +9,8 @@ import { useRecordGroupReorderConfirmationModal } from '@/object-record/record-g
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton'; import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
import { DROPDOWN_OFFSET_Y } from '@/ui/layout/dropdown/constants/DropdownOffsetY'; import { DROPDOWN_OFFSET_Y } from '@/ui/layout/dropdown/constants/DropdownOffsetY';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
import { Trans } from '@lingui/react/macro'; import { Trans } from '@lingui/react/macro';
@ -27,7 +28,11 @@ export const ObjectOptionsDropdown = ({
const { currentContentId, handleContentChange, handleResetContent } = const { currentContentId, handleContentChange, handleResetContent } =
useDropdownContextCurrentContentId<ObjectOptionsContentId>(); useDropdownContextCurrentContentId<ObjectOptionsContentId>();
const { isDropdownOpen } = useDropdown(OBJECT_OPTIONS_DROPDOWN_ID); const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
OBJECT_OPTIONS_DROPDOWN_ID,
);
const { const {
handleRecordGroupOrderChangeWithModal, handleRecordGroupOrderChangeWithModal,
handleRecordGroupReorderConfirmClick, handleRecordGroupReorderConfirmClick,

View File

@ -10,7 +10,7 @@ import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope'; import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem'; import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
@ -62,7 +62,7 @@ export const ObjectOptionsDropdownLayoutContent = () => {
const { availableFieldsForKanban, navigateToSelectSettings } = const { availableFieldsForKanban, navigateToSelectSettings } =
useGetAvailableFieldsForKanban(); useGetAvailableFieldsForKanban();
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const handleSelectKanbanViewType = async () => { const handleSelectKanbanViewType = async () => {
if (isDefaultView) { if (isDefaultView) {
@ -70,7 +70,7 @@ export const ObjectOptionsDropdownLayoutContent = () => {
} }
if (availableFieldsForKanban.length === 0) { if (availableFieldsForKanban.length === 0) {
navigateToSelectSettings(); navigateToSelectSettings();
closeDropdown(); closeDropdown(dropdownId);
} }
if (currentView?.type !== ViewType.Kanban) { if (currentView?.type !== ViewType.Kanban) {
await setAndPersistViewType(ViewType.Kanban); await setAndPersistViewType(ViewType.Kanban);

View File

@ -26,7 +26,7 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton'; import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope'; import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem'; import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
@ -194,7 +194,10 @@ export const ObjectSortDropdownButton = () => {
setIsRecordSortDirectionMenuUnfolded(false); setIsRecordSortDirectionMenuUnfolded(false);
}; };
const { isDropdownOpen } = useDropdown(OBJECT_SORT_DROPDOWN_ID); const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
OBJECT_SORT_DROPDOWN_ID,
);
const { t } = useLingui(); const { t } = useLingui();

View File

@ -1,14 +1,14 @@
import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId'; import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId';
import { useResetSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useResetSortDropdown'; import { useResetSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useResetSortDropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
export const useCloseSortDropdown = () => { export const useCloseSortDropdown = () => {
const { resetSortDropdown } = useResetSortDropdown(); const { resetSortDropdown } = useResetSortDropdown();
const { closeDropdown } = useDropdown(OBJECT_SORT_DROPDOWN_ID); const { closeDropdown } = useCloseDropdown();
const closeSortDropdown = () => { const closeSortDropdown = () => {
closeDropdown(); closeDropdown(OBJECT_SORT_DROPDOWN_ID);
resetSortDropdown(); resetSortDropdown();
}; };

View File

@ -1,18 +0,0 @@
import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId';
import { useResetSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useResetSortDropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
export const useToggleSortDropdown = () => {
const { toggleDropdown } = useDropdown(OBJECT_SORT_DROPDOWN_ID);
const { resetSortDropdown } = useResetSortDropdown();
const toggleSortDropdown = () => {
toggleDropdown();
resetSortDropdown();
};
return {
toggleSortDropdown,
};
};

View File

@ -1,8 +1,9 @@
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton'; import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { AppTooltip, TooltipDelay } from 'twenty-ui/display';
import { Tag } from 'twenty-ui/components'; import { Tag } from 'twenty-ui/components';
import { AppTooltip, TooltipDelay } from 'twenty-ui/display';
const StyledTag = styled(Tag)` const StyledTag = styled(Tag)`
width: 100%; width: 100%;
@ -21,7 +22,10 @@ export const RecordBoardColumnHeaderAggregateDropdownButton = ({
value?: string | number; value?: string | number;
tooltip?: string; tooltip?: string;
}) => { }) => {
const { isDropdownOpen } = useDropdown(dropdownId); const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
dropdownId,
);
return ( return (
<StyledHeader id={dropdownId} isUnfolded={isDropdownOpen}> <StyledHeader id={dropdownId} isUnfolded={isDropdownOpen}>

View File

@ -12,7 +12,7 @@ import {
import { MAX_DATE } from '@/ui/input/components/internal/date/constants/MaxDate'; import { MAX_DATE } from '@/ui/input/components/internal/date/constants/MaxDate';
import { MIN_DATE } from '@/ui/input/components/internal/date/constants/MinDate'; import { MIN_DATE } from '@/ui/input/components/internal/date/constants/MinDate';
import { useDateParser } from '@/ui/input/components/internal/hooks/useDateParser'; import { useDateParser } from '@/ui/input/components/internal/hooks/useDateParser';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { OverlayContainer } from '@/ui/layout/overlay/components/OverlayContainer'; import { OverlayContainer } from '@/ui/layout/overlay/components/OverlayContainer';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { isStandaloneVariableString } from '@/workflow/utils/isStandaloneVariableString'; import { isStandaloneVariableString } from '@/workflow/utils/isStandaloneVariableString';
@ -129,12 +129,8 @@ export const FormDateTimeFieldInput = ({
} }
}; };
const { closeDropdown: closeDropdownMonthSelect } = useDropdown( const { closeDropdown: closeDropdownMonthSelect } = useCloseDropdown();
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID, const { closeDropdown: closeDropdownYearSelect } = useCloseDropdown();
);
const { closeDropdown: closeDropdownYearSelect } = useDropdown(
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
);
const displayDatePicker = const displayDatePicker =
draftValue.type === 'static' && draftValue.mode === 'edit'; draftValue.type === 'static' && draftValue.mode === 'edit';
@ -148,8 +144,8 @@ export const FormDateTimeFieldInput = ({
callback: (event) => { callback: (event) => {
event.stopImmediatePropagation(); event.stopImmediatePropagation();
closeDropdownYearSelect(); closeDropdownYearSelect(MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID);
closeDropdownMonthSelect(); closeDropdownMonthSelect(MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID);
handlePickerClickOutside(); handlePickerClickOutside();
}, },
enabled: displayDatePicker, enabled: displayDatePicker,

View File

@ -11,7 +11,7 @@ import { SingleRecordPickerRecord } from '@/object-record/record-picker/single-r
import { InputLabel } from '@/ui/input/components/InputLabel'; import { InputLabel } from '@/ui/input/components/InputLabel';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { isStandaloneVariableString } from '@/workflow/utils/isStandaloneVariableString'; import { isStandaloneVariableString } from '@/workflow/utils/isStandaloneVariableString';
import { css, useTheme } from '@emotion/react'; import { css, useTheme } from '@emotion/react';
@ -103,7 +103,7 @@ export const FormSingleRecordPicker = ({
const dropdownId = `form-record-picker-${componentId}`; const dropdownId = `form-record-picker-${componentId}`;
const variablesDropdownId = `form-record-picker-${componentId}-variables`; const variablesDropdownId = `form-record-picker-${componentId}-variables`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const setRecordPickerSearchFilter = useSetRecoilComponentStateV2( const setRecordPickerSearchFilter = useSetRecoilComponentStateV2(
singleRecordPickerSearchFilterComponentState, singleRecordPickerSearchFilterComponentState,
@ -118,7 +118,7 @@ export const FormSingleRecordPicker = ({
selectedEntity: SingleRecordPickerRecord | null | undefined, selectedEntity: SingleRecordPickerRecord | null | undefined,
) => { ) => {
onChange?.(selectedEntity?.record?.id ?? ''); onChange?.(selectedEntity?.record?.id ?? '');
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleVariableTagInsert = (variable: string) => { const handleVariableTagInsert = (variable: string) => {
@ -193,7 +193,7 @@ export const FormSingleRecordPicker = ({
componentInstanceId={dropdownId} componentInstanceId={dropdownId}
EmptyIcon={IconForbid} EmptyIcon={IconForbid}
emptyLabel={'No ' + objectNameSingular} emptyLabel={'No ' + objectNameSingular}
onCancel={() => closeDropdown()} onCancel={() => closeDropdown(dropdownId)}
onRecordSelected={handleRecordSelected} onRecordSelected={handleRecordSelected}
objectNameSingular={objectNameSingular} objectNameSingular={objectNameSingular}
recordPickerInstanceId={dropdownId} recordPickerInstanceId={dropdownId}

View File

@ -1,7 +1,9 @@
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { MenuItemWithOptionDropdown } from '@/ui/navigation/menu-item/components/MenuItemWithOptionDropdown'; import { MenuItemWithOptionDropdown } from '@/ui/navigation/menu-item/components/MenuItemWithOptionDropdown';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { import {
IconBookmark, IconBookmark,
@ -33,7 +35,11 @@ export const MultiItemFieldMenuItem = <T,>({
showSetAsPrimaryButton, showSetAsPrimaryButton,
}: MultiItemFieldMenuItemProps<T>) => { }: MultiItemFieldMenuItemProps<T>) => {
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const { isDropdownOpen, closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
dropdownId,
);
const handleMouseEnter = () => setIsHovered(true); const handleMouseEnter = () => setIsHovered(true);
const handleMouseLeave = () => { const handleMouseLeave = () => {
@ -44,7 +50,7 @@ export const MultiItemFieldMenuItem = <T,>({
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
closeDropdown(); closeDropdown(dropdownId);
setIsHovered(false); setIsHovered(false);
onDelete?.(); onDelete?.();
}; };
@ -53,7 +59,7 @@ export const MultiItemFieldMenuItem = <T,>({
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
closeDropdown(); closeDropdown(dropdownId);
onSetAsPrimary?.(); onSetAsPrimary?.();
}; };
@ -61,7 +67,7 @@ export const MultiItemFieldMenuItem = <T,>({
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
closeDropdown(); closeDropdown(dropdownId);
onEdit?.(); onEdit?.();
}; };

View File

@ -34,10 +34,12 @@ import { isFieldCellSupported } from '@/object-record/utils/isFieldCellSupported
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useModal } from '@/ui/layout/modal/hooks/useModal'; import { useModal } from '@/ui/layout/modal/hooks/useModal';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { import {
@ -159,7 +161,11 @@ export const RecordDetailRelationRecordsListItem = ({
const dropdownScopeId = `record-field-card-menu-${relationFieldMetadataId}-${relationRecord.id}`; const dropdownScopeId = `record-field-card-menu-${relationFieldMetadataId}-${relationRecord.id}`;
const { closeDropdown, isDropdownOpen } = useDropdown(dropdownScopeId); const { closeDropdown } = useCloseDropdown();
const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
dropdownScopeId,
);
const dropdownId = getRecordFieldCardRelationPickerDropdownId({ const dropdownId = getRecordFieldCardRelationPickerDropdownId({
fieldDefinition, fieldDefinition,
@ -171,7 +177,7 @@ export const RecordDetailRelationRecordsListItem = ({
); );
const handleDetach = () => { const handleDetach = () => {
closeDropdown(); closeDropdown(dropdownScopeId);
const relationFieldMetadataItem = relationObjectMetadataItem.fields.find( const relationFieldMetadataItem = relationObjectMetadataItem.fields.find(
({ id }) => id === relationFieldMetadataId, ({ id }) => id === relationFieldMetadataId,
@ -196,7 +202,7 @@ export const RecordDetailRelationRecordsListItem = ({
}; };
const handleDelete = async () => { const handleDelete = async () => {
closeDropdown(); closeDropdown(dropdownScopeId);
openModal(getDeleteRelationModalId(relationRecord.id)); openModal(getDeleteRelationModalId(relationRecord.id));
}; };

View File

@ -16,8 +16,9 @@ import { AggregateOperations } from '@/object-record/record-table/constants/Aggr
import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector'; import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector';
import { AppPath } from '@/types/AppPath'; import { AppPath } from '@/types/AppPath';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { useLingui } from '@lingui/react/macro'; import { useLingui } from '@lingui/react/macro';
import { RelationType } from '~/generated-metadata/graphql'; import { RelationType } from '~/generated-metadata/graphql';
@ -69,7 +70,10 @@ export const RecordDetailRelationSection = ({
recordId, recordId,
}); });
const { isDropdownOpen } = useDropdown(dropdownId); const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
dropdownId,
);
const indexViewId = useRecoilValue( const indexViewId = useRecoilValue(
prefetchIndexViewIdFromObjectMetadataItemFamilySelector({ prefetchIndexViewIdFromObjectMetadataItemFamilySelector({

View File

@ -16,7 +16,7 @@ import { getRecordFieldCardRelationPickerDropdownId } from '@/object-record/reco
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { dropdownPlacementComponentStateV2 } from '@/ui/layout/dropdown/states/dropdownPlacementComponentStateV2'; import { dropdownPlacementComponentStateV2 } from '@/ui/layout/dropdown/states/dropdownPlacementComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@ -52,7 +52,7 @@ export const RecordDetailRelationSectionDropdownToMany = () => {
recordId, recordId,
}); });
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const dropdownPlacement = useRecoilComponentValueV2( const dropdownPlacement = useRecoilComponentValueV2(
dropdownPlacementComponentStateV2, dropdownPlacementComponentStateV2,
@ -125,7 +125,7 @@ export const RecordDetailRelationSectionDropdownToMany = () => {
}; };
const handleCreateNew = (searchString?: string) => { const handleCreateNew = (searchString?: string) => {
closeDropdown(); closeDropdown(dropdownId);
createNewRecordAndOpenRightDrawer?.(searchString); createNewRecordAndOpenRightDrawer?.(searchString);
}; };
@ -150,8 +150,12 @@ export const RecordDetailRelationSectionDropdownToMany = () => {
componentInstanceId={dropdownId} componentInstanceId={dropdownId}
onCreate={handleCreateNew} onCreate={handleCreateNew}
onChange={updateRelation} onChange={updateRelation}
onSubmit={closeDropdown} onSubmit={() => {
onClickOutside={closeDropdown} closeDropdown(dropdownId);
}}
onClickOutside={() => {
closeDropdown(dropdownId);
}}
layoutDirection={ layoutDirection={
dropdownPlacement?.includes('end') dropdownPlacement?.includes('end')
? 'search-bar-on-bottom' ? 'search-bar-on-bottom'

View File

@ -16,7 +16,7 @@ import { getRecordFieldCardRelationPickerDropdownId } from '@/object-record/reco
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { dropdownPlacementComponentStateV2 } from '@/ui/layout/dropdown/states/dropdownPlacementComponentStateV2'; import { dropdownPlacementComponentStateV2 } from '@/ui/layout/dropdown/states/dropdownPlacementComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@ -54,7 +54,7 @@ export const RecordDetailRelationSectionDropdownToOne = () => {
recordId, recordId,
}); });
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const dropdownPlacement = useRecoilComponentValueV2( const dropdownPlacement = useRecoilComponentValueV2(
dropdownPlacementComponentStateV2, dropdownPlacementComponentStateV2,
@ -80,7 +80,7 @@ export const RecordDetailRelationSectionDropdownToOne = () => {
const handleRelationPickerEntitySelected = ( const handleRelationPickerEntitySelected = (
selectedRelationEntity?: SingleRecordPickerRecord, selectedRelationEntity?: SingleRecordPickerRecord,
) => { ) => {
closeDropdown(); closeDropdown(dropdownId);
if (!selectedRelationEntity?.id || !relationFieldMetadataItem?.name) return; if (!selectedRelationEntity?.id || !relationFieldMetadataItem?.name) return;
@ -107,7 +107,7 @@ export const RecordDetailRelationSectionDropdownToOne = () => {
}; };
const handleCreateNew = (searchString?: string) => { const handleCreateNew = (searchString?: string) => {
closeDropdown(); closeDropdown(dropdownId);
createNewRecordAndOpenRightDrawer?.(searchString); createNewRecordAndOpenRightDrawer?.(searchString);
}; };
@ -138,7 +138,7 @@ export const RecordDetailRelationSectionDropdownToOne = () => {
onRecordSelected={handleRelationPickerEntitySelected} onRecordSelected={handleRelationPickerEntitySelected}
objectNameSingular={relationObjectMetadataNameSingular} objectNameSingular={relationObjectMetadataNameSingular}
recordPickerInstanceId={dropdownId} recordPickerInstanceId={dropdownId}
onCancel={closeDropdown} onCancel={() => closeDropdown(dropdownId)}
onCreate={shouldAllowCreateNew ? handleCreateNew : undefined} onCreate={shouldAllowCreateNew ? handleCreateNew : undefined}
layoutDirection={ layoutDirection={
dropdownPlacement?.includes('end') dropdownPlacement?.includes('end')

View File

@ -5,11 +5,12 @@ import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-me
import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId'; import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState'; import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
export const useTriggerActionMenuDropdown = ({ export const useTriggerActionMenuDropdown = ({
recordTableId, recordTableId,
}: { }: {
@ -32,7 +33,7 @@ export const useTriggerActionMenuDropdown = ({
actionMenuDropdownId, actionMenuDropdownId,
); );
const { openDropdown } = useDropdown(actionMenuDropdownId); const { openDropdown } = useOpenDropdown();
const { closeCommandMenu } = useCommandMenu(); const { closeCommandMenu } = useCommandMenu();
@ -57,13 +58,16 @@ export const useTriggerActionMenuDropdown = ({
closeCommandMenu(); closeCommandMenu();
openDropdown(); openDropdown({
dropdownComponentInstanceIdFromProps: actionMenuDropdownId,
});
}, },
[ [
recordIndexActionMenuDropdownPositionState, recordIndexActionMenuDropdownPositionState,
isRowSelectedFamilyState, isRowSelectedFamilyState,
closeCommandMenu, closeCommandMenu,
openDropdown, openDropdown,
actionMenuDropdownId,
], ],
); );

View File

@ -6,7 +6,7 @@ import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader'; import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent'; import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useContext } from 'react'; import { useContext } from 'react';
import { Key } from 'ts-key-enum'; import { Key } from 'ts-key-enum';
@ -22,13 +22,13 @@ export const RecordTableColumnAggregateFooterDropdownSubmenuContent = ({
const { dropdownId, resetContent } = useContext( const { dropdownId, resetContent } = useContext(
RecordTableColumnAggregateFooterDropdownContext, RecordTableColumnAggregateFooterDropdownContext,
); );
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
useScopedHotkeys( useScopedHotkeys(
[Key.Escape], [Key.Escape],
() => { () => {
resetContent(); resetContent();
closeDropdown(); closeDropdown(dropdownId);
}, },
TableOptionsHotkeyScope.Dropdown, TableOptionsHotkeyScope.Dropdown,
); );

View File

@ -2,7 +2,7 @@ import { getAggregateOperationLabel } from '@/object-record/record-board/record-
import { RecordTableColumnAggregateFooterDropdownContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterDropdownContext'; import { RecordTableColumnAggregateFooterDropdownContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterDropdownContext';
import { useViewFieldAggregateOperation } from '@/object-record/record-table/record-table-footer/hooks/useViewFieldAggregateOperation'; import { useViewFieldAggregateOperation } from '@/object-record/record-table/record-table-footer/hooks/useViewFieldAggregateOperation';
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations'; import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { ReactNode, useContext } from 'react'; import { ReactNode, useContext } from 'react';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
import { IconCheck } from 'twenty-ui/display'; import { IconCheck } from 'twenty-ui/display';
@ -23,7 +23,8 @@ export const RecordTableColumnAggregateFooterAggregateOperationMenuItems = ({
const { dropdownId, resetContent } = useContext( const { dropdownId, resetContent } = useContext(
RecordTableColumnAggregateFooterDropdownContext, RecordTableColumnAggregateFooterDropdownContext,
); );
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
return ( return (
<> <>
{aggregateOperations.map((operation) => ( {aggregateOperations.map((operation) => (
@ -31,7 +32,7 @@ export const RecordTableColumnAggregateFooterAggregateOperationMenuItems = ({
key={operation} key={operation}
onClick={() => { onClick={() => {
updateViewFieldAggregateOperation(operation); updateViewFieldAggregateOperation(operation);
closeDropdown(); closeDropdown(dropdownId);
}} }}
text={getAggregateOperationLabel(operation)} text={getAggregateOperationLabel(operation)}
RightIcon={ RightIcon={
@ -48,7 +49,7 @@ export const RecordTableColumnAggregateFooterAggregateOperationMenuItems = ({
onClick={() => { onClick={() => {
updateViewFieldAggregateOperation(null); updateViewFieldAggregateOperation(null);
resetContent(); resetContent();
closeDropdown(); closeDropdown(dropdownId);
}} }}
text={'None'} text={'None'}
RightIcon={ RightIcon={

View File

@ -7,7 +7,7 @@ import { getAvailableAggregateOperationsForFieldMetadataType } from '@/object-re
import { TableOptionsHotkeyScope } from '@/object-record/record-table/types/TableOptionsHotkeyScope'; import { TableOptionsHotkeyScope } from '@/object-record/record-table/types/TableOptionsHotkeyScope';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { t } from '@lingui/core/macro'; import { t } from '@lingui/core/macro';
import { useContext, useMemo } from 'react'; import { useContext, useMemo } from 'react';
@ -25,13 +25,13 @@ export const RecordTableColumnAggregateFooterMenuContent = () => {
fieldMetadataType, fieldMetadataType,
resetContent, resetContent,
} = useContext(RecordTableColumnAggregateFooterDropdownContext); } = useContext(RecordTableColumnAggregateFooterDropdownContext);
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const { objectMetadataItem } = useRecordTableContextOrThrow(); const { objectMetadataItem } = useRecordTableContextOrThrow();
useScopedHotkeys( useScopedHotkeys(
[Key.Escape], [Key.Escape],
() => { () => {
closeDropdown(); closeDropdown(dropdownId);
}, },
TableOptionsHotkeyScope.Dropdown, TableOptionsHotkeyScope.Dropdown,
); );
@ -106,7 +106,7 @@ export const RecordTableColumnAggregateFooterMenuContent = () => {
onClick={() => { onClick={() => {
updateViewFieldAggregateOperation(null); updateViewFieldAggregateOperation(null);
resetContent(); resetContent();
closeDropdown(); closeDropdown(dropdownId);
}} }}
text={t`None`} text={t`None`}
RightIcon={ RightIcon={

View File

@ -3,7 +3,7 @@ import { RECORD_TABLE_TD_WIDTH } from '@/object-record/record-table/record-table
import { RecordTableColumnAggregateFooterCellContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterCellContext'; import { RecordTableColumnAggregateFooterCellContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterCellContext';
import { RecordTableColumnAggregateFooterValue } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterValue'; import { RecordTableColumnAggregateFooterValue } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterValue';
import { hasAggregateOperationForViewFieldFamilySelector } from '@/object-record/record-table/record-table-footer/states/hasAggregateOperationForViewFieldFamilySelector'; import { hasAggregateOperationForViewFieldFamilySelector } from '@/object-record/record-table/record-table-footer/states/hasAggregateOperationForViewFieldFamilySelector';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
@ -60,7 +60,12 @@ export const RecordTableColumnAggregateFooterValueCell = ({
isFirstCell: boolean; isFirstCell: boolean;
}) => { }) => {
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const { isDropdownOpen } = useDropdown(dropdownId);
const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
dropdownId,
);
const theme = useTheme(); const theme = useTheme();
const { viewFieldId, fieldMetadataId } = useContext( const { viewFieldId, fieldMetadataId } = useContext(
RecordTableColumnAggregateFooterCellContext, RecordTableColumnAggregateFooterCellContext,

View File

@ -1,12 +1,12 @@
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useOpenRecordFilterChipFromTableHeader } from '@/object-record/record-table/record-table-header/hooks/useOpenRecordFilterChipFromTableHeader'; import { useOpenRecordFilterChipFromTableHeader } from '@/object-record/record-table/record-table-header/hooks/useOpenRecordFilterChipFromTableHeader';
import { onToggleColumnSortComponentState } from '@/object-record/record-table/states/onToggleColumnSortComponentState'; import { onToggleColumnSortComponentState } from '@/object-record/record-table/states/onToggleColumnSortComponentState';
import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector'; import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useToggleScrollWrapper } from '@/ui/utilities/scroll/hooks/useToggleScrollWrapper'; import { useToggleScrollWrapper } from '@/ui/utilities/scroll/hooks/useToggleScrollWrapper';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
@ -54,10 +54,12 @@ export const RecordTableColumnHeadDropdownMenu = ({
const { handleColumnVisibilityChange, handleMoveTableColumn } = const { handleColumnVisibilityChange, handleMoveTableColumn } =
useTableColumns(); useTableColumns();
const { closeDropdown } = useDropdown(column.fieldMetadataId + '-header'); const dropdownId = column.fieldMetadataId + '-header';
const { closeDropdown } = useCloseDropdown();
const closeDropdownAndToggleScroll = () => { const closeDropdownAndToggleScroll = () => {
closeDropdown(); closeDropdown(dropdownId);
toggleScrollXWrapper(true); toggleScrollXWrapper(true);
toggleScrollYWrapper(false); toggleScrollYWrapper(false);
}; };

View File

@ -11,7 +11,7 @@ import { SettingsPath } from '@/types/SettingsPath';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useLingui } from '@lingui/react/macro'; import { useLingui } from '@lingui/react/macro';
@ -23,7 +23,7 @@ export const RecordTableHeaderPlusButtonContent = () => {
const { t } = useLingui(); const { t } = useLingui();
const { objectMetadataItem } = useRecordTableContextOrThrow(); const { objectMetadataItem } = useRecordTableContextOrThrow();
const { closeDropdown } = useDropdown(); const { closeDropdown } = useCloseDropdown();
const hiddenTableColumns = useRecoilComponentValueV2( const hiddenTableColumns = useRecoilComponentValueV2(
hiddenTableColumnsComponentSelector, hiddenTableColumnsComponentSelector,

View File

@ -4,7 +4,7 @@ import { SelectableItem } from '@/object-record/select/types/SelectableItem';
import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/skeletons/DropdownMenuSkeletonItem'; import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/skeletons/DropdownMenuSkeletonItem';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope'; import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem'; import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
@ -35,7 +35,7 @@ export const MultipleSelectDropdown = ({
) => void; ) => void;
loadingItems: boolean; loadingItems: boolean;
}) => { }) => {
const { closeDropdown } = useDropdown(); const { closeDropdown } = useCloseDropdown();
const { resetSelectedItem } = useSelectableList(selectableListId); const { resetSelectedItem } = useSelectableList(selectableListId);

View File

@ -6,7 +6,7 @@ import { SettingsPath } from '@/types/SettingsPath';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useModal } from '@/ui/layout/modal/hooks/useModal'; import { useModal } from '@/ui/layout/modal/hooks/useModal';
import { Trans, useLingui } from '@lingui/react/macro'; import { Trans, useLingui } from '@lingui/react/macro';
@ -35,7 +35,7 @@ export const SettingsAccountsRowDropdownMenu = ({
const { openModal } = useModal(); const { openModal } = useModal();
const navigate = useNavigateSettings(); const navigate = useNavigateSettings();
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const { destroyOneRecord } = useDestroyOneRecord({ const { destroyOneRecord } = useDestroyOneRecord({
objectNameSingular: CoreObjectNameSingular.ConnectedAccount, objectNameSingular: CoreObjectNameSingular.ConnectedAccount,
@ -62,7 +62,7 @@ export const SettingsAccountsRowDropdownMenu = ({
text={t`Emails settings`} text={t`Emails settings`}
onClick={() => { onClick={() => {
navigate(SettingsPath.AccountsEmails); navigate(SettingsPath.AccountsEmails);
closeDropdown(); closeDropdown(dropdownId);
}} }}
/> />
<MenuItem <MenuItem
@ -70,7 +70,7 @@ export const SettingsAccountsRowDropdownMenu = ({
text={t`Calendar settings`} text={t`Calendar settings`}
onClick={() => { onClick={() => {
navigate(SettingsPath.AccountsCalendars); navigate(SettingsPath.AccountsCalendars);
closeDropdown(); closeDropdown(dropdownId);
}} }}
/> />
{account.authFailedAt && ( {account.authFailedAt && (
@ -79,7 +79,7 @@ export const SettingsAccountsRowDropdownMenu = ({
text={t`Reconnect`} text={t`Reconnect`}
onClick={() => { onClick={() => {
triggerProviderReconnect(account.provider, account.id); triggerProviderReconnect(account.provider, account.id);
closeDropdown(); closeDropdown(dropdownId);
}} }}
/> />
)} )}
@ -88,7 +88,7 @@ export const SettingsAccountsRowDropdownMenu = ({
LeftIcon={IconTrash} LeftIcon={IconTrash}
text={t`Remove account`} text={t`Remove account`}
onClick={() => { onClick={() => {
closeDropdown(); closeDropdown(dropdownId);
openModal(DELETE_ACCOUNT_MODAL_ID); openModal(DELETE_ACCOUNT_MODAL_ID);
}} }}
/> />

View File

@ -3,7 +3,7 @@ import { SettingsPath } from '@/types/SettingsPath';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { t } from '@lingui/core/macro'; import { t } from '@lingui/core/macro';
@ -66,7 +66,7 @@ const StyledButton = styled(Button)`
export const SettingsDataModelNewFieldBreadcrumbDropDown = () => { export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
const dropdownId = `settings-object-new-field-breadcrumb-dropdown`; const dropdownId = `settings-object-new-field-breadcrumb-dropdown`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const navigate = useNavigateSettings(); const navigate = useNavigateSettings();
const location = useLocation(); const location = useLocation();
const { objectNamePlural = '' } = useParams(); const { objectNamePlural = '' } = useParams();
@ -90,7 +90,7 @@ export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
fieldType ? { fieldType } : undefined, fieldType ? { fieldType } : undefined,
); );
} }
closeDropdown(); closeDropdown(dropdownId);
}; };
return ( return (

View File

@ -5,7 +5,7 @@ import { TextInput } from '@/ui/input/components/TextInput';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { t } from '@lingui/core/macro'; import { t } from '@lingui/core/macro';
@ -82,12 +82,8 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
const SELECT_COLOR_DROPDOWN_ID = `select-color-dropdown-${option.id}`; const SELECT_COLOR_DROPDOWN_ID = `select-color-dropdown-${option.id}`;
const SELECT_ACTIONS_DROPDOWN_ID = `select-actions-dropdown-${option.id}`; const SELECT_ACTIONS_DROPDOWN_ID = `select-actions-dropdown-${option.id}`;
const { closeDropdown: closeColorDropdown } = useDropdown( const { closeDropdown: closeColorDropdown } = useCloseDropdown();
SELECT_COLOR_DROPDOWN_ID, const { closeDropdown: closeActionsDropdown } = useCloseDropdown();
);
const { closeDropdown: closeActionsDropdown } = useDropdown(
SELECT_ACTIONS_DROPDOWN_ID,
);
const handleInputEnter = () => { const handleInputEnter = () => {
onInputEnter?.(); onInputEnter?.();
@ -126,7 +122,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
key={colorName} key={colorName}
onClick={() => { onClick={() => {
onChange({ ...option, color: colorName }); onChange({ ...option, color: colorName });
closeColorDropdown(); closeColorDropdown(SELECT_COLOR_DROPDOWN_ID);
}} }}
color={colorName} color={colorName}
selected={colorName === option.color} selected={colorName === option.color}
@ -171,7 +167,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
text={t`Remove as default`} text={t`Remove as default`}
onClick={() => { onClick={() => {
onRemoveAsDefault?.(); onRemoveAsDefault?.();
closeActionsDropdown(); closeActionsDropdown(SELECT_ACTIONS_DROPDOWN_ID);
}} }}
/> />
) : ( ) : (
@ -180,7 +176,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
text={t`Set as default`} text={t`Set as default`}
onClick={() => { onClick={() => {
onSetAsDefault?.(); onSetAsDefault?.();
closeActionsDropdown(); closeActionsDropdown(SELECT_ACTIONS_DROPDOWN_ID);
}} }}
/> />
)} )}
@ -191,7 +187,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
text={t`Remove option`} text={t`Remove option`}
onClick={() => { onClick={() => {
onRemove(); onRemove();
closeActionsDropdown(); closeActionsDropdown(SELECT_ACTIONS_DROPDOWN_ID);
}} }}
/> />
)} )}

View File

@ -2,7 +2,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
import { import {
IconArchive, IconArchive,
@ -31,21 +31,21 @@ export const SettingsObjectFieldActiveActionDropdown = ({
}: SettingsObjectFieldActiveActionDropdownProps) => { }: SettingsObjectFieldActiveActionDropdownProps) => {
const dropdownId = `${scopeKey}-settings-field-active-action-dropdown`; const dropdownId = `${scopeKey}-settings-field-active-action-dropdown`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const handleEdit = () => { const handleEdit = () => {
onEdit(); onEdit();
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleDeactivate = () => { const handleDeactivate = () => {
onDeactivate?.(); onDeactivate?.();
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleSetAsLabelIdentifier = () => { const handleSetAsLabelIdentifier = () => {
onSetAsLabelIdentifier?.(); onSetAsLabelIdentifier?.();
closeDropdown(); closeDropdown(dropdownId);
}; };
return ( return (

View File

@ -2,7 +2,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { t } from '@lingui/core/macro'; import { t } from '@lingui/core/macro';
import { import {
IconArchiveOff, IconArchiveOff,
@ -33,21 +33,21 @@ export const SettingsObjectFieldInactiveActionDropdown = ({
}: SettingsObjectFieldInactiveActionDropdownProps) => { }: SettingsObjectFieldInactiveActionDropdownProps) => {
const dropdownId = `${scopeKey}-settings-field-disabled-action-dropdown`; const dropdownId = `${scopeKey}-settings-field-disabled-action-dropdown`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const handleActivate = () => { const handleActivate = () => {
onActivate(); onActivate();
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleDelete = () => { const handleDelete = () => {
onDelete(); onDelete();
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleEdit = () => { const handleEdit = () => {
onEdit(); onEdit();
closeDropdown(); closeDropdown(dropdownId);
}; };
const isDeletable = isCustomField; const isDeletable = isCustomField;

View File

@ -2,7 +2,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { IconArchiveOff, IconDotsVertical, IconTrash } from 'twenty-ui/display'; import { IconArchiveOff, IconDotsVertical, IconTrash } from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input'; import { LightIconButton } from 'twenty-ui/input';
import { MenuItem } from 'twenty-ui/navigation'; import { MenuItem } from 'twenty-ui/navigation';
@ -22,16 +22,16 @@ export const SettingsObjectInactiveMenuDropDown = ({
}: SettingsObjectInactiveMenuDropDownProps) => { }: SettingsObjectInactiveMenuDropDownProps) => {
const dropdownId = `${scopeKey}-settings-object-inactive-menu-dropdown`; const dropdownId = `${scopeKey}-settings-object-inactive-menu-dropdown`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const handleActivate = () => { const handleActivate = () => {
onActivate(); onActivate();
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleDelete = () => { const handleDelete = () => {
onDelete(); onDelete();
closeDropdown(); closeDropdown(dropdownId);
}; };
return ( return (

View File

@ -13,7 +13,7 @@ import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDr
import { SettingsPath } from '@/types/SettingsPath'; import { SettingsPath } from '@/types/SettingsPath';
import { TextInput } from '@/ui/input/components/TextInput'; import { TextInput } from '@/ui/input/components/TextInput';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useModal } from '@/ui/layout/modal/hooks/useModal'; import { useModal } from '@/ui/layout/modal/hooks/useModal';
import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState'; import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
import { TableCell } from '@/ui/layout/table/components/TableCell'; import { TableCell } from '@/ui/layout/table/components/TableCell';
@ -92,7 +92,10 @@ export const SettingsRoleAssignment = ({
useState<SettingsRoleAssignmentConfirmationModalSelectedWorkspaceMember | null>( useState<SettingsRoleAssignmentConfirmationModalSelectedWorkspaceMember | null>(
null, null,
); );
const { closeDropdown } = useDropdown('role-member-select');
const dropdownId = 'role-member-select';
const { closeDropdown } = useCloseDropdown();
const [searchFilter, setSearchFilter] = useState(''); const [searchFilter, setSearchFilter] = useState('');
const currentWorkspaceMembers = useRecoilValue(currentWorkspaceMembersState); const currentWorkspaceMembers = useRecoilValue(currentWorkspaceMembersState);
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
@ -151,7 +154,7 @@ export const SettingsRoleAssignment = ({
role: existingRole, role: existingRole,
}); });
openModal(ROLE_ASSIGNMENT_CONFIRMATION_MODAL_ID); openModal(ROLE_ASSIGNMENT_CONFIRMATION_MODAL_ID);
closeDropdown(); closeDropdown(dropdownId);
}; };
const isModalOpened = useRecoilComponentValueV2( const isModalOpened = useRecoilComponentValueV2(

View File

@ -6,7 +6,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useLingui } from '@lingui/react/macro'; import { useLingui } from '@lingui/react/macro';
import { UnwrapRecoilValue } from 'recoil'; import { UnwrapRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
@ -26,7 +26,7 @@ export const SettingsSecuritySSORowDropdownMenu = ({
const { enqueueSnackBar } = useSnackBar(); const { enqueueSnackBar } = useSnackBar();
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const { deleteSSOIdentityProvider } = useDeleteSSOIdentityProvider(); const { deleteSSOIdentityProvider } = useDeleteSSOIdentityProvider();
const { updateSSOIdentityProvider } = useUpdateSSOIdentityProvider(); const { updateSSOIdentityProvider } = useUpdateSSOIdentityProvider();
@ -81,7 +81,7 @@ export const SettingsSecuritySSORowDropdownMenu = ({
text={SSOIdp.status === 'Active' ? t`Deactivate` : t`Activate`} text={SSOIdp.status === 'Active' ? t`Deactivate` : t`Activate`}
onClick={() => { onClick={() => {
toggleSSOIdentityProviderStatus(SSOIdp.id); toggleSSOIdentityProviderStatus(SSOIdp.id);
closeDropdown(); closeDropdown(dropdownId);
}} }}
/> />
<MenuItem <MenuItem
@ -90,7 +90,7 @@ export const SettingsSecuritySSORowDropdownMenu = ({
text={t`Delete`} text={t`Delete`}
onClick={() => { onClick={() => {
handleDeleteSSOIdentityProvider(SSOIdp.id); handleDeleteSSOIdentityProvider(SSOIdp.id);
closeDropdown(); closeDropdown(dropdownId);
}} }}
/> />
</DropdownMenuItemsContainer> </DropdownMenuItemsContainer>

View File

@ -4,7 +4,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { UnwrapRecoilValue, useSetRecoilState } from 'recoil'; import { UnwrapRecoilValue, useSetRecoilState } from 'recoil';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
import { IconDotsVertical, IconTrash } from 'twenty-ui/display'; import { IconDotsVertical, IconTrash } from 'twenty-ui/display';
@ -27,7 +27,7 @@ export const SettingsSecurityApprovedAccessDomainRowDropdownMenu = ({
const { enqueueSnackBar } = useSnackBar(); const { enqueueSnackBar } = useSnackBar();
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const [deleteApprovedAccessDomain] = useDeleteApprovedAccessDomainMutation(); const [deleteApprovedAccessDomain] = useDeleteApprovedAccessDomainMutation();
@ -70,7 +70,7 @@ export const SettingsSecurityApprovedAccessDomainRowDropdownMenu = ({
text="Delete" text="Delete"
onClick={() => { onClick={() => {
handleDeleteApprovedAccessDomain(); handleDeleteApprovedAccessDomain();
closeDropdown(); closeDropdown(dropdownId);
}} }}
/> />
</DropdownMenuItemsContainer> </DropdownMenuItemsContainer>

View File

@ -3,7 +3,7 @@ import { TextInputV2 } from '@/ui/input/components/TextInputV2';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { TableCell } from '@/ui/layout/table/components/TableCell'; import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableRow } from '@/ui/layout/table/components/TableRow'; import { TableRow } from '@/ui/layout/table/components/TableRow';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
@ -41,7 +41,7 @@ export const SettingsServerlessFunctionTabEnvironmentVariableTableRow = ({
const [editedEnvVariable, setEditedEnvVariable] = useState(envVariable); const [editedEnvVariable, setEditedEnvVariable] = useState(envVariable);
const [editMode, setEditMode] = useState(initialEditMode); const [editMode, setEditMode] = useState(initialEditMode);
const dropDownId = `settings-environment-variable-dropdown-${envVariable.id}`; const dropDownId = `settings-environment-variable-dropdown-${envVariable.id}`;
const { closeDropdown } = useDropdown(dropDownId); const { closeDropdown } = useCloseDropdown();
return editMode ? ( return editMode ? (
<StyledEditModeTableRow> <StyledEditModeTableRow>
@ -117,7 +117,7 @@ export const SettingsServerlessFunctionTabEnvironmentVariableTableRow = ({
LeftIcon={IconPencil} LeftIcon={IconPencil}
onClick={() => { onClick={() => {
setEditMode(true); setEditMode(true);
closeDropdown(); closeDropdown(dropDownId);
}} }}
/> />
<MenuItem <MenuItem
@ -125,7 +125,7 @@ export const SettingsServerlessFunctionTabEnvironmentVariableTableRow = ({
LeftIcon={IconTrash} LeftIcon={IconTrash}
onClick={() => { onClick={() => {
onDelete(); onDelete();
closeDropdown(); closeDropdown(dropDownId);
}} }}
/> />
</DropdownMenuItemsContainer> </DropdownMenuItemsContainer>

View File

@ -8,7 +8,7 @@ import { MatchColumnSelectFieldSelectDropdownContent } from '@/spreadsheet-impor
import { MatchColumnSelectSubFieldSelectDropdownContent } from '@/spreadsheet-import/components/MatchColumnSelectSubFieldSelectDropdownContent'; import { MatchColumnSelectSubFieldSelectDropdownContent } from '@/spreadsheet-import/components/MatchColumnSelectSubFieldSelectDropdownContent';
import { DO_NOT_IMPORT_OPTION_KEY } from '@/spreadsheet-import/constants/DoNotImportOptionKey'; import { DO_NOT_IMPORT_OPTION_KEY } from '@/spreadsheet-import/constants/DoNotImportOptionKey';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
import { IconChevronDown } from 'twenty-ui/display'; import { IconChevronDown } from 'twenty-ui/display';
@ -39,7 +39,7 @@ export const MatchColumnToFieldSelect = ({
}: MatchColumnToFieldSelectProps) => { }: MatchColumnToFieldSelectProps) => {
const dropdownId = `match-column-select-v2-dropdown-${columnIndex}`; const dropdownId = `match-column-select-v2-dropdown-${columnIndex}`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const [selectedFieldMetadataItem, setSelectedFieldMetadataItem] = const [selectedFieldMetadataItem, setSelectedFieldMetadataItem] =
useState<FieldMetadataItem | null>(null); useState<FieldMetadataItem | null>(null);
@ -81,7 +81,7 @@ export const MatchColumnToFieldSelect = ({
setSelectedFieldMetadataItem(null); setSelectedFieldMetadataItem(null);
onChange(correspondingOption); onChange(correspondingOption);
closeDropdown(); closeDropdown(dropdownId);
} }
}; };
@ -89,13 +89,13 @@ export const MatchColumnToFieldSelect = ({
selectedSuggestedOption: SelectOption, selectedSuggestedOption: SelectOption,
) => { ) => {
onChange(selectedSuggestedOption); onChange(selectedSuggestedOption);
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleDoNotImportSelect = () => { const handleDoNotImportSelect = () => {
if (isDefined(doNotImportOption)) { if (isDefined(doNotImportOption)) {
onChange(doNotImportOption); onChange(doNotImportOption);
closeDropdown(); closeDropdown(dropdownId);
} }
}; };
@ -109,7 +109,7 @@ export const MatchColumnToFieldSelect = ({
const handleCancelSelectClick = () => { const handleCancelSelectClick = () => {
setSelectedFieldMetadataItem(null); setSelectedFieldMetadataItem(null);
closeDropdown(); closeDropdown(dropdownId);
}; };
const doNotImportOption = options.find( const doNotImportOption = options.find(

View File

@ -7,7 +7,6 @@ import {
import { SpreadsheetMatchedOptions } from '@/spreadsheet-import/types/SpreadsheetMatchedOptions'; import { SpreadsheetMatchedOptions } from '@/spreadsheet-import/types/SpreadsheetMatchedOptions';
import { getFieldOptions } from '@/spreadsheet-import/utils/getFieldOptions'; import { getFieldOptions } from '@/spreadsheet-import/utils/getFieldOptions';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { Tag, TagColor } from 'twenty-ui/components'; import { Tag, TagColor } from 'twenty-ui/components';
@ -30,8 +29,6 @@ export const SubMatchingSelectDropdownButton = <T extends string>({
column, column,
placeholder, placeholder,
}: SubMatchingSelectDropdownButtonProps<T>) => { }: SubMatchingSelectDropdownButtonProps<T>) => {
const { openDropdown } = useDropdown();
const { fields } = useSpreadsheetImportInternal<T>(); const { fields } = useSpreadsheetImportInternal<T>();
const options = getFieldOptions(fields, column.value) as SelectOption[]; const options = getFieldOptions(fields, column.value) as SelectOption[];
const value = options.find((opt) => opt.value === option.value); const value = options.find((opt) => opt.value === option.value);
@ -39,11 +36,7 @@ export const SubMatchingSelectDropdownButton = <T extends string>({
const theme = useTheme(); const theme = useTheme();
return ( return (
<SubMatchingSelectControlContainer <SubMatchingSelectControlContainer cursor="pointer" id="control">
cursor="pointer"
onClick={() => openDropdown()}
id="control"
>
<Tag <Tag
text={value?.label ?? placeholder} text={value?.label ?? placeholder}
color={value?.color as TagColor} color={value?.color as TagColor}

View File

@ -10,7 +10,7 @@ import {
} from '@/spreadsheet-import/types/SpreadsheetColumn'; } from '@/spreadsheet-import/types/SpreadsheetColumn';
import { SpreadsheetMatchedOptions } from '@/spreadsheet-import/types/SpreadsheetMatchedOptions'; import { SpreadsheetMatchedOptions } from '@/spreadsheet-import/types/SpreadsheetMatchedOptions';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { SelectOption } from 'twenty-ui/input'; import { SelectOption } from 'twenty-ui/input';
@ -38,7 +38,7 @@ export const SubMatchingSelectRowRightDropdown = <T extends string>({
}: SubMatchingSelectRowRightDropdownProps<T>) => { }: SubMatchingSelectRowRightDropdownProps<T>) => {
const dropdownId = `sub-matching-select-dropdown-${option.entry}`; const dropdownId = `sub-matching-select-dropdown-${option.entry}`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const { fields } = useSpreadsheetImportInternal<T>(); const { fields } = useSpreadsheetImportInternal<T>();
const options = getFieldOptions(fields, column.value) as SelectOption[]; const options = getFieldOptions(fields, column.value) as SelectOption[];
@ -46,7 +46,7 @@ export const SubMatchingSelectRowRightDropdown = <T extends string>({
const handleSelect = (selectedOption: SelectOption) => { const handleSelect = (selectedOption: SelectOption) => {
onSubChange(selectedOption.value as T, column.index, option.entry ?? ''); onSubChange(selectedOption.value as T, column.index, option.entry ?? '');
closeDropdown(); closeDropdown(dropdownId);
}; };
return ( return (

View File

@ -3,23 +3,23 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { IconHelpCircle, IconMessage } from 'twenty-ui/display'; import { IconHelpCircle, IconMessage } from 'twenty-ui/display';
import { MenuItem } from 'twenty-ui/navigation'; import { MenuItem } from 'twenty-ui/navigation';
export const SupportDropdown = () => { export const SupportDropdown = () => {
const dropdownId = `support-field-active-action-dropdown`; const dropdownId = `support-field-active-action-dropdown`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const handleTalkToUs = () => { const handleTalkToUs = () => {
window.FrontChat?.('show'); window.FrontChat?.('show');
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleUserGuide = () => { const handleUserGuide = () => {
window.open('https://twenty.com/user-guide', '_blank'); window.open('https://twenty.com/user-guide', '_blank');
closeDropdown(); closeDropdown(dropdownId);
}; };
return ( return (

View File

@ -7,7 +7,7 @@ import {
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID, MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID,
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID, MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
} from '@/ui/input/components/internal/date/components/InternalDatePicker'; } from '@/ui/input/components/internal/date/components/InternalDatePicker';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState'; import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { Nullable } from 'twenty-ui/utilities'; import { Nullable } from 'twenty-ui/utilities';
@ -61,23 +61,19 @@ export const DateInput = ({
onSubmit?.(newDate); onSubmit?.(newDate);
}; };
const { closeDropdown: closeDropdownMonthSelect } = useDropdown( const { closeDropdown: closeDropdownMonthSelect } = useCloseDropdown();
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID, const { closeDropdown: closeDropdownYearSelect } = useCloseDropdown();
);
const { closeDropdown: closeDropdownYearSelect } = useDropdown(
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
);
const handleEnter = () => { const handleEnter = () => {
closeDropdownYearSelect(); closeDropdownYearSelect(MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID);
closeDropdownMonthSelect(); closeDropdownMonthSelect(MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID);
onEnter(internalValue); onEnter(internalValue);
}; };
const handleEscape = () => { const handleEscape = () => {
closeDropdownYearSelect(); closeDropdownYearSelect(MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID);
closeDropdownMonthSelect(); closeDropdownMonthSelect(MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID);
onEscape(internalValue); onEscape(internalValue);
}; };
@ -90,8 +86,8 @@ export const DateInput = ({
.getValue(); .getValue();
if (hotkeyScope?.scope === TableHotkeyScope.CellEditMode) { if (hotkeyScope?.scope === TableHotkeyScope.CellEditMode) {
closeDropdownYearSelect(); closeDropdownYearSelect(MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID);
closeDropdownMonthSelect(); closeDropdownMonthSelect(MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID);
onEscape(internalValue); onEscape(internalValue);
onClickOutside(event, internalValue); onClickOutside(event, internalValue);
} }

View File

@ -5,7 +5,6 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { arrayToChunks } from '~/utils/array/arrayToChunks'; import { arrayToChunks } from '~/utils/array/arrayToChunks';
@ -13,6 +12,8 @@ import { arrayToChunks } from '~/utils/array/arrayToChunks';
import { ICON_PICKER_DROPDOWN_CONTENT_WIDTH } from '@/ui/input/components/constants/IconPickerDropdownContentWidth'; import { ICON_PICKER_DROPDOWN_CONTENT_WIDTH } from '@/ui/input/components/constants/IconPickerDropdownContentWidth';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope'; import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { DropdownOffset } from '@/ui/layout/dropdown/types/DropdownOffset';
import { useSelectableListListenToEnterHotkeyOnItem } from '@/ui/layout/selectable-list/hooks/useSelectableListListenToEnterHotkeyOnItem'; import { useSelectableListListenToEnterHotkeyOnItem } from '@/ui/layout/selectable-list/hooks/useSelectableListListenToEnterHotkeyOnItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@ -25,7 +26,6 @@ import {
LightIconButton, LightIconButton,
} from 'twenty-ui/input'; } from 'twenty-ui/input';
import { IconPickerHotkeyScope } from '../types/IconPickerHotkeyScope'; import { IconPickerHotkeyScope } from '../types/IconPickerHotkeyScope';
import { DropdownOffset } from '@/ui/layout/dropdown/types/DropdownOffset';
export type IconPickerProps = { export type IconPickerProps = {
disabled?: boolean; disabled?: boolean;
@ -137,7 +137,7 @@ export const IconPicker = ({
} }
}; };
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const { getIcons, getIcon } = useIcons(); const { getIcons, getIcon } = useIcons();
const icons = getIcons(); const icons = getIcons();
@ -242,7 +242,7 @@ export const IconPicker = ({
iconKey={iconKey} iconKey={iconKey}
onClick={() => { onClick={() => {
onChange({ iconKey, Icon: getIcon(iconKey) }); onChange({ iconKey, Icon: getIcon(iconKey) });
closeDropdown(); closeDropdown(dropdownId);
}} }}
selectedIconKey={selectedIconKey} selectedIconKey={selectedIconKey}
Icon={getIcon(iconKey)} Icon={getIcon(iconKey)}

View File

@ -5,13 +5,13 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { SelectValue } from '@/ui/input/components/internal/select/types'; import { SelectValue } from '@/ui/input/components/internal/select/types';
import { SelectControl } from '@/ui/input/components/SelectControl'; import { SelectControl } from '@/ui/input/components/SelectControl';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope'; import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { DropdownOffset } from '@/ui/layout/dropdown/types/DropdownOffset'; import { DropdownOffset } from '@/ui/layout/dropdown/types/DropdownOffset';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem'; import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
@ -116,7 +116,7 @@ export const Select = <Value extends SelectValue>({
!isDefined(callToActionButton) && !isDefined(callToActionButton) &&
(!isDefined(emptyOption) || selectedOption !== emptyOption)); (!isDefined(emptyOption) || selectedOption !== emptyOption));
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const dropDownMenuWidth = const dropDownMenuWidth =
dropdownWidthAuto && selectContainerRef.current?.clientWidth dropdownWidthAuto && selectContainerRef.current?.clientWidth
@ -195,7 +195,7 @@ export const Select = <Value extends SelectValue>({
onEnter={() => { onEnter={() => {
onChange?.(option.value); onChange?.(option.value);
onBlur?.(); onBlur?.();
closeDropdown(); closeDropdown(dropdownId);
}} }}
> >
<MenuItemSelect <MenuItemSelect
@ -207,7 +207,7 @@ export const Select = <Value extends SelectValue>({
onClick={() => { onClick={() => {
onChange?.(option.value); onChange?.(option.value);
onBlur?.(); onBlur?.();
closeDropdown(); closeDropdown(dropdownId);
}} }}
/> />
</SelectableListItem> </SelectableListItem>

View File

@ -3,12 +3,12 @@ import styled from '@emotion/styled';
import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode'; import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { CurrencyPickerHotkeyScope } from '../types/CurrencyPickerHotkeyScope'; import { CurrencyPickerHotkeyScope } from '../types/CurrencyPickerHotkeyScope';
import { CURRENCIES } from '@/settings/data-model/constants/Currencies'; import { CURRENCIES } from '@/settings/data-model/constants/Currencies';
import { Currency } from '@/ui/input/components/internal/types/Currency'; import { Currency } from '@/ui/input/components/internal/types/Currency';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { IconChevronDown } from 'twenty-ui/display'; import { IconChevronDown } from 'twenty-ui/display';
import { CurrencyPickerDropdownSelect } from './CurrencyPickerDropdownSelect'; import { CurrencyPickerDropdownSelect } from './CurrencyPickerDropdownSelect';
@ -52,13 +52,13 @@ export const CurrencyPickerDropdownButton = ({
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const { closeDropdown } = useDropdown( const dropdownId = CurrencyPickerHotkeyScope.CurrencyPicker;
CurrencyPickerHotkeyScope.CurrencyPicker,
); const { closeDropdown } = useCloseDropdown();
const handleChange = (currency: Currency) => { const handleChange = (currency: Currency) => {
onChange(currency); onChange(currency);
closeDropdown(); closeDropdown(dropdownId);
}; };
const currency = CURRENCIES.find( const currency = CURRENCIES.find(

View File

@ -3,13 +3,12 @@ import { DateTime } from 'luxon';
import { lazy, Suspense, useContext } from 'react'; import { lazy, Suspense, useContext } from 'react';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader'; import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
import { AbsoluteDatePickerHeader } from '@/ui/input/components/internal/date/components/AbsoluteDatePickerHeader'; import { AbsoluteDatePickerHeader } from '@/ui/input/components/internal/date/components/AbsoluteDatePickerHeader';
import { DateTimeInput } from '@/ui/input/components/internal/date/components/DateTimeInput'; import { DateTimeInput } from '@/ui/input/components/internal/date/components/DateTimeInput';
import { RelativeDatePickerHeader } from '@/ui/input/components/internal/date/components/RelativeDatePickerHeader'; import { RelativeDatePickerHeader } from '@/ui/input/components/internal/date/components/RelativeDatePickerHeader';
import { getHighlightedDates } from '@/ui/input/components/internal/date/utils/getHighlightedDates'; import { getHighlightedDates } from '@/ui/input/components/internal/date/utils/getHighlightedDates';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { UserContext } from '@/users/contexts/UserContext'; import { UserContext } from '@/users/contexts/UserContext';
import { import {
VariableDateViewFilterValueDirection, VariableDateViewFilterValueDirection,
@ -342,12 +341,8 @@ export const DateTimePicker = ({
const { timeZone } = useContext(UserContext); const { timeZone } = useContext(UserContext);
const theme = useTheme(); const theme = useTheme();
const { closeDropdown: closeDropdownMonthSelect } = useDropdown( const { closeDropdown: closeDropdownMonthSelect } = useCloseDropdown();
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID, const { closeDropdown: closeDropdownYearSelect } = useCloseDropdown();
);
const { closeDropdown: closeDropdownYearSelect } = useDropdown(
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
);
const handleClear = () => { const handleClear = () => {
closeDropdowns(); closeDropdowns();
@ -355,8 +350,8 @@ export const DateTimePicker = ({
}; };
const closeDropdowns = () => { const closeDropdowns = () => {
closeDropdownYearSelect(); closeDropdownYearSelect(MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID);
closeDropdownMonthSelect(); closeDropdownMonthSelect(MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID);
}; };
const handleClose = (newDate: Date) => { const handleClose = (newDate: Date) => {

View File

@ -1,13 +1,15 @@
import { useCountries } from '@/ui/input/components/internal/hooks/useCountries'; import { useCountries } from '@/ui/input/components/internal/hooks/useCountries';
import { Country } from '@/ui/input/components/internal/types/Country'; import { Country } from '@/ui/input/components/internal/types/Country';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { PhoneCountryPickerDropdownSelect } from './PhoneCountryPickerDropdownSelect'; import { PhoneCountryPickerDropdownSelect } from './PhoneCountryPickerDropdownSelect';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import 'react-phone-number-input/style.css'; import 'react-phone-number-input/style.css';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
import { IconChevronDown, IconWorld } from 'twenty-ui/display'; import { IconChevronDown, IconWorld } from 'twenty-ui/display';
@ -75,12 +77,17 @@ export const PhoneCountryPickerDropdownButton = ({
const [selectedCountry, setSelectedCountry] = useState<Country>(); const [selectedCountry, setSelectedCountry] = useState<Country>();
const { isDropdownOpen, closeDropdown } = useDropdown( const dropdownId = 'country-picker-dropdown-id';
'country-picker-dropdown-id',
const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
dropdownId,
); );
const { closeDropdown } = useCloseDropdown();
const handleChange = (countryCode: string) => { const handleChange = (countryCode: string) => {
closeDropdown(); closeDropdown(dropdownId);
onChange(countryCode); onChange(countryCode);
}; };

View File

@ -3,11 +3,14 @@ import { DropdownInternalContainer } from '@/ui/layout/dropdown/components/inter
import { DROPDOWN_RESIZE_MIN_HEIGHT } from '@/ui/layout/dropdown/constants/DropdownResizeMinHeight'; import { DROPDOWN_RESIZE_MIN_HEIGHT } from '@/ui/layout/dropdown/constants/DropdownResizeMinHeight';
import { DROPDOWN_RESIZE_MIN_WIDTH } from '@/ui/layout/dropdown/constants/DropdownResizeMinWidth'; import { DROPDOWN_RESIZE_MIN_WIDTH } from '@/ui/layout/dropdown/constants/DropdownResizeMinWidth';
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext'; import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
import { useToggleDropdown } from '@/ui/layout/dropdown/hooks/useToggleDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { dropdownMaxHeightComponentState } from '@/ui/layout/dropdown/states/internal/dropdownMaxHeightComponentState'; import { dropdownMaxHeightComponentState } from '@/ui/layout/dropdown/states/internal/dropdownMaxHeightComponentState';
import { dropdownMaxWidthComponentState } from '@/ui/layout/dropdown/states/internal/dropdownMaxWidthComponentState'; import { dropdownMaxWidthComponentState } from '@/ui/layout/dropdown/states/internal/dropdownMaxWidthComponentState';
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { DropdownOffset } from '@/ui/layout/dropdown/types/DropdownOffset'; import { DropdownOffset } from '@/ui/layout/dropdown/types/DropdownOffset';
import { GlobalHotkeysConfig } from '@/ui/utilities/hotkey/types/GlobalHotkeysConfig'; import { GlobalHotkeysConfig } from '@/ui/utilities/hotkey/types/GlobalHotkeysConfig';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { import {
@ -24,7 +27,6 @@ import { Keys } from 'react-hotkeys-hook';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
import { useIsMobile } from 'twenty-ui/utilities'; import { useIsMobile } from 'twenty-ui/utilities';
import { useDropdown } from '../hooks/useDropdown';
type Width = `${string}px` | `${number}%` | 'auto' | number; type Width = `${string}px` | `${number}%` | 'auto' | number;
const StyledDropdownFallbackAnchor = styled.div` const StyledDropdownFallbackAnchor = styled.div`
@ -75,7 +77,12 @@ export const Dropdown = ({
excludedClickOutsideIds, excludedClickOutsideIds,
isDropdownInModal = false, isDropdownInModal = false,
}: DropdownProps) => { }: DropdownProps) => {
const { isDropdownOpen, toggleDropdown } = useDropdown(dropdownId); const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
dropdownId,
);
const { toggleDropdown } = useToggleDropdown();
const isUsingOffset = const isUsingOffset =
isDefined(dropdownOffset?.x) || isDefined(dropdownOffset?.y); isDefined(dropdownOffset?.x) || isDefined(dropdownOffset?.y);
@ -147,10 +154,12 @@ export const Dropdown = ({
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
toggleDropdown(globalHotkeysConfig); toggleDropdown({
onClickOutside?.(); dropdownComponentInstanceIdFromProps: dropdownId,
globalHotkeysConfig,
});
}, },
[globalHotkeysConfig, onClickOutside, toggleDropdown], [globalHotkeysConfig, toggleDropdown, dropdownId],
); );
return ( return (

View File

@ -1,7 +1,7 @@
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
@ -43,7 +43,7 @@ export const DropdownMenuInnerSelect = ({
}: DropdownMenuInnerSelectProps) => { }: DropdownMenuInnerSelectProps) => {
const theme = useTheme(); const theme = useTheme();
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
return ( return (
<Dropdown <Dropdown
@ -61,7 +61,7 @@ export const DropdownMenuInnerSelect = ({
key={`dropdown-menu-inner-select-item-${selectOption.value}`} key={`dropdown-menu-inner-select-item-${selectOption.value}`}
onClick={() => { onClick={() => {
onChange(selectOption); onChange(selectOption);
closeDropdown(); closeDropdown(dropdownId);
}} }}
text={selectOption.label} text={selectOption.label}
disabled={selectOption.disabled} disabled={selectOption.disabled}

View File

@ -7,6 +7,11 @@ import { useAvailableComponentInstanceId } from '@/ui/utilities/state/component-
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
type ToggleDropdownArgs = {
dropdownComponentInstanceIdFromProps?: string;
globalHotkeysConfig?: Partial<GlobalHotkeysConfig>;
};
export const useToggleDropdown = () => { export const useToggleDropdown = () => {
const dropdownComponentInstanceIdFromContext = const dropdownComponentInstanceIdFromContext =
useAvailableComponentInstanceId(DropdownComponentInstanceContext); useAvailableComponentInstanceId(DropdownComponentInstanceContext);
@ -16,15 +21,9 @@ export const useToggleDropdown = () => {
const toggleDropdown = useRecoilCallback( const toggleDropdown = useRecoilCallback(
({ snapshot }) => ({ snapshot }) =>
({ (args?: ToggleDropdownArgs | null | undefined) => {
dropdownComponentInstanceIdFromProps,
globalHotkeysConfig,
}: {
dropdownComponentInstanceIdFromProps?: string;
globalHotkeysConfig?: Partial<GlobalHotkeysConfig>;
}) => {
const dropdownComponentInstanceId = const dropdownComponentInstanceId =
dropdownComponentInstanceIdFromProps ?? args?.dropdownComponentInstanceIdFromProps ??
dropdownComponentInstanceIdFromContext; dropdownComponentInstanceIdFromContext;
if (!isDefined(dropdownComponentInstanceId)) { if (!isDefined(dropdownComponentInstanceId)) {
@ -44,7 +43,7 @@ export const useToggleDropdown = () => {
} else { } else {
openDropdown({ openDropdown({
dropdownComponentInstanceIdFromProps: dropdownComponentInstanceId, dropdownComponentInstanceIdFromProps: dropdownComponentInstanceId,
globalHotkeysConfig, globalHotkeysConfig: args?.globalHotkeysConfig,
}); });
} }
}, },

View File

@ -1,4 +1,4 @@
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { TAB_LIST_GAP } from '@/ui/layout/tab-list/constants/TabListGap'; import { TAB_LIST_GAP } from '@/ui/layout/tab-list/constants/TabListGap';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState'; import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
import { TabListComponentInstanceContext } from '@/ui/layout/tab-list/states/contexts/TabListComponentInstanceContext'; import { TabListComponentInstanceContext } from '@/ui/layout/tab-list/states/contexts/TabListComponentInstanceContext';
@ -87,7 +87,7 @@ export const TabList = ({
const hasHiddenTabs = hiddenTabsCount > 0; const hasHiddenTabs = hiddenTabsCount > 0;
const dropdownId = `tab-overflow-${componentInstanceId}`; const dropdownId = `tab-overflow-${componentInstanceId}`;
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const isActiveTabHidden = useMemo(() => { const isActiveTabHidden = useMemo(() => {
if (!hasHiddenTabs) return false; if (!hasHiddenTabs) return false;
@ -215,7 +215,7 @@ export const TabList = ({
<TabListDropdown <TabListDropdown
dropdownId={dropdownId} dropdownId={dropdownId}
onClose={() => { onClose={() => {
closeDropdown(); closeDropdown(dropdownId);
}} }}
overflow={{ overflow={{
hiddenTabsCount, hiddenTabsCount,

View File

@ -16,7 +16,7 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenu
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent'; import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { MULTI_WORKSPACE_DROPDOWN_ID } from '@/ui/navigation/navigation-drawer/constants/MultiWorkspaceDropdownId'; import { MULTI_WORKSPACE_DROPDOWN_ID } from '@/ui/navigation/navigation-drawer/constants/MultiWorkspaceDropdownId';
import { multiWorkspaceDropdownState } from '@/ui/navigation/navigation-drawer/states/multiWorkspaceDropdownState'; import { multiWorkspaceDropdownState } from '@/ui/navigation/navigation-drawer/states/multiWorkspaceDropdownState';
import { useColorScheme } from '@/ui/theme/hooks/useColorScheme'; import { useColorScheme } from '@/ui/theme/hooks/useColorScheme';
@ -57,7 +57,7 @@ export const MultiWorkspaceDropdownDefaultComponents = () => {
const availableWorkspacesCount = const availableWorkspacesCount =
countAvailableWorkspaces(availableWorkspaces); countAvailableWorkspaces(availableWorkspaces);
const { buildWorkspaceUrl } = useBuildWorkspaceUrl(); const { buildWorkspaceUrl } = useBuildWorkspaceUrl();
const { closeDropdown } = useDropdown(MULTI_WORKSPACE_DROPDOWN_ID); const { closeDropdown } = useCloseDropdown();
const { signOut } = useAuth(); const { signOut } = useAuth();
const { enqueueSnackBar } = useSnackBar(); const { enqueueSnackBar } = useSnackBar();
const { colorScheme, colorSchemeList } = useColorScheme(); const { colorScheme, colorSchemeList } = useColorScheme();
@ -195,7 +195,9 @@ export const MultiWorkspaceDropdownDefaultComponents = () => {
/> />
<UndecoratedLink <UndecoratedLink
to={getSettingsPath(SettingsPath.WorkspaceMembersPage)} to={getSettingsPath(SettingsPath.WorkspaceMembersPage)}
onClick={closeDropdown} onClick={() => {
closeDropdown(MULTI_WORKSPACE_DROPDOWN_ID);
}}
> >
<MenuItem LeftIcon={IconUserPlus} text={t`Invite user`} /> <MenuItem LeftIcon={IconUserPlus} text={t`Invite user`} />
</UndecoratedLink> </UndecoratedLink>

View File

@ -9,7 +9,7 @@ import { SOFT_DELETE_FILTER_FIELD_NAME } from '@/object-record/record-filter/con
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter'; import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { getAllRecordFilterDescendantsOfRecordFilterGroup } from '@/object-record/record-filter/utils/getAllRecordFilterDescendantsOfRecordFilterGroup'; import { getAllRecordFilterDescendantsOfRecordFilterGroup } from '@/object-record/record-filter/utils/getAllRecordFilterDescendantsOfRecordFilterGroup';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip'; import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId'; import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
@ -19,7 +19,7 @@ import { isDefined } from 'twenty-shared/utils';
import { IconFilter } from 'twenty-ui/display'; import { IconFilter } from 'twenty-ui/display';
export const AdvancedFilterChip = () => { export const AdvancedFilterChip = () => {
const { closeDropdown } = useDropdown(ADVANCED_FILTER_DROPDOWN_ID); const { closeDropdown } = useCloseDropdown();
const currentRecordFilterGroups = useRecoilComponentValueV2( const currentRecordFilterGroups = useRecoilComponentValueV2(
currentRecordFilterGroupsComponentState, currentRecordFilterGroupsComponentState,
@ -49,7 +49,7 @@ export const AdvancedFilterChip = () => {
}); });
const handleRemoveClick = () => { const handleRemoveClick = () => {
closeDropdown(); closeDropdown(ADVANCED_FILTER_DROPDOWN_ID);
const viewFilterGroupIds = currentRecordFilterGroups.map( const viewFilterGroupIds = currentRecordFilterGroups.map(
(recordFilterGroup) => recordFilterGroup.id, (recordFilterGroup) => recordFilterGroup.id,

View File

@ -2,12 +2,12 @@ import { useCallback } from 'react';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { EditableFilterChip } from '@/views/components/EditableFilterChip'; import { EditableFilterChip } from '@/views/components/EditableFilterChip';
import { ObjectFilterDropdownFilterInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput'; import { ObjectFilterDropdownFilterInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput';
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter'; import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
import { isRecordFilterConsideredEmpty } from '@/object-record/record-filter/utils/isRecordFilterConsideredEmpty'; import { isRecordFilterConsideredEmpty } from '@/object-record/record-filter/utils/isRecordFilterConsideredEmpty';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useSetEditableFilterChipDropdownStates } from '@/views/hooks/useSetEditableFilterChipDropdownStates'; import { useSetEditableFilterChipDropdownStates } from '@/views/hooks/useSetEditableFilterChipDropdownStates';
type EditableFilterDropdownButtonProps = { type EditableFilterDropdownButtonProps = {
@ -17,12 +17,14 @@ type EditableFilterDropdownButtonProps = {
export const EditableFilterDropdownButton = ({ export const EditableFilterDropdownButton = ({
recordFilter, recordFilter,
}: EditableFilterDropdownButtonProps) => { }: EditableFilterDropdownButtonProps) => {
const { closeDropdown } = useDropdown(recordFilter.id); const dropdownId = recordFilter.id;
const { closeDropdown } = useCloseDropdown();
const { removeRecordFilter } = useRemoveRecordFilter(); const { removeRecordFilter } = useRemoveRecordFilter();
const handleRemove = () => { const handleRemove = () => {
closeDropdown(); closeDropdown(dropdownId);
removeRecordFilter({ recordFilterId: recordFilter.id }); removeRecordFilter({ recordFilterId: recordFilter.id });
}; };

View File

@ -4,7 +4,8 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
@ -43,12 +44,8 @@ export const UpdateViewButtonGroup = () => {
contextStoreCurrentViewIdComponentState, contextStoreCurrentViewIdComponentState,
); );
const { closeDropdown: closeUpdateViewButtonDropdown } = useDropdown( const { closeDropdown: closeUpdateViewButtonDropdown } = useCloseDropdown();
UPDATE_VIEW_BUTTON_DROPDOWN_ID, const { openDropdown: openViewPickerDropdown } = useOpenDropdown();
);
const { openDropdown: openViewPickerDropdown } = useDropdown(
VIEW_PICKER_DROPDOWN_ID,
);
const { currentView } = useGetCurrentViewOnly(); const { currentView } = useGetCurrentViewOnly();
const setViewPickerReferenceViewId = useSetRecoilComponentStateV2( const setViewPickerReferenceViewId = useSetRecoilComponentStateV2(
@ -60,11 +57,13 @@ export const UpdateViewButtonGroup = () => {
return; return;
} }
openViewPickerDropdown(); openViewPickerDropdown({
dropdownComponentInstanceIdFromProps: VIEW_PICKER_DROPDOWN_ID,
});
setViewPickerReferenceViewId(currentViewId); setViewPickerReferenceViewId(currentViewId);
setViewPickerMode('create-from-current'); setViewPickerMode('create-from-current');
closeUpdateViewButtonDropdown(); closeUpdateViewButtonDropdown(UPDATE_VIEW_BUTTON_DROPDOWN_ID);
}; };
const handleCreateViewClick = () => { const handleCreateViewClick = () => {

View File

@ -1,13 +1,13 @@
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId'; import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { useResetFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useResetFilterDropdown'; import { useResetFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useResetFilterDropdown';
import { useToggleDropdown } from '@/ui/layout/dropdown/hooks/useToggleDropdown';
import { t } from '@lingui/core/macro'; import { t } from '@lingui/core/macro';
import { IconPlus } from 'twenty-ui/display'; import { IconPlus } from 'twenty-ui/display';
import { LightButton } from 'twenty-ui/input'; import { LightButton } from 'twenty-ui/input';
export const ViewBarDetailsAddFilterButton = () => { export const ViewBarDetailsAddFilterButton = () => {
const { toggleDropdown } = useDropdown(VIEW_BAR_FILTER_DROPDOWN_ID); const { toggleDropdown } = useToggleDropdown();
const { resetFilterDropdown } = useResetFilterDropdown( const { resetFilterDropdown } = useResetFilterDropdown(
VIEW_BAR_FILTER_DROPDOWN_ID, VIEW_BAR_FILTER_DROPDOWN_ID,
@ -15,7 +15,9 @@ export const ViewBarDetailsAddFilterButton = () => {
const handleClick = () => { const handleClick = () => {
resetFilterDropdown(); resetFilterDropdown();
toggleDropdown(); toggleDropdown({
dropdownComponentInstanceIdFromProps: VIEW_BAR_FILTER_DROPDOWN_ID,
});
}; };
return ( return (

View File

@ -1,10 +1,14 @@
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton'; import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId'; import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { Trans } from '@lingui/react/macro'; import { Trans } from '@lingui/react/macro';
export const ViewBarFilterButton = () => { export const ViewBarFilterButton = () => {
const { isDropdownOpen } = useDropdown(VIEW_BAR_FILTER_DROPDOWN_ID); const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
VIEW_BAR_FILTER_DROPDOWN_ID,
);
return ( return (
<StyledHeaderDropdownButton isUnfolded={isDropdownOpen}> <StyledHeaderDropdownButton isUnfolded={isDropdownOpen}>

View File

@ -3,7 +3,6 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId'; import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { useVectorSearchFilterActions } from '@/views/hooks/useVectorSearchFilterActions'; import { useVectorSearchFilterActions } from '@/views/hooks/useVectorSearchFilterActions';
import { OPERAND_DROPDOWN_CLICK_OUTSIDE_ID } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandDropdown';
import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState';
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter'; import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
import { isRecordFilterConsideredEmpty } from '@/object-record/record-filter/utils/isRecordFilterConsideredEmpty'; import { isRecordFilterConsideredEmpty } from '@/object-record/record-filter/utils/isRecordFilterConsideredEmpty';
@ -53,7 +52,6 @@ export const ViewBarFilterDropdown = () => {
dropdownComponents={<ViewBarFilterDropdownContent />} dropdownComponents={<ViewBarFilterDropdownContent />}
dropdownOffset={{ y: 8 }} dropdownOffset={{ y: 8 }}
onClickOutside={handleDropdownClickOutside} onClickOutside={handleDropdownClickOutside}
excludedClickOutsideIds={[OPERAND_DROPDOWN_CLICK_OUTSIDE_ID]}
/> />
); );
}; };

View File

@ -12,7 +12,8 @@ import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDrop
import { useSetRecordFilterUsedInAdvancedFilterDropdownRow } from '@/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow'; import { useSetRecordFilterUsedInAdvancedFilterDropdownRow } from '@/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow';
import { RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator'; import { RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
import { useCreateEmptyRecordFilterFromFieldMetadataItem } from '@/object-record/record-filter/hooks/useCreateEmptyRecordFilterFromFieldMetadataItem'; import { useCreateEmptyRecordFilterFromFieldMetadataItem } from '@/object-record/record-filter/hooks/useCreateEmptyRecordFilterFromFieldMetadataItem';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId'; import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly'; import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
@ -40,13 +41,9 @@ export const ViewBarFilterDropdownAdvancedFilterButton = () => {
VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS.ADVANCED_FILTER, VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS.ADVANCED_FILTER,
); );
const { openDropdown: openAdvancedFilterDropdown } = useDropdown( const { openDropdown: openAdvancedFilterDropdown } = useOpenDropdown();
ADVANCED_FILTER_DROPDOWN_ID,
);
const { closeDropdown: closeObjectFilterDropdown } = useDropdown( const { closeDropdown: closeObjectFilterDropdown } = useCloseDropdown();
VIEW_BAR_FILTER_DROPDOWN_ID,
);
const { currentView } = useGetCurrentViewOnly(); const { currentView } = useGetCurrentViewOnly();
@ -118,8 +115,10 @@ export const ViewBarFilterDropdownAdvancedFilterButton = () => {
setRecordFilterUsedInAdvancedFilterDropdownRow(newRecordFilter); setRecordFilterUsedInAdvancedFilterDropdownRow(newRecordFilter);
} }
closeObjectFilterDropdown(); closeObjectFilterDropdown(VIEW_BAR_FILTER_DROPDOWN_ID);
openAdvancedFilterDropdown(); openAdvancedFilterDropdown({
dropdownComponentInstanceIdFromProps: ADVANCED_FILTER_DROPDOWN_ID,
});
}; };
return ( return (

View File

@ -3,7 +3,8 @@ import styled from '@emotion/styled';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { StyledDropdownButtonContainer } from '@/ui/layout/dropdown/components/StyledDropdownButtonContainer'; import { StyledDropdownButtonContainer } from '@/ui/layout/dropdown/components/StyledDropdownButtonContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useGetRecordIndexTotalCount } from '@/views/hooks/internal/useGetRecordIndexTotalCount'; import { useGetRecordIndexTotalCount } from '@/views/hooks/internal/useGetRecordIndexTotalCount';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly'; import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { ViewPickerContentCreateMode } from '@/views/view-picker/components/ViewPickerContentCreateMode'; import { ViewPickerContentCreateMode } from '@/views/view-picker/components/ViewPickerContentCreateMode';
@ -51,7 +52,8 @@ export const ViewPickerDropdown = () => {
const { totalCount } = useGetRecordIndexTotalCount(); const { totalCount } = useGetRecordIndexTotalCount();
const { isDropdownOpen: isViewsListDropdownOpen } = useDropdown( const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
VIEW_PICKER_DROPDOWN_ID, VIEW_PICKER_DROPDOWN_ID,
); );
@ -61,7 +63,7 @@ export const ViewPickerDropdown = () => {
const CurrentViewIcon = getIcon(currentView?.icon); const CurrentViewIcon = getIcon(currentView?.icon);
const handleClickOutside = async () => { const handleClickOutside = async () => {
if (isViewsListDropdownOpen && viewPickerMode === 'edit') { if (isDropdownOpen && viewPickerMode === 'edit') {
await updateViewFromCurrentState(); await updateViewFromCurrentState();
} }
setViewPickerMode('list'); setViewPickerMode('list');
@ -74,7 +76,7 @@ export const ViewPickerDropdown = () => {
dropdownPlacement="bottom-start" dropdownPlacement="bottom-start"
onClickOutside={handleClickOutside} onClickOutside={handleClickOutside}
clickableComponent={ clickableComponent={
<StyledDropdownButtonContainer isUnfolded={isViewsListDropdownOpen}> <StyledDropdownButtonContainer isUnfolded={isDropdownOpen}>
{currentView && CurrentViewIcon ? ( {currentView && CurrentViewIcon ? (
<CurrentViewIcon size={theme.icon.size.md} /> <CurrentViewIcon size={theme.icon.size.md} />
) : ( ) : (

View File

@ -9,7 +9,7 @@ import { DraggableList } from '@/ui/layout/draggable-list/components/DraggableLi
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useChangeView } from '@/views/hooks/useChangeView'; import { useChangeView } from '@/views/hooks/useChangeView';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly'; import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
@ -51,11 +51,11 @@ export const ViewPickerListContent = () => {
const { updateView } = useUpdateView(); const { updateView } = useUpdateView();
const { changeView } = useChangeView(); const { changeView } = useChangeView();
const { closeDropdown } = useDropdown(VIEW_PICKER_DROPDOWN_ID); const { closeDropdown } = useCloseDropdown();
const handleViewSelect = (viewId: string) => { const handleViewSelect = (viewId: string) => {
changeView(viewId); changeView(viewId);
closeDropdown(); closeDropdown(VIEW_PICKER_DROPDOWN_ID);
}; };
const handleAddViewButtonClick = () => { const handleAddViewButtonClick = () => {

View File

@ -2,7 +2,7 @@ import { useCreateFavorite } from '@/favorites/hooks/useCreateFavorite';
import { useFavorites } from '@/favorites/hooks/useFavorites'; import { useFavorites } from '@/favorites/hooks/useFavorites';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { MenuItemWithOptionDropdown } from '@/ui/navigation/menu-item/components/MenuItemWithOptionDropdown'; import { MenuItemWithOptionDropdown } from '@/ui/navigation/menu-item/components/MenuItemWithOptionDropdown';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { View } from '@/views/types/View'; import { View } from '@/views/types/View';
@ -33,8 +33,10 @@ export const ViewPickerOptionDropdown = ({
view, view,
handleViewSelect, handleViewSelect,
}: ViewPickerOptionDropdownProps) => { }: ViewPickerOptionDropdownProps) => {
const dropdownId = `view-picker-options-${view.id}`;
const { t } = useLingui(); const { t } = useLingui();
const { closeDropdown } = useDropdown(`view-picker-options-${view.id}`); const { closeDropdown } = useCloseDropdown();
const { getIcon } = useIcons(); const { getIcon } = useIcons();
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const { deleteViewFromCurrentState } = useDeleteViewFromCurrentState(); const { deleteViewFromCurrentState } = useDeleteViewFromCurrentState();
@ -54,7 +56,7 @@ export const ViewPickerOptionDropdown = ({
const handleDelete = () => { const handleDelete = () => {
setViewPickerReferenceViewId(view.id); setViewPickerReferenceViewId(view.id);
deleteViewFromCurrentState(); deleteViewFromCurrentState();
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleAddToFavorites = () => { const handleAddToFavorites = () => {
@ -64,7 +66,7 @@ export const ViewPickerOptionDropdown = ({
setViewPickerReferenceViewId(view.id); setViewPickerReferenceViewId(view.id);
setViewPickerMode('favorite-folders-picker'); setViewPickerMode('favorite-folders-picker');
} }
closeDropdown(); closeDropdown(dropdownId);
}; };
return ( return (
@ -103,7 +105,7 @@ export const ViewPickerOptionDropdown = ({
text={t`Edit`} text={t`Edit`}
onClick={(event) => { onClick={(event) => {
onEdit(event, view.id); onEdit(event, view.id);
closeDropdown(); closeDropdown(dropdownId);
}} }}
/> />
<MenuItem <MenuItem

View File

@ -9,7 +9,7 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { WorkflowFieldsMultiSelect } from '@/workflow/components/WorkflowEditUpdateEventFieldsMultiSelect'; import { WorkflowFieldsMultiSelect } from '@/workflow/components/WorkflowEditUpdateEventFieldsMultiSelect';
import { WorkflowDatabaseEventTrigger } from '@/workflow/types/Workflow'; import { WorkflowDatabaseEventTrigger } from '@/workflow/types/Workflow';
import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName'; import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName';
@ -71,7 +71,9 @@ export const WorkflowEditTriggerDatabaseEventForm = ({
const { getIcon } = useIcons(); const { getIcon } = useIcons();
const [searchInputValue, setSearchInputValue] = useState(''); const [searchInputValue, setSearchInputValue] = useState('');
const [isSystemObjectsOpen, setIsSystemObjectsOpen] = useState(false); const [isSystemObjectsOpen, setIsSystemObjectsOpen] = useState(false);
const { closeDropdown } = useDropdown('workflow-edit-trigger-record-type'); const dropdownId = 'workflow-edit-trigger-record-type';
const { closeDropdown } = useCloseDropdown();
const { objectMetadataItems } = useFilteredObjectMetadataItems(); const { objectMetadataItems } = useFilteredObjectMetadataItems();
@ -131,7 +133,7 @@ export const WorkflowEditTriggerDatabaseEventForm = ({
eventName: `${value}.${triggerEvent.event}`, eventName: `${value}.${triggerEvent.event}`,
}, },
}); });
closeDropdown(); closeDropdown(dropdownId);
}; };
const handleFieldsChange = (fields: FieldMultiSelectValue | string) => { const handleFieldsChange = (fields: FieldMultiSelectValue | string) => {

View File

@ -4,12 +4,12 @@ import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema'; import { StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema';
import { useState } from 'react'; import { useState } from 'react';
import { IconX, OverflowingTextWithTooltip, useIcons } from 'twenty-ui/display'; import { IconX, OverflowingTextWithTooltip, useIcons } from 'twenty-ui/display';
import { MenuItem, MenuItemSelect } from 'twenty-ui/navigation'; import { MenuItem, MenuItemSelect } from 'twenty-ui/navigation';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
type WorkflowVariablesDropdownWorkflowStepItemsProps = { type WorkflowVariablesDropdownWorkflowStepItemsProps = {
dropdownId: string; dropdownId: string;
@ -25,7 +25,7 @@ export const WorkflowVariablesDropdownWorkflowStepItems = ({
const { getIcon } = useIcons(); const { getIcon } = useIcons();
const [searchInputValue, setSearchInputValue] = useState(''); const [searchInputValue, setSearchInputValue] = useState('');
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useCloseDropdown();
const availableSteps = steps.filter((step) => const availableSteps = steps.filter((step) =>
searchInputValue searchInputValue
@ -38,7 +38,7 @@ export const WorkflowVariablesDropdownWorkflowStepItems = ({
<DropdownMenuHeader <DropdownMenuHeader
StartComponent={ StartComponent={
<DropdownMenuHeaderLeftComponent <DropdownMenuHeaderLeftComponent
onClick={closeDropdown} onClick={() => closeDropdown(dropdownId)}
Icon={IconX} Icon={IconX}
/> />
} }