Fix show page relation record count (#11459)

This PR fixes the incorrect relation count on a show page relation
section title, when there are more than 60 records.

An aggregate COUNT query has been used to rely on the backend.

A new component RecordDetailRelationSectionDropdown has been created to
abstract a chunk of the parent RecordDetailRelationSection component.

Fixes https://github.com/twentyhq/twenty/issues/11032
This commit is contained in:
Lucas Bordeau
2025-04-09 14:41:11 +02:00
committed by GitHub
parent bd3ec6d5e3
commit 1834b38d04
2 changed files with 280 additions and 193 deletions

View File

@ -1,65 +1,46 @@
import styled from '@emotion/styled'; import { useContext } from 'react';
import { useCallback, useContext } from 'react';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { useAggregateRecords } from '@/object-record/hooks/useAggregateRecords';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
import { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly'; import { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly';
import { useIsRecordReadOnly } from '@/object-record/record-field/hooks/useIsRecordReadOnly'; import { useIsRecordReadOnly } from '@/object-record/record-field/hooks/useIsRecordReadOnly';
import { usePersistField } from '@/object-record/record-field/hooks/usePersistField';
import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/record-field/meta-types/input/hooks/useAddNewRecordAndOpenRightDrawer';
import { useUpdateRelationFromManyFieldInput } from '@/object-record/record-field/meta-types/input/hooks/useUpdateRelationFromManyFieldInput';
import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { MultipleRecordPicker } from '@/object-record/record-picker/multiple-record-picker/components/MultipleRecordPicker';
import { useMultipleRecordPickerPerformSearch } from '@/object-record/record-picker/multiple-record-picker/hooks/useMultipleRecordPickerPerformSearch';
import { multipleRecordPickerPickableMorphItemsComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerPickableMorphItemsComponentState';
import { multipleRecordPickerSearchFilterComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerSearchFilterComponentState';
import { multipleRecordPickerSearchableObjectMetadataItemsComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerSearchableObjectMetadataItemsComponentState';
import { SingleRecordPicker } from '@/object-record/record-picker/single-record-picker/components/SingleRecordPicker';
import { singleRecordPickerSearchFilterComponentState } from '@/object-record/record-picker/single-record-picker/states/singleRecordPickerSearchFilterComponentState';
import { singleRecordPickerSelectedIdComponentState } from '@/object-record/record-picker/single-record-picker/states/singleRecordPickerSelectedIdComponentState';
import { SingleRecordPickerRecord } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerRecord';
import { RecordDetailRelationRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsList'; import { RecordDetailRelationRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsList';
import { RecordDetailRelationSectionDropdown } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationSectionDropdown';
import { RecordDetailSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailSection'; import { RecordDetailSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailSection';
import { RecordDetailSectionHeader } from '@/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader'; import { RecordDetailSectionHeader } from '@/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
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 { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
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 { RelationDefinitionType } from '~/generated-metadata/graphql'; import { RelationDefinitionType } from '~/generated-metadata/graphql';
import { getAppPath } from '~/utils/navigation/getAppPath'; import { getAppPath } from '~/utils/navigation/getAppPath';
import { IconForbid, IconPencil, IconPlus } from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
type RecordDetailRelationSectionProps = { type RecordDetailRelationSectionProps = {
loading: boolean; loading: boolean;
}; };
const StyledAddDropdown = styled(Dropdown)`
margin-left: auto;
`;
export const RecordDetailRelationSection = ({ export const RecordDetailRelationSection = ({
loading, loading,
}: RecordDetailRelationSectionProps) => { }: RecordDetailRelationSectionProps) => {
const { t } = useLingui(); const { t } = useLingui();
const { recordId, fieldDefinition } = useContext(FieldContext); const { recordId, fieldDefinition } = useContext(FieldContext);
const { const {
fieldName, fieldName,
relationFieldMetadataId, relationFieldMetadataId,
relationObjectMetadataNameSingular, relationObjectMetadataNameSingular,
relationType, relationType,
} = fieldDefinition.metadata as FieldRelationMetadata; } = fieldDefinition.metadata as FieldRelationMetadata;
const record = useRecoilValue(recordStoreFamilyState(recordId));
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const { objectMetadataItem: relationObjectMetadataItem } = const { objectMetadataItem: relationObjectMetadataItem } =
@ -86,69 +67,7 @@ export const RecordDetailRelationSection = ({
const dropdownId = `record-field-card-relation-picker-${fieldDefinition.fieldMetadataId}-${recordId}`; const dropdownId = `record-field-card-relation-picker-${fieldDefinition.fieldMetadataId}-${recordId}`;
const { closeDropdown, isDropdownOpen, dropdownPlacement } = const { isDropdownOpen } = useDropdown(dropdownId);
useDropdown(dropdownId);
const setMultipleRecordPickerSearchFilter = useSetRecoilComponentStateV2(
multipleRecordPickerSearchFilterComponentState,
dropdownId,
);
const setMultipleRecordPickerPickableMorphItems =
useSetRecoilComponentStateV2(
multipleRecordPickerPickableMorphItemsComponentState,
dropdownId,
);
const setMultipleRecordPickerSearchableObjectMetadataItems =
useSetRecoilComponentStateV2(
multipleRecordPickerSearchableObjectMetadataItemsComponentState,
dropdownId,
);
const { performSearch: multipleRecordPickerPerformSearch } =
useMultipleRecordPickerPerformSearch();
const setSingleRecordPickerSearchFilter = useSetRecoilComponentStateV2(
singleRecordPickerSearchFilterComponentState,
dropdownId,
);
const setSingleRecordPickerSelectedId = useSetRecoilComponentStateV2(
singleRecordPickerSelectedIdComponentState,
dropdownId,
);
const handleCloseRelationPickerDropdown = useCallback(() => {
setMultipleRecordPickerSearchFilter('');
}, [setMultipleRecordPickerSearchFilter]);
const persistField = usePersistField();
const { updateOneRecord: updateOneRelationRecord } = useUpdateOneRecord({
objectNameSingular: relationObjectMetadataNameSingular,
});
const handleRelationPickerEntitySelected = (
selectedRelationEntity?: SingleRecordPickerRecord,
) => {
closeDropdown();
if (!selectedRelationEntity?.id || !relationFieldMetadataItem?.name) return;
if (isToOneObject) {
persistField(selectedRelationEntity.record);
return;
}
updateOneRelationRecord({
idToUpdate: selectedRelationEntity.id,
updateOneRecordInput: {
[relationFieldMetadataItem.name]: record,
},
});
};
const { updateRelation } = useUpdateRelationFromManyFieldInput();
const indexViewId = useRecoilValue( const indexViewId = useRecoilValue(
prefetchIndexViewIdFromObjectMetadataItemFamilySelector({ prefetchIndexViewIdFromObjectMetadataItemFamilySelector({
@ -175,20 +94,24 @@ export const RecordDetailRelationSection = ({
filterQueryParams, filterQueryParams,
); );
const showContent = () => { const filtersForAggregate = isToManyObjects
return ( ? ({
relationRecords.length > 0 && ( [`${relationFieldMetadataItem?.name}Id`]: {
<RecordDetailRelationRecordsList relationRecords={relationRecords} /> in: [recordId],
) },
); } satisfies RecordGqlOperationFilter)
}; : {};
const { createNewRecordAndOpenRightDrawer } = const { data: relationAggregateResult, loading: aggregateLoading } =
useAddNewRecordAndOpenRightDrawer({ useAggregateRecords<{
relationObjectMetadataNameSingular, id: { COUNT: number };
relationObjectMetadataItem, }>({
relationFieldMetadataItem, objectNameSingular: relationObjectMetadataItem.nameSingular,
recordId, filter: filtersForAggregate,
skip: !isToManyObjects,
recordGqlFieldsAggregate: {
id: [AGGREGATE_OPERATIONS.count],
},
}); });
const isRecordReadOnly = useIsRecordReadOnly({ const isRecordReadOnly = useIsRecordReadOnly({
@ -200,45 +123,9 @@ export const RecordDetailRelationSection = ({
isRecordReadOnly, isRecordReadOnly,
}); });
if (loading) return null; if (loading || aggregateLoading || isFieldReadOnly) return null;
const relationRecordsCount = relationRecords.length; const relationRecordsCount = relationAggregateResult?.id?.COUNT ?? 0;
const handleOpenRelationPickerDropdown = () => {
if (isToOneObject) {
setSingleRecordPickerSearchFilter('');
if (relationRecords.length > 0) {
setSingleRecordPickerSelectedId(relationRecords[0].id);
}
}
if (isToManyObjects) {
setMultipleRecordPickerSearchableObjectMetadataItems([
relationObjectMetadataItem,
]);
setMultipleRecordPickerSearchFilter('');
setMultipleRecordPickerPickableMorphItems(
relationRecords.map((record) => ({
recordId: record.id,
objectMetadataId: relationObjectMetadataItem.id,
isSelected: true,
isMatchingSearchFilter: true,
})),
);
multipleRecordPickerPerformSearch({
multipleRecordPickerInstanceId: dropdownId,
forceSearchFilter: '',
forceSearchableObjectMetadataItems: [relationObjectMetadataItem],
forcePickableMorphItems: relationRecords.map((record) => ({
recordId: record.id,
objectMetadataId: relationObjectMetadataItem.id,
isSelected: true,
isMatchingSearchFilter: true,
})),
});
}
};
return ( return (
<RecordDetailSection> <RecordDetailSection>
@ -258,61 +145,12 @@ export const RecordDetailRelationSection = ({
hideRightAdornmentOnMouseLeave={!isDropdownOpen && !isMobile} hideRightAdornmentOnMouseLeave={!isDropdownOpen && !isMobile}
areRecordsAvailable={relationRecords.length > 0} areRecordsAvailable={relationRecords.length > 0}
rightAdornment={ rightAdornment={
!isFieldReadOnly && ( <RecordDetailRelationSectionDropdown loading={loading} />
<DropdownScope dropdownScopeId={dropdownId}>
<StyledAddDropdown
dropdownId={dropdownId}
dropdownPlacement="left-start"
onClose={handleCloseRelationPickerDropdown}
onOpen={handleOpenRelationPickerDropdown}
clickableComponent={
<LightIconButton
className="displayOnHover"
Icon={isToOneObject ? IconPencil : IconPlus}
accent="tertiary"
/>
}
dropdownHotkeyScope={{ scope: dropdownId }}
dropdownComponents={
isToOneObject ? (
<SingleRecordPicker
componentInstanceId={dropdownId}
EmptyIcon={IconForbid}
onRecordSelected={handleRelationPickerEntitySelected}
objectNameSingular={relationObjectMetadataNameSingular}
recordPickerInstanceId={dropdownId}
onCreate={createNewRecordAndOpenRightDrawer}
onCancel={closeDropdown}
layoutDirection={
dropdownPlacement?.includes('end')
? 'search-bar-on-bottom'
: 'search-bar-on-top'
}
/>
) : (
<MultipleRecordPicker
componentInstanceId={dropdownId}
onCreate={() => {
closeDropdown();
createNewRecordAndOpenRightDrawer?.();
}}
onChange={updateRelation}
onSubmit={closeDropdown}
onClickOutside={closeDropdown}
layoutDirection={
dropdownPlacement?.includes('end')
? 'search-bar-on-bottom'
: 'search-bar-on-top'
}
/>
)
}
/>
</DropdownScope>
)
} }
/> />
{showContent()} {relationRecords.length > 0 && (
<RecordDetailRelationRecordsList relationRecords={relationRecords} />
)}
</RecordDetailSection> </RecordDetailSection>
); );
}; };

View File

@ -0,0 +1,249 @@
import styled from '@emotion/styled';
import { useCallback, useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
import { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly';
import { useIsRecordReadOnly } from '@/object-record/record-field/hooks/useIsRecordReadOnly';
import { usePersistField } from '@/object-record/record-field/hooks/usePersistField';
import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/record-field/meta-types/input/hooks/useAddNewRecordAndOpenRightDrawer';
import { useUpdateRelationFromManyFieldInput } from '@/object-record/record-field/meta-types/input/hooks/useUpdateRelationFromManyFieldInput';
import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { MultipleRecordPicker } from '@/object-record/record-picker/multiple-record-picker/components/MultipleRecordPicker';
import { useMultipleRecordPickerPerformSearch } from '@/object-record/record-picker/multiple-record-picker/hooks/useMultipleRecordPickerPerformSearch';
import { multipleRecordPickerPickableMorphItemsComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerPickableMorphItemsComponentState';
import { multipleRecordPickerSearchFilterComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerSearchFilterComponentState';
import { multipleRecordPickerSearchableObjectMetadataItemsComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerSearchableObjectMetadataItemsComponentState';
import { SingleRecordPicker } from '@/object-record/record-picker/single-record-picker/components/SingleRecordPicker';
import { singleRecordPickerSearchFilterComponentState } from '@/object-record/record-picker/single-record-picker/states/singleRecordPickerSearchFilterComponentState';
import { singleRecordPickerSelectedIdComponentState } from '@/object-record/record-picker/single-record-picker/states/singleRecordPickerSelectedIdComponentState';
import { SingleRecordPickerRecord } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerRecord';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { IconForbid, IconPencil, IconPlus } from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
import { RelationDefinitionType } from '~/generated-metadata/graphql';
type RecordDetailRelationSectionDropdownProps = {
loading: boolean;
};
const StyledAddDropdown = styled(Dropdown)`
margin-left: auto;
`;
export const RecordDetailRelationSectionDropdown = ({
loading,
}: RecordDetailRelationSectionDropdownProps) => {
const { recordId, fieldDefinition } = useContext(FieldContext);
const {
fieldName,
relationFieldMetadataId,
relationObjectMetadataNameSingular,
relationType,
} = fieldDefinition.metadata as FieldRelationMetadata;
const record = useRecoilValue(recordStoreFamilyState(recordId));
const { objectMetadataItem: relationObjectMetadataItem } =
useObjectMetadataItem({
objectNameSingular: relationObjectMetadataNameSingular,
});
const relationFieldMetadataItem = relationObjectMetadataItem.fields.find(
({ id }) => id === relationFieldMetadataId,
);
const fieldValue = useRecoilValue<
({ id: string } & Record<string, any>) | ObjectRecord[] | null
>(recordStoreFamilySelector({ recordId, fieldName }));
// TODO: use new relation type
const isToOneObject = relationType === RelationDefinitionType.MANY_TO_ONE;
const isToManyObjects = relationType === RelationDefinitionType.ONE_TO_MANY;
const relationRecords: ObjectRecord[] =
fieldValue && isToOneObject
? [fieldValue as ObjectRecord]
: ((fieldValue as ObjectRecord[]) ?? []);
const dropdownId = `record-field-card-relation-picker-${fieldDefinition.fieldMetadataId}-${recordId}`;
const { closeDropdown, dropdownPlacement } = useDropdown(dropdownId);
const setMultipleRecordPickerSearchFilter = useSetRecoilComponentStateV2(
multipleRecordPickerSearchFilterComponentState,
dropdownId,
);
const setMultipleRecordPickerPickableMorphItems =
useSetRecoilComponentStateV2(
multipleRecordPickerPickableMorphItemsComponentState,
dropdownId,
);
const setMultipleRecordPickerSearchableObjectMetadataItems =
useSetRecoilComponentStateV2(
multipleRecordPickerSearchableObjectMetadataItemsComponentState,
dropdownId,
);
const { performSearch: multipleRecordPickerPerformSearch } =
useMultipleRecordPickerPerformSearch();
const setSingleRecordPickerSearchFilter = useSetRecoilComponentStateV2(
singleRecordPickerSearchFilterComponentState,
dropdownId,
);
const setSingleRecordPickerSelectedId = useSetRecoilComponentStateV2(
singleRecordPickerSelectedIdComponentState,
dropdownId,
);
const handleCloseRelationPickerDropdown = useCallback(() => {
setMultipleRecordPickerSearchFilter('');
}, [setMultipleRecordPickerSearchFilter]);
const persistField = usePersistField();
const { updateOneRecord: updateOneRelationRecord } = useUpdateOneRecord({
objectNameSingular: relationObjectMetadataNameSingular,
});
const handleRelationPickerEntitySelected = (
selectedRelationEntity?: SingleRecordPickerRecord,
) => {
closeDropdown();
if (!selectedRelationEntity?.id || !relationFieldMetadataItem?.name) return;
if (isToOneObject) {
persistField(selectedRelationEntity.record);
return;
}
updateOneRelationRecord({
idToUpdate: selectedRelationEntity.id,
updateOneRecordInput: {
[relationFieldMetadataItem.name]: record,
},
});
};
const { updateRelation } = useUpdateRelationFromManyFieldInput();
const { createNewRecordAndOpenRightDrawer } =
useAddNewRecordAndOpenRightDrawer({
relationObjectMetadataNameSingular,
relationObjectMetadataItem,
relationFieldMetadataItem,
recordId,
});
const isRecordReadOnly = useIsRecordReadOnly({
recordId,
});
const isFieldReadOnly = useIsFieldValueReadOnly({
fieldDefinition,
isRecordReadOnly,
});
if (loading || isFieldReadOnly) return null;
const handleOpenRelationPickerDropdown = () => {
if (isToOneObject) {
setSingleRecordPickerSearchFilter('');
if (relationRecords.length > 0) {
setSingleRecordPickerSelectedId(relationRecords[0].id);
}
}
if (isToManyObjects) {
setMultipleRecordPickerSearchableObjectMetadataItems([
relationObjectMetadataItem,
]);
setMultipleRecordPickerSearchFilter('');
setMultipleRecordPickerPickableMorphItems(
relationRecords.map((record) => ({
recordId: record.id,
objectMetadataId: relationObjectMetadataItem.id,
isSelected: true,
isMatchingSearchFilter: true,
})),
);
multipleRecordPickerPerformSearch({
multipleRecordPickerInstanceId: dropdownId,
forceSearchFilter: '',
forceSearchableObjectMetadataItems: [relationObjectMetadataItem],
forcePickableMorphItems: relationRecords.map((record) => ({
recordId: record.id,
objectMetadataId: relationObjectMetadataItem.id,
isSelected: true,
isMatchingSearchFilter: true,
})),
});
}
};
return (
<DropdownScope dropdownScopeId={dropdownId}>
<StyledAddDropdown
dropdownId={dropdownId}
dropdownPlacement="left-start"
onClose={handleCloseRelationPickerDropdown}
onOpen={handleOpenRelationPickerDropdown}
clickableComponent={
<LightIconButton
className="displayOnHover"
Icon={isToOneObject ? IconPencil : IconPlus}
accent="tertiary"
/>
}
dropdownHotkeyScope={{ scope: dropdownId }}
dropdownComponents={
isToOneObject ? (
<SingleRecordPicker
componentInstanceId={dropdownId}
EmptyIcon={IconForbid}
onRecordSelected={handleRelationPickerEntitySelected}
objectNameSingular={relationObjectMetadataNameSingular}
recordPickerInstanceId={dropdownId}
onCreate={createNewRecordAndOpenRightDrawer}
onCancel={closeDropdown}
layoutDirection={
dropdownPlacement?.includes('end')
? 'search-bar-on-bottom'
: 'search-bar-on-top'
}
/>
) : (
<MultipleRecordPicker
componentInstanceId={dropdownId}
onCreate={() => {
closeDropdown();
createNewRecordAndOpenRightDrawer?.();
}}
onChange={updateRelation}
onSubmit={closeDropdown}
onClickOutside={closeDropdown}
layoutDirection={
dropdownPlacement?.includes('end')
? 'search-bar-on-bottom'
: 'search-bar-on-top'
}
/>
)
}
/>
</DropdownScope>
);
};