Removed useDropdown and its legacy states (#13111)

This PR removes useDropdown barrel hook and refactors the legacy
useDropdown states to the last version of our recoil component state
management.

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
Lucas Bordeau
2025-07-08 20:16:15 +02:00
committed by GitHub
parent 1bf5139f03
commit 66b633e08e
33 changed files with 404 additions and 332 deletions

View File

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

View File

@ -1,91 +0,0 @@
import { renderHook } from '@testing-library/react';
import { act } from 'react';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
import { ObjectOptionsDropdownContext } from '@/object-record/object-options-dropdown/states/contexts/ObjectOptionsDropdownContext';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { ViewType } from '@/views/types/ViewType';
jest.mock('@/ui/layout/dropdown/hooks/useDropdown', () => ({
useDropdown: jest.fn(() => ({
closeDropdown: jest.fn(),
})),
}));
describe('useOptionsDropdown', () => {
const mockOnContentChange = jest.fn();
const mockCloseDropdown = jest.fn();
const mockResetContent = jest.fn();
beforeEach(() => {
jest.mocked(useDropdown).mockReturnValue({
scopeId: 'mock-scope',
isDropdownOpen: false,
closeDropdown: mockCloseDropdown,
toggleDropdown: jest.fn(),
openDropdown: jest.fn(),
dropdownPlacement: null,
setDropdownPlacement: jest.fn(),
});
});
afterEach(() => {
jest.clearAllMocks();
});
const renderWithProvider = (contextValue: Partial<any> = {}) => {
const wrapper = ({ children }: any) => (
<ObjectOptionsDropdownContext.Provider
value={{
viewType: ViewType.Table,
objectMetadataItem: {
__typename: 'object',
id: '1',
nameSingular: 'company',
namePlural: 'companies',
labelSingular: 'Company',
labelPlural: 'Companies',
icon: 'IconBuildingSkyscraper',
fields: [{}],
} as ObjectMetadataItem,
recordIndexId: 'test-record-index',
currentContentId: 'recordGroups',
onContentChange: mockOnContentChange,
resetContent: mockResetContent,
dropdownId: OBJECT_OPTIONS_DROPDOWN_ID,
...contextValue,
}}
>
{children}
</ObjectOptionsDropdownContext.Provider>
);
return renderHook(() => useObjectOptionsDropdown(), { wrapper });
};
it('provides closeDropdown functionality from the context', () => {
const { result } = renderWithProvider();
act(() => {
result.current.closeDropdown();
});
expect(mockResetContent).toHaveBeenCalled();
expect(mockCloseDropdown).toHaveBeenCalled();
});
it('returns all context values', () => {
const { result } = renderWithProvider({
currentContentId: 'fields',
});
expect(result.current).toHaveProperty('currentContentId', 'fields');
expect(result.current).toHaveProperty(
'onContentChange',
mockOnContentChange,
);
expect(result.current).toHaveProperty('closeDropdown');
expect(result.current).toHaveProperty('resetContent', mockResetContent);
});
});

View File

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

View File

@ -1,5 +1,5 @@
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import styled from '@emotion/styled';
import { Tag } from 'twenty-ui/components';
@ -23,7 +23,7 @@ export const RecordBoardColumnHeaderAggregateDropdownButton = ({
tooltip?: string;
}) => {
const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
isDropdownOpenComponentState,
dropdownId,
);

View File

@ -1,7 +1,7 @@
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { MenuItemWithOptionDropdown } from '@/ui/navigation/menu-item/components/MenuItemWithOptionDropdown';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import React, { useState } from 'react';
@ -37,7 +37,7 @@ export const MultiItemFieldMenuItem = <T,>({
const [isHovered, setIsHovered] = useState(false);
const { closeDropdown } = useCloseDropdown();
const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
isDropdownOpenComponentState,
dropdownId,
);

View File

@ -36,7 +36,7 @@ import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useModal } from '@/ui/layout/modal/hooks/useModal';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@ -163,7 +163,7 @@ export const RecordDetailRelationRecordsListItem = ({
const { closeDropdown } = useCloseDropdown();
const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
isDropdownOpenComponentState,
dropdownScopeId,
);

View File

@ -16,7 +16,7 @@ import { AggregateOperations } from '@/object-record/record-table/constants/Aggr
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector';
import { AppPath } from '@/types/AppPath';
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
@ -71,7 +71,7 @@ export const RecordDetailRelationSection = ({
});
const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
isDropdownOpenComponentState,
dropdownId,
);

View File

@ -18,7 +18,7 @@ import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { dropdownPlacementComponentStateV2 } from '@/ui/layout/dropdown/states/dropdownPlacementComponentStateV2';
import { dropdownPlacementComponentState } from '@/ui/layout/dropdown/states/dropdownPlacementComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { IconPlus } from 'twenty-ui/display';
@ -55,7 +55,7 @@ export const RecordDetailRelationSectionDropdownToMany = () => {
const { closeDropdown } = useCloseDropdown();
const dropdownPlacement = useRecoilComponentValueV2(
dropdownPlacementComponentStateV2,
dropdownPlacementComponentState,
dropdownId,
);

View File

@ -18,7 +18,7 @@ import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { dropdownPlacementComponentStateV2 } from '@/ui/layout/dropdown/states/dropdownPlacementComponentStateV2';
import { dropdownPlacementComponentState } from '@/ui/layout/dropdown/states/dropdownPlacementComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { IconForbid, IconPencil } from 'twenty-ui/display';
@ -57,7 +57,7 @@ export const RecordDetailRelationSectionDropdownToOne = () => {
const { closeDropdown } = useCloseDropdown();
const dropdownPlacement = useRecoilComponentValueV2(
dropdownPlacementComponentStateV2,
dropdownPlacementComponentState,
dropdownId,
);

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 { RecordTableColumnAggregateFooterValue } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterValue';
import { hasAggregateOperationForViewFieldFamilySelector } from '@/object-record/record-table/record-table-footer/states/hasAggregateOperationForViewFieldFamilySelector';
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
@ -62,7 +62,7 @@ export const RecordTableColumnAggregateFooterValueCell = ({
const [isHovered, setIsHovered] = useState(false);
const isDropdownOpen = useRecoilComponentValueV2(
isDropdownOpenComponentStateV2,
isDropdownOpenComponentState,
dropdownId,
);