From aac70c679fba96c8342eaafa25443e9e7283ecae Mon Sep 17 00:00:00 2001 From: Baptiste Devessier Date: Tue, 30 Dec 2025 15:43:58 +0100 Subject: [PATCH] Field widget fix dropdowns (#16855) ## Before https://github.com/user-attachments/assets/a78f6561-a519-455e-a838-c4e138fb336f ## After https://github.com/user-attachments/assets/ec704406-b16b-491a-8a88-8aa6fe25254b Closes https://github.com/twentyhq/core-team-issues/issues/2023 --- .../FieldWidgetCellEditModePortal.tsx | 20 +++++++------------ .../FieldWidgetCellHoveredPortal.tsx | 15 ++------------ .../field/hooks/useIsFieldWidgetEditing.ts | 20 +++++++++++++++++++ 3 files changed, 29 insertions(+), 26 deletions(-) create mode 100644 packages/twenty-front/src/modules/page-layout/widgets/field/hooks/useIsFieldWidgetEditing.ts diff --git a/packages/twenty-front/src/modules/page-layout/widgets/field/components/FieldWidgetCellEditModePortal.tsx b/packages/twenty-front/src/modules/page-layout/widgets/field/components/FieldWidgetCellEditModePortal.tsx index a935edff30..b4793a4468 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/field/components/FieldWidgetCellEditModePortal.tsx +++ b/packages/twenty-front/src/modules/page-layout/widgets/field/components/FieldWidgetCellEditModePortal.tsx @@ -1,15 +1,13 @@ import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { useRecordFieldsScopeContextOrThrow } from '@/object-record/record-field-list/contexts/RecordFieldsScopeContext'; import { FieldInput } from '@/object-record/record-field/ui/components/FieldInput'; import { RecordInlineCellAnchoredPortal } from '@/object-record/record-inline-cell/components/RecordInlineCellAnchoredPortal'; import { RecordInlineCellEditMode } from '@/object-record/record-inline-cell/components/RecordInlineCellEditMode'; -import { getDropdownFocusIdForRecordField } from '@/object-record/utils/getDropdownFocusIdForRecordField'; import { FieldWidgetInputContextProvider } from '@/page-layout/widgets/field/components/FieldWidgetInputContextProvider'; +import { useIsFieldWidgetEditing } from '@/page-layout/widgets/field/hooks/useIsFieldWidgetEditing'; +import { useOpenFieldWidgetFieldInputEditMode } from '@/page-layout/widgets/field/hooks/useOpenFieldWidgetFieldInputEditMode'; import { fieldWidgetHoverComponentState } from '@/page-layout/widgets/field/states/fieldWidgetHoverComponentState'; -import { activeDropdownFocusIdState } from '@/ui/layout/dropdown/states/activeDropdownFocusIdState'; import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; -import { useRecoilValue } from 'recoil'; type FieldWidgetCellEditModePortalProps = { objectMetadataItem: ObjectMetadataItem; @@ -24,22 +22,18 @@ export const FieldWidgetCellEditModePortal = ({ recordId, instanceId, }: FieldWidgetCellEditModePortalProps) => { - const { scopeInstanceId } = useRecordFieldsScopeContextOrThrow(); - const activeDropdownFocusId = useRecoilValue(activeDropdownFocusIdState); - const expectedDropdownFocusId = getDropdownFocusIdForRecordField({ - recordId, - fieldMetadataId: fieldMetadataItem.id, - componentType: 'inline-cell', - instanceId: scopeInstanceId, - }); - const isEditing = activeDropdownFocusId === expectedDropdownFocusId; + const { isEditing } = useIsFieldWidgetEditing(); const setIsHovered = useSetRecoilComponentState( fieldWidgetHoverComponentState, ); + const { closeFieldInput } = useOpenFieldWidgetFieldInputEditMode(); + const handleCloseEditMode = () => { setIsHovered(false); + + closeFieldInput(); }; if (!isEditing) { diff --git a/packages/twenty-front/src/modules/page-layout/widgets/field/components/FieldWidgetCellHoveredPortal.tsx b/packages/twenty-front/src/modules/page-layout/widgets/field/components/FieldWidgetCellHoveredPortal.tsx index edc05e5b82..da8d480129 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/field/components/FieldWidgetCellHoveredPortal.tsx +++ b/packages/twenty-front/src/modules/page-layout/widgets/field/components/FieldWidgetCellHoveredPortal.tsx @@ -1,11 +1,8 @@ import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { useRecordFieldsScopeContextOrThrow } from '@/object-record/record-field-list/contexts/RecordFieldsScopeContext'; import { RecordInlineCellAnchoredPortal } from '@/object-record/record-inline-cell/components/RecordInlineCellAnchoredPortal'; -import { getDropdownFocusIdForRecordField } from '@/object-record/utils/getDropdownFocusIdForRecordField'; import { FieldWidgetCellHoveredContent } from '@/page-layout/widgets/field/components/FieldWidgetCellHoveredContent'; -import { activeDropdownFocusIdState } from '@/ui/layout/dropdown/states/activeDropdownFocusIdState'; -import { useRecoilValue } from 'recoil'; +import { useIsFieldWidgetEditing } from '@/page-layout/widgets/field/hooks/useIsFieldWidgetEditing'; type FieldWidgetCellHoveredPortalProps = { objectMetadataItem: ObjectMetadataItem; @@ -24,15 +21,7 @@ export const FieldWidgetCellHoveredPortal = ({ isHovered, onMouseLeave, }: FieldWidgetCellHoveredPortalProps) => { - const { scopeInstanceId } = useRecordFieldsScopeContextOrThrow(); - const activeDropdownFocusId = useRecoilValue(activeDropdownFocusIdState); - const expectedDropdownFocusId = getDropdownFocusIdForRecordField({ - recordId, - fieldMetadataId: fieldMetadataItem.id, - componentType: 'inline-cell', - instanceId: scopeInstanceId, - }); - const isEditing = activeDropdownFocusId === expectedDropdownFocusId; + const { isEditing } = useIsFieldWidgetEditing(); if (!isHovered || isEditing) { return null; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/field/hooks/useIsFieldWidgetEditing.ts b/packages/twenty-front/src/modules/page-layout/widgets/field/hooks/useIsFieldWidgetEditing.ts new file mode 100644 index 0000000000..0eea75a45d --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/field/hooks/useIsFieldWidgetEditing.ts @@ -0,0 +1,20 @@ +import { useRecoilValue } from 'recoil'; + +import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/ui/states/contexts/RecordFieldComponentInstanceContext'; +import { focusStackState } from '@/ui/utilities/focus/states/focusStackState'; +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; + +export const useIsFieldWidgetEditing = () => { + const recordFieldInstanceId = useAvailableComponentInstanceIdOrThrow( + RecordFieldComponentInstanceContext, + ); + + const focusStack = useRecoilValue(focusStackState); + + const isEditing = focusStack.some( + (item) => + item.componentInstance.componentInstanceId === recordFieldInstanceId, + ); + + return { isEditing }; +};