From dd0ea2366ffcdd64afb27f6d5575819dbb1ec7d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?=
<71827178+bosiraphael@users.noreply.github.com>
Date: Thu, 17 Apr 2025 18:40:24 +0200
Subject: [PATCH] 839 Table focus refactoring (#11629)
# Table Focus Refactoring
This pull request implements the table focus refactoring requested in
[#839](https://github.com/twentyhq/core-team-issues/issues/839),
dissociating hover and focus behaviors in the table component to improve
keyboard navigation.
## Technical Implementation
- Created separate component states to handle focus and hover
independently.
- Updated all relevant hooks and functions to use the new focus
mechanism.
- Removed deprecated states and hooks.
- Introduced dedicated portal components to improve the table
performance (the table cells are much simpler and the more complex logic
is handled via the portals)
## Key Behavior Changes
- Performance improvements
- Focus is now handled exclusively with keyboard navigation
- Clicking on a cell or inline-cell now sets the focus to that cell
- Hover state is managed separately from focus, improving user
experience and accessibility
- The table scrolls when the focused cell changes
## Video
https://github.com/user-attachments/assets/9966beac-3b0f-4433-a87a-299506d83353
---
.../record-table/components/RecordTable.tsx | 9 +
.../RecordTableBodyEffectsWrapper.tsx | 18 +-
...cordTableFocusModeHotkeysSetterEffect.tsx} | 33 +---
...dTableNoRecordGroupBodyContextProvider.tsx | 13 +-
...ordTableRecordGroupBodyContextProvider.tsx | 13 +-
...ecordTableScrollToFocusedElementEffect.tsx | 49 ++++++
.../perf/RecordTableCell.perf.stories.tsx | 5 +-
.../constants/FocusClickOutsideListenerId.ts | 2 +
.../SoftFocusClickOutsideListenerId.ts | 2 -
.../contexts/RecordTableBodyContext.ts | 2 +-
.../contexts/RecordTableCellContext.ts | 3 -
.../useCloseCurrentTableCellInEditMode.ts | 28 +---
.../hooks/internal/useDisableSoftFocus.ts | 42 -----
.../internal/useGetIsSomeCellInEditMode.ts | 35 ----
.../internal/useHandleContainerMouseEnter.ts | 51 ++----
.../hooks/internal/useLeaveTableFocus.ts | 40 +----
.../internal/useMoveEditModeToCellPosition.ts | 41 -----
.../useSetRecordTableFocusPosition.ts | 28 ++++
.../hooks/internal/useSetSoftFocusPosition.ts | 48 ------
.../record-table/hooks/useRecordTable.ts | 44 ++---
.../hooks/useRecordTableMoveFocus.ts | 78 ++++-----
...ecordTableBodyFocusClickOutsideEffect.tsx} | 6 +-
...=> RecordTableBodyFocusKeyboardEffect.tsx} | 6 +-
.../RecordTableNoRecordGroupBody.tsx | 2 +
.../RecordTableRecordGroupsBody.tsx | 2 +
.../components/RecordTableCell.tsx | 6 +-
.../RecordTableCellBaseContainer.tsx | 44 ++---
.../components/RecordTableCellContainer.tsx | 22 +--
.../RecordTableCellDisplayContainer.tsx | 6 +-
.../components/RecordTableCellDisplayMode.tsx | 36 ++--
.../components/RecordTableCellEditButton.tsx | 4 +-
.../components/RecordTableCellEditMode.tsx | 54 ++++--
.../RecordTableCellEditModePortal.tsx | 44 +++++
.../RecordTableCellHoveredPortal.tsx | 96 +++++++++++
.../RecordTableCellPortalWrapper.tsx | 66 ++++++++
.../components/RecordTableCellPortals.tsx | 22 +++
.../components/RecordTableCellWrapper.tsx | 16 --
.../record-table-cell/hooks/__mocks__/cell.ts | 3 -
.../__tests__/useCurrentCellPosition.test.tsx | 37 -----
.../useCurrentTableCellEditMode.test.tsx | 50 ------
.../useIsSoftFocusOnCurrentTableCell.test.tsx | 42 -----
.../useMoveHoverToCurrentCell.test.tsx | 80 +++++++++
...MoveSoftFocusToCurrentCellOnHover.test.tsx | 147 -----------------
.../useSelectedTableCellEditMode.test.tsx | 63 -------
.../useSetIsRecordTableFocusActive.test.tsx | 155 ++++++++++++++++++
.../useCloseRecordTableCellInGroup.test.tsx | 18 +-
.../useCloseRecordTableCellNoGroup.test.tsx | 19 +--
.../useCloseRecordTableCellInGroup.ts | 6 +-
.../useCloseRecordTableCellNoGroup.ts | 6 +-
.../hooks/useCurrentCellPosition.ts | 9 -
.../hooks/useCurrentTableCellEditMode.ts | 27 ---
.../hooks/useIsSoftFocusOnCurrentTableCell.ts | 14 --
.../hooks/useMoveHoverToCurrentCell.ts | 55 +++++++
.../useMoveSoftFocusToCurrentCellOnHover.ts | 68 --------
.../hooks/useOpenRecordTableCellFromCell.ts | 9 +-
.../hooks/useOpenRecordTableCellV2.ts | 18 +-
.../hooks/useSelectedTableCellEditMode.ts | 21 ---
.../hooks/useSetIsRecordTableFocusActive.ts | 51 ++++++
.../hooks/useSetSoftFocus.ts | 39 -----
.../useSetSoftFocusOnCurrentTableCell.ts | 13 --
...isRecordTableFocusActiveComponentState.ts} | 11 +-
.../states/isSoftFocusActiveComponentState.ts | 8 -
...oftFocusOnTableCellComponentFamilyState.ts | 10 --
.../states/isSoftFocusUsingMouseState.ts | 5 -
...TableCellInEditModeComponentFamilyState.ts | 10 --
...ableCellEditModePositionComponentState.ts} | 11 +-
...recordTableFocusPositionComponentState.ts} | 4 +-
.../recordTableHoverPositionComponentState.ts | 10 ++
.../isSomeCellInEditModeComponentSelector.ts | 20 +++
.../tableRecordGroupIdsComponentState.ts | 11 --
.../record-table/types/TableHotkeyScope.ts | 2 +-
.../decorators/RecordTableDecorator.tsx | 2 +-
72 files changed, 920 insertions(+), 1150 deletions(-)
rename packages/twenty-front/src/modules/object-record/record-table/{record-table-cell/components/RecordTableCellSoftFocusModeHotkeysSetterEffect.tsx => components/RecordTableFocusModeHotkeysSetterEffect.tsx} (66%)
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/components/RecordTableScrollToFocusedElementEffect.tsx
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/constants/FocusClickOutsideListenerId.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/constants/SoftFocusClickOutsideListenerId.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useDisableSoftFocus.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useGetIsSomeCellInEditMode.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useMoveEditModeToCellPosition.ts
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableFocusPosition.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetSoftFocusPosition.ts
rename packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/{RecordTableBodySoftFocusClickOutsideEffect.tsx => RecordTableBodyFocusClickOutsideEffect.tsx} (84%)
rename packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/{RecordTableBodySoftFocusKeyboardEffect.tsx => RecordTableBodyFocusKeyboardEffect.tsx} (66%)
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditModePortal.tsx
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellHoveredPortal.tsx
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortals.tsx
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useCurrentCellPosition.test.tsx
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useCurrentTableCellEditMode.test.tsx
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useIsSoftFocusOnCurrentTableCell.test.tsx
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveHoverToCurrentCell.test.tsx
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveSoftFocusToCurrentCellOnHover.test.tsx
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSelectedTableCellEditMode.test.tsx
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSetIsRecordTableFocusActive.test.tsx
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useCurrentCellPosition.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useCurrentTableCellEditMode.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useIsSoftFocusOnCurrentTableCell.ts
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveHoverToCurrentCell.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode.ts
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetIsRecordTableFocusActive.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocus.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocusOnCurrentTableCell.ts
rename packages/twenty-front/src/modules/object-record/record-table/states/{tableCellWidthsComponentState.ts => isRecordTableFocusActiveComponentState.ts} (50%)
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusActiveComponentState.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusUsingMouseState.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/isTableCellInEditModeComponentFamilyState.ts
rename packages/twenty-front/src/modules/object-record/record-table/states/{currentTableCellInEditModePositionComponentState.ts => recordTableCellEditModePositionComponentState.ts} (62%)
rename packages/twenty-front/src/modules/object-record/record-table/states/{softFocusPositionComponentState.ts => recordTableFocusPositionComponentState.ts} (82%)
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/recordTableHoverPositionComponentState.ts
create mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/selectors/isSomeCellInEditModeComponentSelector.ts
delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/tableRecordGroupIdsComponentState.ts
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx
index 8f5627ac6..621e5b068 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx
@@ -6,9 +6,11 @@ import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record
import { RecordTableBodyEffectsWrapper } from '@/object-record/record-table/components/RecordTableBodyEffectsWrapper';
import { RecordTableContent } from '@/object-record/record-table/components/RecordTableContent';
import { RecordTableEmpty } from '@/object-record/record-table/components/RecordTableEmpty';
+import { RecordTableScrollToFocusedElementEffect } from '@/object-record/record-table/components/RecordTableScrollToFocusedElementEffect';
import { RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/RecordTableClickOutsideListenerId';
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
+import { isRecordTableFocusActiveComponentState } from '@/object-record/record-table/states/isRecordTableFocusActiveComponentState';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@@ -44,6 +46,11 @@ export const RecordTable = () => {
const recordTableIsEmpty =
!isRecordTableInitialLoading && allRecordIds.length === 0;
+ const isRecordTableFocusActive = useRecoilComponentValueV2(
+ isRecordTableFocusActiveComponentState,
+ recordTableId,
+ );
+
if (!isNonEmptyString(objectNameSingular)) {
return <>>;
}
@@ -64,6 +71,8 @@ export const RecordTable = () => {
tableBodyRef={tableBodyRef}
/>
+ {isRecordTableFocusActive && }
+
{recordTableIsEmpty && !hasRecordGroups ? (
)}
{isAtLeastOneRecordSelected && }
- {isSoftFocusActiveState && }
- {isSoftFocusActiveState && (
-
+ {isRecordTableFocusActive && }
+ {isRecordTableFocusActive && (
+
)}
>
);
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusModeHotkeysSetterEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableFocusModeHotkeysSetterEffect.tsx
similarity index 66%
rename from packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusModeHotkeysSetterEffect.tsx
rename to packages/twenty-front/src/modules/object-record/record-table/components/RecordTableFocusModeHotkeysSetterEffect.tsx
index 7503a8e1c..2e09b9841 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusModeHotkeysSetterEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableFocusModeHotkeysSetterEffect.tsx
@@ -1,5 +1,4 @@
-import { useContext, useEffect, useRef } from 'react';
-import { useRecoilValue } from 'recoil';
+import { useContext } from 'react';
import { Key } from 'ts-key-enum';
import { useClearField } from '@/object-record/record-field/hooks/useClearField';
@@ -7,17 +6,13 @@ import { useIsFieldClearable } from '@/object-record/record-field/hooks/useIsFie
import { useIsFieldInputOnly } from '@/object-record/record-field/hooks/useIsFieldInputOnly';
import { useToggleEditOnlyInput } from '@/object-record/record-field/hooks/useToggleEditOnlyInput';
import { useOpenRecordTableCellFromCell } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell';
-import { isSoftFocusUsingMouseState } from '@/object-record/record-table/states/isSoftFocusUsingMouseState';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { isNonTextWritingKey } from '@/ui/utilities/hotkey/utils/isNonTextWritingKey';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
-import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
-import { TableHotkeyScope } from '../../types/TableHotkeyScope';
-
-export const RecordTableCellSoftFocusModeHotkeysSetterEffect = () => {
- const currentHotkeyScope = useRecoilValue(currentHotkeyScopeState);
+import { TableHotkeyScope } from '../types/TableHotkeyScope';
+export const RecordTableFocusModeHotkeysSetterEffect = () => {
const { openTableCell } = useOpenRecordTableCellFromCell();
const { isReadOnly } = useContext(FieldContext);
@@ -26,21 +21,9 @@ export const RecordTableCellSoftFocusModeHotkeysSetterEffect = () => {
const isFieldClearable = useIsFieldClearable();
const toggleEditOnlyInput = useToggleEditOnlyInput();
- const scrollRef = useRef(null);
- const isSoftFocusUsingMouse = useRecoilValue(isSoftFocusUsingMouseState);
const clearField = useClearField();
- useEffect(() => {
- if (currentHotkeyScope.scope !== TableHotkeyScope.TableSoftFocus) {
- return;
- }
-
- if (!isSoftFocusUsingMouse) {
- scrollRef.current?.scrollIntoView({ block: 'nearest' });
- }
- }, [currentHotkeyScope.scope, isSoftFocusUsingMouse]);
-
useScopedHotkeys(
[Key.Backspace, Key.Delete],
() => {
@@ -48,7 +31,7 @@ export const RecordTableCellSoftFocusModeHotkeysSetterEffect = () => {
clearField();
}
},
- TableHotkeyScope.TableSoftFocus,
+ TableHotkeyScope.TableFocus,
[clearField, isFieldClearable, isFieldInputOnly],
);
@@ -65,8 +48,8 @@ export const RecordTableCellSoftFocusModeHotkeysSetterEffect = () => {
toggleEditOnlyInput();
}
},
- TableHotkeyScope.TableSoftFocus,
- [openTableCell],
+ TableHotkeyScope.TableFocus,
+ [openTableCell, isFieldInputOnly, toggleEditOnlyInput, isReadOnly],
);
useScopedHotkeys(
@@ -93,8 +76,8 @@ export const RecordTableCellSoftFocusModeHotkeysSetterEffect = () => {
openTableCell(keyboardEvent.key);
}
},
- TableHotkeyScope.TableSoftFocus,
- [openTableCell],
+ TableHotkeyScope.TableFocus,
+ [openTableCell, isFieldInputOnly, toggleEditOnlyInput, isReadOnly],
{
preventDefault: false,
},
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableNoRecordGroupBodyContextProvider.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableNoRecordGroupBodyContextProvider.tsx
index 7d57d626e..4278883a8 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableNoRecordGroupBodyContextProvider.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableNoRecordGroupBodyContextProvider.tsx
@@ -3,7 +3,7 @@ import { useRecordTableContextOrThrow } from '@/object-record/record-table/conte
import { useHandleContainerMouseEnter } from '@/object-record/record-table/hooks/internal/useHandleContainerMouseEnter';
import { useRecordTableMoveFocus } from '@/object-record/record-table/hooks/useRecordTableMoveFocus';
import { useCloseRecordTableCellNoGroup } from '@/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellNoGroup';
-import { useMoveSoftFocusToCurrentCellOnHover } from '@/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover';
+import { useMoveHoverToCurrentCell } from '@/object-record/record-table/record-table-cell/hooks/useMoveHoverToCurrentCell';
import {
OpenTableCellArgs,
useOpenRecordTableCellV2,
@@ -40,13 +40,10 @@ export const RecordTableNoRecordGroupBodyContextProvider = ({
closeTableCellNoGroup();
};
- const { moveSoftFocusToCurrentCell } =
- useMoveSoftFocusToCurrentCellOnHover(recordTableId);
+ const { moveHoverToCurrentCell } = useMoveHoverToCurrentCell(recordTableId);
- const handleMoveSoftFocusToCurrentCell = (
- cellPosition: TableCellPosition,
- ) => {
- moveSoftFocusToCurrentCell(cellPosition);
+ const handleMoveHoverToCurrentCell = (cellPosition: TableCellPosition) => {
+ moveHoverToCurrentCell(cellPosition);
};
const { triggerActionMenuDropdown } = useTriggerActionMenuDropdown({
@@ -70,7 +67,7 @@ export const RecordTableNoRecordGroupBodyContextProvider = ({
onOpenTableCell: handleOpenTableCell,
onMoveFocus: handleMoveFocus,
onCloseTableCell: handleCloseTableCell,
- onMoveSoftFocusToCurrentCell: handleMoveSoftFocusToCurrentCell,
+ onMoveHoverToCurrentCell: handleMoveHoverToCurrentCell,
onActionMenuDropdownOpened: handleActionMenuDropdown,
onCellMouseEnter: handleContainerMouseEnter,
}}
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupBodyContextProvider.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupBodyContextProvider.tsx
index f65702193..8151628f5 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupBodyContextProvider.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupBodyContextProvider.tsx
@@ -3,7 +3,7 @@ import { useRecordTableContextOrThrow } from '@/object-record/record-table/conte
import { useHandleContainerMouseEnter } from '@/object-record/record-table/hooks/internal/useHandleContainerMouseEnter';
import { useRecordTableMoveFocus } from '@/object-record/record-table/hooks/useRecordTableMoveFocus';
import { useCloseRecordTableCellInGroup } from '@/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellInGroup';
-import { useMoveSoftFocusToCurrentCellOnHover } from '@/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover';
+import { useMoveHoverToCurrentCell } from '@/object-record/record-table/record-table-cell/hooks/useMoveHoverToCurrentCell';
import {
OpenTableCellArgs,
useOpenRecordTableCellV2,
@@ -41,13 +41,10 @@ export const RecordTableRecordGroupBodyContextProvider = ({
closeTableCellInGroup();
};
- const { moveSoftFocusToCurrentCell } =
- useMoveSoftFocusToCurrentCellOnHover(recordTableId);
+ const { moveHoverToCurrentCell } = useMoveHoverToCurrentCell(recordTableId);
- const handleMoveSoftFocusToCurrentCell = (
- cellPosition: TableCellPosition,
- ) => {
- moveSoftFocusToCurrentCell(cellPosition);
+ const handleMoveHoverToCurrentCell = (cellPosition: TableCellPosition) => {
+ moveHoverToCurrentCell(cellPosition);
};
const { triggerActionMenuDropdown } = useTriggerActionMenuDropdown({
@@ -71,7 +68,7 @@ export const RecordTableRecordGroupBodyContextProvider = ({
onOpenTableCell: handleOpenTableCell,
onMoveFocus: handleMoveFocus,
onCloseTableCell: handlecloseTableCellInGroup,
- onMoveSoftFocusToCurrentCell: handleMoveSoftFocusToCurrentCell,
+ onMoveHoverToCurrentCell: handleMoveHoverToCurrentCell,
onActionMenuDropdownOpened: handleActionMenuDropdown,
onCellMouseEnter: handleContainerMouseEnter,
}}
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableScrollToFocusedElementEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableScrollToFocusedElementEffect.tsx
new file mode 100644
index 000000000..b018f500f
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableScrollToFocusedElementEffect.tsx
@@ -0,0 +1,49 @@
+import { recordTableFocusPositionComponentState } from '@/object-record/record-table/states/recordTableFocusPositionComponentState';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+import { useEffect } from 'react';
+import { isDefined } from 'twenty-shared/utils';
+
+export const RecordTableScrollToFocusedElementEffect = () => {
+ const focusPosition = useRecoilComponentValueV2(
+ recordTableFocusPositionComponentState,
+ );
+
+ useEffect(() => {
+ if (!focusPosition) {
+ return;
+ }
+
+ const focusElement = document.getElementById(
+ `record-table-cell-${focusPosition.column}-${focusPosition.row}`,
+ );
+
+ if (!focusElement) {
+ return;
+ }
+
+ const isSecondColumn = focusPosition.column === 1;
+
+ if (isSecondColumn) {
+ const checkBoxColumnCell = document.getElementById(
+ `record-table-cell-0-0`,
+ );
+ const firstColumnCell = document.getElementById(`record-table-cell-1-0`);
+
+ if (isDefined(checkBoxColumnCell) && isDefined(firstColumnCell)) {
+ const checkBoxColumnWidth = checkBoxColumnCell.offsetWidth;
+ const firstColumnWidth = firstColumnCell.offsetWidth;
+ focusElement.style.scrollMarginLeft = `${checkBoxColumnWidth + firstColumnWidth}px`;
+ }
+ }
+
+ focusElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
+
+ return () => {
+ if (isDefined(focusElement)) {
+ focusElement.style.scrollMarginLeft = '';
+ }
+ };
+ }, [focusPosition]);
+
+ return null;
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx
index 63e4fcaec..5fd5335a7 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx
@@ -93,7 +93,7 @@ const meta: Meta = {
onOpenTableCell: () => {},
onMoveFocus: () => {},
onCloseTableCell: () => {},
- onMoveSoftFocusToCurrentCell: () => {},
+ onMoveHoverToCurrentCell: () => {},
onActionMenuDropdownOpened: () => {},
onCellMouseEnter: () => {},
}}
@@ -122,10 +122,7 @@ const meta: Meta = {
void;
onMoveFocus: (direction: MoveFocusDirection) => void;
onCloseTableCell: () => void;
- onMoveSoftFocusToCurrentCell: (cellPosition: TableCellPosition) => void;
+ onMoveHoverToCurrentCell: (cellPosition: TableCellPosition) => void;
onActionMenuDropdownOpened: (
event: React.MouseEvent,
recordId: string,
diff --git a/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableCellContext.ts b/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableCellContext.ts
index 527d99019..7fc397071 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableCellContext.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableCellContext.ts
@@ -6,9 +6,6 @@ import { TableCellPosition } from '@/object-record/record-table/types/TableCellP
export type RecordTableCellContextValue = {
columnDefinition: ColumnDefinition;
- columnIndex: number;
- isInEditMode: boolean;
- hasSoftFocus: boolean;
cellPosition: TableCellPosition;
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useCloseCurrentTableCellInEditMode.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useCloseCurrentTableCellInEditMode.ts
index 33f97d7a1..f4c1806a3 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useCloseCurrentTableCellInEditMode.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useCloseCurrentTableCellInEditMode.ts
@@ -1,45 +1,27 @@
import { useRecoilCallback } from 'recoil';
-import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
-import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
+import { recordTableCellEditModePositionComponentState } from '@/object-record/record-table/states/recordTableCellEditModePositionComponentState';
import { useGoBackToPreviousDropdownFocusId } from '@/ui/layout/dropdown/hooks/useGoBackToPreviousDropdownFocusId';
-import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
export const useCloseCurrentTableCellInEditMode = (recordTableId?: string) => {
const currentTableCellInEditModePositionState =
useRecoilComponentCallbackStateV2(
- currentTableCellInEditModePositionComponentState,
+ recordTableCellEditModePositionComponentState,
recordTableId,
);
- const isTableCellInEditModeFamilyState = useRecoilComponentCallbackStateV2(
- isTableCellInEditModeComponentFamilyState,
- recordTableId,
- );
const { goBackToPreviousDropdownFocusId } =
useGoBackToPreviousDropdownFocusId();
return useRecoilCallback(
- ({ set, snapshot }) => {
+ ({ set }) => {
return async () => {
- const currentTableCellInEditModePosition = getSnapshotValue(
- snapshot,
- currentTableCellInEditModePositionState,
- );
-
- set(
- isTableCellInEditModeFamilyState(currentTableCellInEditModePosition),
- false,
- );
+ set(currentTableCellInEditModePositionState, null);
goBackToPreviousDropdownFocusId();
};
},
- [
- currentTableCellInEditModePositionState,
- isTableCellInEditModeFamilyState,
- goBackToPreviousDropdownFocusId,
- ],
+ [currentTableCellInEditModePositionState, goBackToPreviousDropdownFocusId],
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useDisableSoftFocus.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useDisableSoftFocus.ts
deleted file mode 100644
index 90a5819f4..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useDisableSoftFocus.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { useRecoilCallback } from 'recoil';
-
-import { isSoftFocusActiveComponentState } from '@/object-record/record-table/states/isSoftFocusActiveComponentState';
-import { isSoftFocusOnTableCellComponentFamilyState } from '@/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState';
-import { softFocusPositionComponentState } from '@/object-record/record-table/states/softFocusPositionComponentState';
-import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
-import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-
-export const useDisableSoftFocus = (recordTableId?: string) => {
- const softFocusPositionState = useRecoilComponentCallbackStateV2(
- softFocusPositionComponentState,
- recordTableId,
- );
- const isSoftFocusActiveState = useRecoilComponentCallbackStateV2(
- isSoftFocusActiveComponentState,
- recordTableId,
- );
- const isSoftFocusOnTableCellFamilyState = useRecoilComponentCallbackStateV2(
- isSoftFocusOnTableCellComponentFamilyState,
- recordTableId,
- );
-
- return useRecoilCallback(
- ({ set, snapshot }) => {
- return () => {
- const currentPosition = getSnapshotValue(
- snapshot,
- softFocusPositionState,
- );
-
- set(isSoftFocusActiveState, false);
-
- set(isSoftFocusOnTableCellFamilyState(currentPosition), false);
- };
- },
- [
- isSoftFocusActiveState,
- softFocusPositionState,
- isSoftFocusOnTableCellFamilyState,
- ],
- );
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useGetIsSomeCellInEditMode.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useGetIsSomeCellInEditMode.ts
deleted file mode 100644
index 96e1dfdbd..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useGetIsSomeCellInEditMode.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { useRecoilCallback } from 'recoil';
-
-import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
-import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
-import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
-import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-
-export const useGetIsSomeCellInEditModeState = (recordTableId?: string) => {
- const currentTableCellInEditModePositionState =
- useRecoilComponentCallbackStateV2(
- currentTableCellInEditModePositionComponentState,
- recordTableId,
- );
- const isTableCellInEditModeFamilyState = useRecoilComponentCallbackStateV2(
- isTableCellInEditModeComponentFamilyState,
- recordTableId,
- );
-
- return useRecoilCallback(
- ({ snapshot }) =>
- () => {
- const currentTableCellInEditModePosition = getSnapshotValue(
- snapshot,
- currentTableCellInEditModePositionState,
- );
-
- const isSomeCellInEditModeState = isTableCellInEditModeFamilyState(
- currentTableCellInEditModePosition,
- );
-
- return isSomeCellInEditModeState;
- },
- [currentTableCellInEditModePositionState, isTableCellInEditModeFamilyState],
- );
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useHandleContainerMouseEnter.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useHandleContainerMouseEnter.ts
index e2f0d8e91..7fb081552 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useHandleContainerMouseEnter.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useHandleContainerMouseEnter.ts
@@ -1,10 +1,7 @@
import { useRecoilCallback } from 'recoil';
-import { useMoveSoftFocusToCurrentCellOnHover } from '@/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover';
-import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
-import { isSoftFocusOnTableCellComponentFamilyState } from '@/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState';
-import { isSoftFocusUsingMouseState } from '@/object-record/record-table/states/isSoftFocusUsingMouseState';
-import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
+import { useMoveHoverToCurrentCell } from '@/object-record/record-table/record-table-cell/hooks/useMoveHoverToCurrentCell';
+import { isSomeCellInEditModeComponentSelector } from '@/object-record/record-table/states/selectors/isSomeCellInEditModeComponentSelector';
import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
@@ -18,54 +15,26 @@ export const useHandleContainerMouseEnter = ({
}: {
recordTableId: string;
}) => {
- const { moveSoftFocusToCurrentCell } =
- useMoveSoftFocusToCurrentCellOnHover(recordTableId);
+ const { moveHoverToCurrentCell } = useMoveHoverToCurrentCell(recordTableId);
- const currentTableCellInEditModePositionState =
- useRecoilComponentCallbackStateV2(
- currentTableCellInEditModePositionComponentState,
- recordTableId,
- );
-
- const isSoftFocusOnTableCellFamilyState = useRecoilComponentCallbackStateV2(
- isSoftFocusOnTableCellComponentFamilyState,
- recordTableId,
- );
-
- const isTableCellInEditModeFamilyState = useRecoilComponentCallbackStateV2(
- isTableCellInEditModeComponentFamilyState,
+ const isSomeCellInEditModeSelector = useRecoilComponentCallbackStateV2(
+ isSomeCellInEditModeComponentSelector,
recordTableId,
);
const handleContainerMouseEnter = useRecoilCallback(
- ({ snapshot, set }) =>
+ ({ snapshot }) =>
({ cellPosition }: HandleContainerMouseEnterArgs) => {
- const isSoftFocusOnTableCell = getSnapshotValue(
- snapshot,
- isSoftFocusOnTableCellFamilyState(cellPosition),
- );
-
- const currentTableCellInEditModePosition = getSnapshotValue(
- snapshot,
- currentTableCellInEditModePositionState,
- );
-
const isSomeCellInEditMode = getSnapshotValue(
snapshot,
- isTableCellInEditModeFamilyState(currentTableCellInEditModePosition),
+ isSomeCellInEditModeSelector,
);
- if (!isSomeCellInEditMode && !isSoftFocusOnTableCell) {
- moveSoftFocusToCurrentCell(cellPosition);
- set(isSoftFocusUsingMouseState, true);
+ if (!isSomeCellInEditMode) {
+ moveHoverToCurrentCell(cellPosition);
}
},
- [
- isSoftFocusOnTableCellFamilyState,
- currentTableCellInEditModePositionState,
- isTableCellInEditModeFamilyState,
- moveSoftFocusToCurrentCell,
- ],
+ [isSomeCellInEditModeSelector, moveHoverToCurrentCell],
);
return {
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useLeaveTableFocus.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useLeaveTableFocus.ts
index dad738671..61f627e0b 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useLeaveTableFocus.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useLeaveTableFocus.ts
@@ -1,13 +1,7 @@
-import { useRecoilCallback } from 'recoil';
-
-import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
-
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
+import { useSetIsRecordTableFocusActive } from '@/object-record/record-table/record-table-cell/hooks/useSetIsRecordTableFocusActive';
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
-import { isSoftFocusActiveComponentState } from '@/object-record/record-table/states/isSoftFocusActiveComponentState';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
-import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { useDisableSoftFocus } from './useDisableSoftFocus';
export const useLeaveTableFocus = (recordTableId?: string) => {
const recordTableIdFromContext = useAvailableComponentInstanceIdOrThrow(
@@ -15,33 +9,17 @@ export const useLeaveTableFocus = (recordTableId?: string) => {
recordTableId,
);
- const disableSoftFocus = useDisableSoftFocus(recordTableIdFromContext);
-
- const isSoftFocusActiveState = useRecoilComponentCallbackStateV2(
- isSoftFocusActiveComponentState,
- recordTableIdFromContext,
- );
-
const resetTableRowSelection = useResetTableRowSelection(
recordTableIdFromContext,
);
- return useRecoilCallback(
- ({ snapshot }) =>
- () => {
- const isSoftFocusActive = getSnapshotValue(
- snapshot,
- isSoftFocusActiveState,
- );
-
- resetTableRowSelection();
-
- if (!isSoftFocusActive) {
- return;
- }
-
- disableSoftFocus();
- },
- [disableSoftFocus, isSoftFocusActiveState, resetTableRowSelection],
+ const { setIsFocusActiveForCurrentPosition } = useSetIsRecordTableFocusActive(
+ recordTableIdFromContext,
);
+
+ return () => {
+ resetTableRowSelection();
+
+ setIsFocusActiveForCurrentPosition(false);
+ };
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useMoveEditModeToCellPosition.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useMoveEditModeToCellPosition.ts
deleted file mode 100644
index cdfd84235..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useMoveEditModeToCellPosition.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { useRecoilCallback } from 'recoil';
-
-import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
-
-import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
-import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
-import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { TableCellPosition } from '../../types/TableCellPosition';
-
-export const useMoveEditModeToTableCellPosition = (recordTableId?: string) => {
- const isTableCellInEditModeFamilyState = useRecoilComponentCallbackStateV2(
- isTableCellInEditModeComponentFamilyState,
- recordTableId,
- );
- const currentTableCellInEditModePositionState =
- useRecoilComponentCallbackStateV2(
- currentTableCellInEditModePositionComponentState,
- recordTableId,
- );
-
- return useRecoilCallback(
- ({ set, snapshot }) => {
- return (newPosition: TableCellPosition) => {
- const currentTableCellInEditModePosition = getSnapshotValue(
- snapshot,
- currentTableCellInEditModePositionState,
- );
-
- set(
- isTableCellInEditModeFamilyState(currentTableCellInEditModePosition),
- false,
- );
-
- set(currentTableCellInEditModePositionState, newPosition);
-
- set(isTableCellInEditModeFamilyState(newPosition), true);
- };
- },
- [currentTableCellInEditModePositionState, isTableCellInEditModeFamilyState],
- );
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableFocusPosition.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableFocusPosition.ts
new file mode 100644
index 000000000..520920620
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableFocusPosition.ts
@@ -0,0 +1,28 @@
+import { useRecoilCallback } from 'recoil';
+
+import { recordTableFocusPositionComponentState } from '@/object-record/record-table/states/recordTableFocusPositionComponentState';
+import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
+import { useSetIsRecordTableFocusActive } from '../../record-table-cell/hooks/useSetIsRecordTableFocusActive';
+import { TableCellPosition } from '../../types/TableCellPosition';
+
+export const useSetRecordTableFocusPosition = (recordTableId?: string) => {
+ const focusPositionState = useRecoilComponentCallbackStateV2(
+ recordTableFocusPositionComponentState,
+ recordTableId,
+ );
+
+ const { setIsFocusActive, setIsFocusActiveForCurrentPosition } =
+ useSetIsRecordTableFocusActive(recordTableId);
+
+ return useRecoilCallback(
+ ({ set }) => {
+ return (newPosition: TableCellPosition) => {
+ set(focusPositionState, newPosition);
+
+ setIsFocusActiveForCurrentPosition(false);
+ setIsFocusActive(true, newPosition);
+ };
+ },
+ [focusPositionState, setIsFocusActive, setIsFocusActiveForCurrentPosition],
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetSoftFocusPosition.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetSoftFocusPosition.ts
deleted file mode 100644
index 5a2756216..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetSoftFocusPosition.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { useRecoilCallback } from 'recoil';
-
-import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
-
-import { isSoftFocusActiveComponentState } from '@/object-record/record-table/states/isSoftFocusActiveComponentState';
-import { isSoftFocusOnTableCellComponentFamilyState } from '@/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState';
-import { softFocusPositionComponentState } from '@/object-record/record-table/states/softFocusPositionComponentState';
-import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { TableCellPosition } from '../../types/TableCellPosition';
-
-export const useSetSoftFocusPosition = (recordTableId?: string) => {
- const softFocusPositionState = useRecoilComponentCallbackStateV2(
- softFocusPositionComponentState,
- recordTableId,
- );
- const isSoftFocusActiveState = useRecoilComponentCallbackStateV2(
- isSoftFocusActiveComponentState,
- recordTableId,
- );
- const isSoftFocusOnTableCellFamilyState = useRecoilComponentCallbackStateV2(
- isSoftFocusOnTableCellComponentFamilyState,
- recordTableId,
- );
-
- return useRecoilCallback(
- ({ set, snapshot }) => {
- return (newPosition: TableCellPosition) => {
- const currentPosition = getSnapshotValue(
- snapshot,
- softFocusPositionState,
- );
-
- set(isSoftFocusActiveState, true);
-
- set(isSoftFocusOnTableCellFamilyState(currentPosition), false);
-
- set(softFocusPositionState, newPosition);
-
- set(isSoftFocusOnTableCellFamilyState(newPosition), true);
- };
- },
- [
- softFocusPositionState,
- isSoftFocusActiveState,
- isSoftFocusOnTableCellFamilyState,
- ],
- );
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts
index 90b96d1b9..941b47c0a 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts
@@ -1,11 +1,9 @@
-import { useRecoilCallback, useSetRecoilState } from 'recoil';
+import { useRecoilCallback } from 'recoil';
import { Key } from 'ts-key-enum';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
-import { useGetIsSomeCellInEditModeState } from '@/object-record/record-table/hooks/internal/useGetIsSomeCellInEditMode';
import { useSetHasUserSelectedAllRows } from '@/object-record/record-table/hooks/internal/useSetAllRowSelectedState';
import { useRecordTableMoveFocus } from '@/object-record/record-table/hooks/useRecordTableMoveFocus';
-import { isSoftFocusUsingMouseState } from '@/object-record/record-table/states/isSoftFocusUsingMouseState';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
@@ -15,6 +13,7 @@ import { useUpsertRecordFromState } from '../../hooks/useUpsertRecordFromState';
import { ColumnDefinition } from '../types/ColumnDefinition';
import { TableHotkeyScope } from '../types/TableHotkeyScope';
+import { useSetIsRecordTableFocusActive } from '@/object-record/record-table/record-table-cell/hooks/useSetIsRecordTableFocusActive';
import { availableTableColumnsComponentState } from '@/object-record/record-table/states/availableTableColumnsComponentState';
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
@@ -26,13 +25,12 @@ import { tableLastRowVisibleComponentState } from '@/object-record/record-table/
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
-import { useDisableSoftFocus } from './internal/useDisableSoftFocus';
import { useLeaveTableFocus } from './internal/useLeaveTableFocus';
import { useResetTableRowSelection } from './internal/useResetTableRowSelection';
import { useSelectAllRows } from './internal/useSelectAllRows';
import { useSetRecordTableData } from './internal/useSetRecordTableData';
+import { useSetRecordTableFocusPosition } from './internal/useSetRecordTableFocusPosition';
import { useSetRowSelectedState } from './internal/useSetRowSelectedState';
-import { useSetSoftFocusPosition } from './internal/useSetSoftFocusPosition';
type useRecordTableProps = {
recordTableId?: string;
@@ -145,25 +143,23 @@ export const useRecordTable = (props?: useRecordTableProps) => {
const upsertRecordTableItem = useUpsertRecordFromState;
- const setSoftFocusPosition = useSetSoftFocusPosition(recordTableId);
+ const setFocusPosition = useSetRecordTableFocusPosition(recordTableId);
+
+ const { setIsFocusActiveForCurrentPosition } =
+ useSetIsRecordTableFocusActive(recordTableId);
const { moveDown, moveLeft, moveRight, moveUp } =
useRecordTableMoveFocus(recordTableId);
- const useMapKeyboardToSoftFocus = () => {
- const disableSoftFocus = useDisableSoftFocus(recordTableId);
+ const useMapKeyboardToFocus = () => {
const setHotkeyScope = useSetHotkeyScope();
- const setIsSoftFocusUsingMouseState = useSetRecoilState(
- isSoftFocusUsingMouseState,
- );
-
useScopedHotkeys(
[Key.ArrowUp, `${Key.Shift}+${Key.Enter}`],
() => {
moveUp();
},
- TableHotkeyScope.TableSoftFocus,
+ TableHotkeyScope.TableFocus,
[moveUp],
);
@@ -172,7 +168,7 @@ export const useRecordTable = (props?: useRecordTableProps) => {
() => {
moveDown();
},
- TableHotkeyScope.TableSoftFocus,
+ TableHotkeyScope.TableFocus,
[moveDown],
);
@@ -180,9 +176,8 @@ export const useRecordTable = (props?: useRecordTableProps) => {
[Key.ArrowLeft, `${Key.Shift}+${Key.Tab}`],
() => {
moveLeft();
- setIsSoftFocusUsingMouseState(false);
},
- TableHotkeyScope.TableSoftFocus,
+ TableHotkeyScope.TableFocus,
[moveLeft],
);
@@ -190,9 +185,8 @@ export const useRecordTable = (props?: useRecordTableProps) => {
[Key.ArrowRight, Key.Tab],
() => {
moveRight();
- setIsSoftFocusUsingMouseState(false);
},
- TableHotkeyScope.TableSoftFocus,
+ TableHotkeyScope.TableFocus,
[moveRight],
);
@@ -203,18 +197,15 @@ export const useRecordTable = (props?: useRecordTableProps) => {
goto: true,
keyboardShortcutMenu: true,
});
- disableSoftFocus();
+ setIsFocusActiveForCurrentPosition(false);
},
- TableHotkeyScope.TableSoftFocus,
- [disableSoftFocus],
+ TableHotkeyScope.TableFocus,
+ [setIsFocusActiveForCurrentPosition],
);
};
const { selectAllRows } = useSelectAllRows(recordTableId);
- const isSomeCellInEditModeState =
- useGetIsSomeCellInEditModeState(recordTableId);
-
return {
onColumnsChange,
setAvailableTableColumns,
@@ -228,13 +219,12 @@ export const useRecordTable = (props?: useRecordTableProps) => {
moveLeft,
moveRight,
moveUp,
- useMapKeyboardToSoftFocus,
+ useMapKeyboardToFocus,
selectAllRows,
setOnColumnsChange,
setIsRecordTableInitialLoading,
setRecordTableLastRowVisible,
- setSoftFocusPosition,
- isSomeCellInEditModeState,
+ setFocusPosition,
setHasUserSelectedAllRows,
setOnToggleColumnFilter,
setOnToggleColumnSort,
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTableMoveFocus.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTableMoveFocus.ts
index 8e97bebe2..09cada125 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTableMoveFocus.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTableMoveFocus.ts
@@ -4,16 +4,16 @@ import { MoveFocusDirection } from '@/object-record/record-table/types/MoveFocus
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
+import { useSetRecordTableFocusPosition } from '@/object-record/record-table/hooks/internal/useSetRecordTableFocusPosition';
+import { recordTableFocusPositionComponentState } from '@/object-record/record-table/states/recordTableFocusPositionComponentState';
import { numberOfTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/numberOfTableColumnsComponentSelector';
-import { softFocusPositionComponentState } from '@/object-record/record-table/states/softFocusPositionComponentState';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { useSetSoftFocusPosition } from './internal/useSetSoftFocusPosition';
export const useRecordTableMoveFocus = (recordTableId?: string) => {
- const setSoftFocusPosition = useSetSoftFocusPosition(recordTableId);
+ const setFocusPosition = useSetRecordTableFocusPosition(recordTableId);
- const softFocusPositionState = useRecoilComponentCallbackStateV2(
- softFocusPositionComponentState,
+ const focusPositionState = useRecoilComponentCallbackStateV2(
+ recordTableFocusPositionComponentState,
recordTableId,
);
@@ -25,23 +25,20 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
const moveUp = useRecoilCallback(
({ snapshot }) =>
() => {
- const softFocusPosition = getSnapshotValue(
- snapshot,
- softFocusPositionState,
- );
+ const focusPosition = getSnapshotValue(snapshot, focusPositionState);
- let newRowIndex = softFocusPosition.row - 1;
+ let newRowIndex = focusPosition.row - 1;
if (newRowIndex < 0) {
newRowIndex = 0;
}
- setSoftFocusPosition({
- ...softFocusPosition,
+ setFocusPosition({
+ ...focusPosition,
row: newRowIndex,
});
},
- [softFocusPositionState, setSoftFocusPosition],
+ [focusPositionState, setFocusPosition],
);
const moveDown = useRecoilCallback(
@@ -51,27 +48,20 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
snapshot,
recordIndexAllRecordIdsSelector,
);
- const softFocusPosition = getSnapshotValue(
- snapshot,
- softFocusPositionState,
- );
+ const focusPosition = getSnapshotValue(snapshot, focusPositionState);
- let newRowIndex = softFocusPosition.row + 1;
+ let newRowIndex = focusPosition.row + 1;
if (newRowIndex >= allRecordIds.length) {
newRowIndex = allRecordIds.length - 1;
}
- setSoftFocusPosition({
- ...softFocusPosition,
+ setFocusPosition({
+ ...focusPosition,
row: newRowIndex,
});
},
- [
- recordIndexAllRecordIdsSelector,
- setSoftFocusPosition,
- softFocusPositionState,
- ],
+ [recordIndexAllRecordIdsSelector, setFocusPosition, focusPositionState],
);
const numberOfTableColumnsSelector = useRecoilComponentCallbackStateV2(
@@ -86,18 +76,15 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
snapshot,
recordIndexAllRecordIdsSelector,
);
- const softFocusPosition = getSnapshotValue(
- snapshot,
- softFocusPositionState,
- );
+ const focusPosition = getSnapshotValue(snapshot, focusPositionState);
const numberOfTableColumns = getSnapshotValue(
snapshot,
numberOfTableColumnsSelector,
);
- const currentColumnIndex = softFocusPosition.column;
- const currentRowIndex = softFocusPosition.row;
+ const currentColumnIndex = focusPosition.column;
+ const currentRowIndex = focusPosition.row;
const isLastRowAndLastColumn =
currentColumnIndex === numberOfTableColumns - 1 &&
@@ -114,12 +101,12 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
}
if (isNotLastColumn) {
- setSoftFocusPosition({
+ setFocusPosition({
row: currentRowIndex,
column: currentColumnIndex + 1,
});
} else if (isLastColumnButNotLastRow) {
- setSoftFocusPosition({
+ setFocusPosition({
row: currentRowIndex + 1,
column: 0,
});
@@ -127,27 +114,24 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
},
[
recordIndexAllRecordIdsSelector,
- softFocusPositionState,
+ focusPositionState,
numberOfTableColumnsSelector,
- setSoftFocusPosition,
+ setFocusPosition,
],
);
const moveLeft = useRecoilCallback(
({ snapshot }) =>
() => {
- const softFocusPosition = getSnapshotValue(
- snapshot,
- softFocusPositionState,
- );
+ const focusPosition = getSnapshotValue(snapshot, focusPositionState);
const numberOfTableColumns = getSnapshotValue(
snapshot,
numberOfTableColumnsSelector,
);
- const currentColumnIndex = softFocusPosition.column;
- const currentRowIndex = softFocusPosition.row;
+ const currentColumnIndex = focusPosition.column;
+ const currentRowIndex = focusPosition.row;
const isFirstRowAndFirstColumn =
currentColumnIndex === 0 && currentRowIndex === 0;
@@ -162,22 +146,18 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
}
if (isNotFirstColumn) {
- setSoftFocusPosition({
+ setFocusPosition({
row: currentRowIndex,
column: currentColumnIndex - 1,
});
} else if (isFirstColumnButNotFirstRow) {
- setSoftFocusPosition({
+ setFocusPosition({
row: currentRowIndex - 1,
column: numberOfTableColumns - 1,
});
}
},
- [
- numberOfTableColumnsSelector,
- softFocusPositionState,
- setSoftFocusPosition,
- ],
+ [numberOfTableColumnsSelector, focusPositionState, setFocusPosition],
);
const moveFocus = (direction: MoveFocusDirection) => {
@@ -202,7 +182,7 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
moveLeft,
moveRight,
moveUp,
- setSoftFocusPosition,
+ setFocusPosition,
moveFocus,
};
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodySoftFocusClickOutsideEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFocusClickOutsideEffect.tsx
similarity index 84%
rename from packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodySoftFocusClickOutsideEffect.tsx
rename to packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFocusClickOutsideEffect.tsx
index 65925cfb0..a7fd3b2a9 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodySoftFocusClickOutsideEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFocusClickOutsideEffect.tsx
@@ -3,13 +3,13 @@ import { useRecordTableContextOrThrow } from '@/object-record/record-table/conte
import { useLeaveTableFocus } from '@/object-record/record-table/hooks/internal/useLeaveTableFocus';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
-type RecordTableBodySoftFocusClickOutsideEffectProps = {
+type RecordTableBodyFocusClickOutsideEffectProps = {
tableBodyRef: React.RefObject;
};
-export const RecordTableBodySoftFocusClickOutsideEffect = ({
+export const RecordTableBodyFocusClickOutsideEffect = ({
tableBodyRef,
-}: RecordTableBodySoftFocusClickOutsideEffectProps) => {
+}: RecordTableBodyFocusClickOutsideEffectProps) => {
const { recordTableId } = useRecordTableContextOrThrow();
const leaveTableFocus = useLeaveTableFocus(recordTableId);
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodySoftFocusKeyboardEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFocusKeyboardEffect.tsx
similarity index 66%
rename from packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodySoftFocusKeyboardEffect.tsx
rename to packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFocusKeyboardEffect.tsx
index 66265bc0e..98e7b90ab 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodySoftFocusKeyboardEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFocusKeyboardEffect.tsx
@@ -1,14 +1,14 @@
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
-export const RecordTableBodySoftFocusKeyboardEffect = () => {
+export const RecordTableBodyFocusKeyboardEffect = () => {
const { recordTableId } = useRecordTableContextOrThrow();
- const { useMapKeyboardToSoftFocus } = useRecordTable({
+ const { useMapKeyboardToFocus } = useRecordTable({
recordTableId,
});
- useMapKeyboardToSoftFocus();
+ useMapKeyboardToFocus();
return <>>;
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBody.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBody.tsx
index 02539907e..ef9bf5ff2 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBody.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBody.tsx
@@ -4,6 +4,7 @@ import { RecordTableNoRecordGroupRows } from '@/object-record/record-table/compo
import { RecordTableBodyDragDropContextProvider } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDragDropContextProvider';
import { RecordTableBodyDroppable } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppable';
import { RecordTableBodyLoading } from '@/object-record/record-table/record-table-body/components/RecordTableBodyLoading';
+import { RecordTableCellPortals } from '@/object-record/record-table/record-table-cell/components/RecordTableCellPortals';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@@ -25,6 +26,7 @@ export const RecordTableNoRecordGroupBody = () => {
+
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody.tsx
index 087019240..e6720e66b 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody.tsx
@@ -6,6 +6,7 @@ import { RecordTableRecordGroupRows } from '@/object-record/record-table/compone
import { RecordTableBodyDroppable } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppable';
import { RecordTableBodyLoading } from '@/object-record/record-table/record-table-body/components/RecordTableBodyLoading';
import { RecordTableBodyRecordGroupDragDropContextProvider } from '@/object-record/record-table/record-table-body/components/RecordTableBodyRecordGroupDragDropContextProvider';
+import { RecordTableCellPortals } from '@/object-record/record-table/record-table-cell/components/RecordTableCellPortals';
import { RecordTableRecordGroupSection } from '@/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
@@ -42,6 +43,7 @@ export const RecordTableRecordGroupsBody = () => {
+
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCell.tsx
index 4d6fcdd74..32b2687c5 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCell.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCell.tsx
@@ -1,15 +1,11 @@
import { FieldDisplay } from '@/object-record/record-field/components/FieldDisplay';
import { FieldFocusContextProvider } from '@/object-record/record-field/contexts/FieldFocusContextProvider';
import { RecordTableCellContainer } from '@/object-record/record-table/record-table-cell/components/RecordTableCellContainer';
-import { RecordTableCellFieldInput } from '@/object-record/record-table/record-table-cell/components/RecordTableCellFieldInput';
export const RecordTableCell = () => {
return (
- }
- nonEditModeContent={}
- />
+ } />
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellBaseContainer.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellBaseContainer.tsx
index 9fddb0436..7e9593e32 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellBaseContainer.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellBaseContainer.tsx
@@ -9,11 +9,11 @@ import { useOpenRecordTableCellFromCell } from '@/object-record/record-table/rec
import { BORDER_COMMON, ThemeContext } from 'twenty-ui/theme';
const StyledBaseContainer = styled.div<{
- hasSoftFocus: boolean;
fontColorExtraLight: string;
fontColorMedium: string;
backgroundColorTransparentSecondary: string;
isReadOnly: boolean;
+ borderColorBlue: string;
}>`
align-items: center;
box-sizing: border-box;
@@ -23,23 +23,10 @@ const StyledBaseContainer = styled.div<{
position: relative;
user-select: none;
- background: ${({ hasSoftFocus, backgroundColorTransparentSecondary }) =>
- hasSoftFocus ? backgroundColorTransparentSecondary : 'none'};
-
- border-radius: ${({ hasSoftFocus, isReadOnly }) =>
- hasSoftFocus && !isReadOnly ? BORDER_COMMON.radius.sm : 'none'};
-
- outline: ${({
- hasSoftFocus,
- fontColorExtraLight,
- fontColorMedium,
- isReadOnly,
- }) =>
- hasSoftFocus
- ? isReadOnly
- ? `1px solid ${fontColorMedium}`
- : `1px solid ${fontColorExtraLight}`
- : 'none'};
+ &.focus-active {
+ border-radius: ${BORDER_COMMON.radius.sm};
+ outline: 1px solid ${({ borderColorBlue }) => borderColorBlue};
+ }
`;
export const RecordTableCellBaseContainer = ({
@@ -52,18 +39,16 @@ export const RecordTableCellBaseContainer = ({
const { openTableCell } = useOpenRecordTableCellFromCell();
const { theme } = useContext(ThemeContext);
- const { hasSoftFocus, cellPosition } = useContext(RecordTableCellContext);
+ const { cellPosition } = useContext(RecordTableCellContext);
- const { onMoveSoftFocusToCurrentCell, onCellMouseEnter } =
+ const { onMoveHoverToCurrentCell, onCellMouseEnter } =
useRecordTableBodyContextOrThrow();
const handleContainerMouseMove = () => {
setIsFocused(true);
- if (!hasSoftFocus) {
- onCellMouseEnter({
- cellPosition,
- });
- }
+ onCellMouseEnter({
+ cellPosition,
+ });
};
const handleContainerMouseLeave = () => {
@@ -71,10 +56,8 @@ export const RecordTableCellBaseContainer = ({
};
const handleContainerClick = () => {
- if (!hasSoftFocus) {
- onMoveSoftFocusToCurrentCell(cellPosition);
- openTableCell();
- }
+ onMoveHoverToCurrentCell(cellPosition);
+ openTableCell();
};
return (
@@ -87,8 +70,9 @@ export const RecordTableCellBaseContainer = ({
}
fontColorExtraLight={theme.font.color.extraLight}
fontColorMedium={theme.border.color.medium}
- hasSoftFocus={hasSoftFocus}
+ borderColorBlue={theme.adaptiveColors.blue4}
isReadOnly={isReadOnly ?? false}
+ id={`record-table-cell-${cellPosition.column}-${cellPosition.row}`}
>
{children}
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx
index 9db07ceaf..480a67d77 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx
@@ -1,14 +1,10 @@
-import { ReactElement, useContext } from 'react';
+import { ReactElement } from 'react';
-import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
import { RecordTableCellBaseContainer } from '@/object-record/record-table/record-table-cell/components/RecordTableCellBaseContainer';
-import { RecordTableCellSoftFocusModeHotkeysSetterEffect } from '@/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusModeHotkeysSetterEffect';
import { RecordTableCellDisplayMode } from './RecordTableCellDisplayMode';
-import { RecordTableCellEditMode } from './RecordTableCellEditMode';
export type RecordTableCellContainerProps = {
- editModeContent: ReactElement;
nonEditModeContent: ReactElement;
transparent?: boolean;
maxContentWidth?: number;
@@ -17,23 +13,13 @@ export type RecordTableCellContainerProps = {
};
export const RecordTableCellContainer = ({
- editModeContent,
nonEditModeContent,
}: RecordTableCellContainerProps) => {
- const { hasSoftFocus, isInEditMode } = useContext(RecordTableCellContext);
-
return (
- {isInEditMode ? (
- {editModeContent}
- ) : (
-
- {nonEditModeContent}
-
- )}
- {hasSoftFocus ? (
-
- ) : null}
+
+ {nonEditModeContent}
+
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx
index 4f0f2c342..c11df4434 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx
@@ -26,7 +26,7 @@ const StyledEmptyPlaceholderField = withTheme(styled.div<{ theme: Theme }>`
`);
export type EditableCellDisplayContainerProps = {
- softFocus?: boolean;
+ focus?: boolean;
onClick?: () => void;
scrollRef?: Ref;
isHovered?: boolean;
@@ -36,7 +36,7 @@ export type EditableCellDisplayContainerProps = {
export const RecordTableCellDisplayContainer = ({
children,
- softFocus,
+ focus,
onClick,
scrollRef,
onContextMenu,
@@ -44,7 +44,7 @@ export const RecordTableCellDisplayContainer = ({
}: React.PropsWithChildren) => (
{
+}: {
+ children: ReactNode;
+}) => {
const { recordId, isReadOnly } = useContext(FieldContext);
- const { columnIndex, hasSoftFocus } = useContext(RecordTableCellContext);
-
- const isMobile = useIsMobile();
-
const { onActionMenuDropdownOpened } = useRecordTableBodyContextOrThrow();
const { openTableCell } = useOpenRecordTableCellFromCell();
const isFieldInputOnly = useIsFieldInputOnly();
- const isFirstColumn = columnIndex === 0;
-
- const showButton =
- hasSoftFocus &&
- !isFieldInputOnly &&
- !isReadOnly &&
- !(isMobile && isFirstColumn);
const handleActionMenuDropdown = (event: React.MouseEvent) => {
onActionMenuDropdownOpened(event, recordId);
@@ -41,15 +29,11 @@ export const RecordTableCellDisplayMode = ({
};
return (
- <>
-
- {children}
-
- {showButton && }
- >
+
+ {children}
+
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditButton.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditButton.tsx
index 886dabca1..aef9c027c 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditButton.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditButton.tsx
@@ -8,12 +8,12 @@ import { isDefined } from 'twenty-shared/utils';
import { IconArrowUpRight, IconPencil } from 'twenty-ui/display';
export const RecordTableCellEditButton = () => {
- const { columnIndex } = useContext(RecordTableCellContext);
+ const { cellPosition } = useContext(RecordTableCellContext);
const { openTableCell } = useOpenRecordTableCellFromCell();
const isFieldInputOnly = useIsFieldInputOnly();
- const isFirstColumn = columnIndex === 0;
+ const isFirstColumn = cellPosition.column === 0;
const customButtonIcon = useGetButtonIcon();
const buttonIcon = isFirstColumn
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditMode.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditMode.tsx
index 0ad8d1c67..13b18d27b 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditMode.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditMode.tsx
@@ -1,7 +1,10 @@
+import { useIsFieldInputOnly } from '@/object-record/record-field/hooks/useIsFieldInputOnly';
import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/states/contexts/RecordFieldComponentInstanceContext';
import { recordFieldInputIsFieldInErrorComponentState } from '@/object-record/record-field/states/recordFieldInputIsFieldInErrorComponentState';
import { recordFieldInputLayoutDirectionComponentState } from '@/object-record/record-field/states/recordFieldInputLayoutDirectionComponentState';
import { recordFieldInputLayoutDirectionLoadingComponentState } from '@/object-record/record-field/states/recordFieldInputLayoutDirectionLoadingComponentState';
+import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
+import { useSetRecordTableFocusPosition } from '@/object-record/record-table/hooks/internal/useSetRecordTableFocusPosition';
import { OverlayContainer } from '@/ui/layout/overlay/components/OverlayContainer';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@@ -14,9 +17,11 @@ import {
offset,
useFloating,
} from '@floating-ui/react';
-import { ReactElement } from 'react';
+import { ReactElement, useContext } from 'react';
-const StyledEditableCellEditModeContainer = styled.div`
+const StyledEditableCellEditModeContainer = styled.div<{
+ isFieldInputOnly: boolean;
+}>`
align-items: center;
display: flex;
height: 100%;
@@ -25,11 +30,17 @@ const StyledEditableCellEditModeContainer = styled.div
-
- {children}
-
+ {isFieldInputOnly ? (
+ {
+ setFocusPosition(cellPosition);
+ }}
+ >
+ {children}
+
+ ) : (
+
+ {children}
+
+ )}
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditModePortal.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditModePortal.tsx
new file mode 100644
index 000000000..49384d00d
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditModePortal.tsx
@@ -0,0 +1,44 @@
+import { RecordTableCellPortalWrapper } from '@/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+
+import { RecordTableFocusModeHotkeysSetterEffect } from '@/object-record/record-table/components/RecordTableFocusModeHotkeysSetterEffect';
+import { RecordTableCellEditMode } from '@/object-record/record-table/record-table-cell/components/RecordTableCellEditMode';
+import { RecordTableCellFieldInput } from '@/object-record/record-table/record-table-cell/components/RecordTableCellFieldInput';
+import { recordTableCellEditModePositionComponentState } from '@/object-record/record-table/states/recordTableCellEditModePositionComponentState';
+import { recordTableFocusPositionComponentState } from '@/object-record/record-table/states/recordTableFocusPositionComponentState';
+import styled from '@emotion/styled';
+
+const StyledRecordTableCellHoveredPortal = styled.div`
+ height: 100%;
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: 100%;
+`;
+
+export const RecordTableCellEditModePortal = () => {
+ const focusedCellPosition = useRecoilComponentValueV2(
+ recordTableFocusPositionComponentState,
+ );
+
+ const currentTableCellInEditModePosition = useRecoilComponentValueV2(
+ recordTableCellEditModePositionComponentState,
+ );
+
+ if (!focusedCellPosition) {
+ return null;
+ }
+
+ return (
+
+ {currentTableCellInEditModePosition && (
+
+
+
+
+
+ )}
+
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellHoveredPortal.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellHoveredPortal.tsx
new file mode 100644
index 000000000..50b5273fb
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellHoveredPortal.tsx
@@ -0,0 +1,96 @@
+import { RecordTableCellPortalWrapper } from '@/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper';
+import { recordTableHoverPositionComponentState } from '@/object-record/record-table/states/recordTableHoverPositionComponentState';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+import styled from '@emotion/styled';
+
+import { FieldDisplay } from '@/object-record/record-field/components/FieldDisplay';
+import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
+import { useIsFieldInputOnly } from '@/object-record/record-field/hooks/useIsFieldInputOnly';
+import { RecordTableCellDisplayMode } from '@/object-record/record-table/record-table-cell/components/RecordTableCellDisplayMode';
+import { RecordTableCellEditButton } from '@/object-record/record-table/record-table-cell/components/RecordTableCellEditButton';
+import { RecordTableCellEditMode } from '@/object-record/record-table/record-table-cell/components/RecordTableCellEditMode';
+import { RecordTableCellFieldInput } from '@/object-record/record-table/record-table-cell/components/RecordTableCellFieldInput';
+import { useContext } from 'react';
+import { BORDER_COMMON } from 'twenty-ui/theme';
+import { useIsMobile } from 'twenty-ui/utilities';
+
+const StyledRecordTableCellHoveredPortalContent = styled.div<{
+ isReadOnly: boolean;
+}>`
+ align-items: center;
+ background: ${({ theme }) => theme.background.transparent.secondary};
+ background-color: ${({ theme }) => theme.background.primary};
+ border-radius: ${({ isReadOnly }) =>
+ !isReadOnly ? BORDER_COMMON.radius.sm : 'none'};
+ box-sizing: border-box;
+ cursor: ${({ isReadOnly }) => (isReadOnly ? 'default' : 'pointer')};
+ display: flex;
+
+ height: 32px;
+
+ outline: ${({ theme, isReadOnly }) =>
+ isReadOnly
+ ? `1px solid ${theme.border.color.medium}`
+ : `1px solid ${theme.font.color.extraLight}`};
+
+ position: relative;
+ user-select: none;
+`;
+
+const RecordTableCellHoveredPortalContent = () => {
+ const hoverPosition = useRecoilComponentValueV2(
+ recordTableHoverPositionComponentState,
+ );
+
+ const isMobile = useIsMobile();
+
+ const isFirstColumn = hoverPosition?.column === 0;
+
+ const { isReadOnly } = useContext(FieldContext);
+
+ const isFieldInputOnly = useIsFieldInputOnly();
+
+ const showButton =
+ !isFieldInputOnly && !isReadOnly && !(isMobile && isFirstColumn);
+
+ return (
+
+ {isFieldInputOnly ? (
+
+
+
+ ) : (
+
+
+
+ )}
+ {showButton && }
+
+ );
+};
+
+const StyledRecordTableCellHoveredPortal = styled.div`
+ height: 100%;
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: 100%;
+`;
+
+export const RecordTableCellHoveredPortal = () => {
+ const hoverPosition = useRecoilComponentValueV2(
+ recordTableHoverPositionComponentState,
+ );
+
+ if (!hoverPosition) {
+ return null;
+ }
+
+ return (
+
+
+
+
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx
new file mode 100644
index 000000000..9c307b9e4
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx
@@ -0,0 +1,66 @@
+import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
+import { getBasePathToShowPage } from '@/object-metadata/utils/getBasePathToShowPage';
+import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
+import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
+import { RecordTableRowContextProvider } from '@/object-record/record-table/contexts/RecordTableRowContext';
+import { RecordTableCellFieldContextWrapper } from '@/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper';
+import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
+import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+import ReactDOM from 'react-dom';
+
+export const RecordTableCellPortalWrapper = ({
+ position,
+ children,
+}: {
+ position: TableCellPosition;
+ children: React.ReactNode;
+}) => {
+ const anchorElement = document.body.querySelector(
+ `#record-table-cell-${position.column}-${position.row}`,
+ ) as HTMLElement;
+
+ const allRecordIds = useRecoilComponentValueV2(
+ recordIndexAllRecordIdsComponentSelector,
+ );
+
+ const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
+
+ const visibleTableColumns = useRecoilComponentValueV2(
+ visibleTableColumnsComponentSelector,
+ );
+
+ if (!anchorElement) {
+ return null;
+ }
+
+ const recordId = allRecordIds[position.row];
+
+ return ReactDOM.createPortal(
+
+
+
+ {children}
+
+
+ ,
+ anchorElement,
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortals.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortals.tsx
new file mode 100644
index 000000000..f48c05abb
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortals.tsx
@@ -0,0 +1,22 @@
+import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
+import { RecordTableCellEditModePortal } from '@/object-record/record-table/record-table-cell/components/RecordTableCellEditModePortal';
+import { RecordTableCellHoveredPortal } from '@/object-record/record-table/record-table-cell/components/RecordTableCellHoveredPortal';
+import { isRecordTableFocusActiveComponentState } from '@/object-record/record-table/states/isRecordTableFocusActiveComponentState';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+
+export const RecordTableCellPortals = () => {
+ const { recordTableId } = useRecordTableContextOrThrow();
+
+ const isRecordTableFocusActive = useRecoilComponentValueV2(
+ isRecordTableFocusActiveComponentState,
+ recordTableId,
+ );
+
+ return (
+ <>
+
+
+ {isRecordTableFocusActive && }
+ >
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellWrapper.tsx
index 81f2ea988..f7259963f 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellWrapper.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellWrapper.tsx
@@ -2,11 +2,8 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
import { useRecordTableRowContextOrThrow } from '@/object-record/record-table/contexts/RecordTableRowContext';
import { RecordTableCellFieldContextWrapper } from '@/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper';
-import { isSoftFocusOnTableCellComponentFamilyState } from '@/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState';
-import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
-import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
import { useMemo } from 'react';
export const RecordTableCellWrapper = ({
@@ -28,23 +25,10 @@ export const RecordTableCellWrapper = ({
[columnIndex, rowIndex],
);
- const isInEditMode = useRecoilComponentFamilyValueV2(
- isTableCellInEditModeComponentFamilyState,
- currentTableCellPosition,
- );
-
- const hasSoftFocus = useRecoilComponentFamilyValueV2(
- isSoftFocusOnTableCellComponentFamilyState,
- currentTableCellPosition,
- );
-
return (
{
- it('should return the current table cell position', () => {
- const wrapper = ({ children }: { children: React.ReactNode }) => (
-
-
-
- {children}
-
-
-
- );
-
- const { result } = renderHook(() => useCurrentTableCellPosition(), {
- wrapper,
- });
-
- expect(result.current).toEqual({
- column: 3,
- row: 2,
- });
- });
-});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useCurrentTableCellEditMode.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useCurrentTableCellEditMode.test.tsx
deleted file mode 100644
index 47f024ace..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useCurrentTableCellEditMode.test.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import { act, renderHook, waitFor } from '@testing-library/react';
-import { RecoilRoot } from 'recoil';
-
-import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
-
-import { useCurrentTableCellEditMode } from '../useCurrentTableCellEditMode';
-
-const onColumnsChange = jest.fn();
-
-const recordTableId = 'scopeId';
-
-const Wrapper = ({ children }: { children: React.ReactNode }) => (
-
-
- {children}
-
-
-);
-
-describe('useCurrentTableCellEditMode.', () => {
- it('should return initial values', () => {
- const { result } = renderHook(() => useCurrentTableCellEditMode(), {
- wrapper: Wrapper,
- });
-
- expect(result.current.isCurrentTableCellInEditMode).toBe(false);
- expect(result.current.setCurrentTableCellInEditMode).toBeInstanceOf(
- Function,
- );
- });
-
- it('should call setCurrentTableCellInEditMode', async () => {
- const { result } = renderHook(() => useCurrentTableCellEditMode(), {
- wrapper: Wrapper,
- });
-
- expect(result.current.isCurrentTableCellInEditMode).toBe(false);
-
- act(() => {
- result.current.setCurrentTableCellInEditMode();
- });
-
- await waitFor(() => {
- expect(result.current.isCurrentTableCellInEditMode).toBe(true);
- });
- });
-});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useIsSoftFocusOnCurrentTableCell.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useIsSoftFocusOnCurrentTableCell.test.tsx
deleted file mode 100644
index c89570918..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useIsSoftFocusOnCurrentTableCell.test.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { renderHook } from '@testing-library/react';
-import { RecoilRoot } from 'recoil';
-
-import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
-import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
-import { RecordTableRowContextProvider } from '@/object-record/record-table/contexts/RecordTableRowContext';
-import { RecordTableRowDraggableContextProvider } from '@/object-record/record-table/contexts/RecordTableRowDraggableContext';
-import {
- recordTableCellContextValue,
- recordTableRowContextValue,
- recordTableRowDraggableContextValue,
-} from '@/object-record/record-table/record-table-cell/hooks/__mocks__/cell';
-import { useIsSoftFocusOnCurrentTableCell } from '@/object-record/record-table/record-table-cell/hooks/useIsSoftFocusOnCurrentTableCell';
-
-const Wrapper = ({ children }: { children: React.ReactNode }) => (
-
-
-
-
-
- {children}
-
-
-
-
-
-);
-
-describe('useIsSoftFocusOnCurrentTableCell', () => {
- it('should work as expected', () => {
- const { result } = renderHook(() => useIsSoftFocusOnCurrentTableCell(), {
- wrapper: Wrapper,
- });
-
- expect(result.current).toBe(false);
- });
-});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveHoverToCurrentCell.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveHoverToCurrentCell.test.tsx
new file mode 100644
index 000000000..d804584c3
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveHoverToCurrentCell.test.tsx
@@ -0,0 +1,80 @@
+import { renderHook } from '@testing-library/react';
+import { act } from 'react';
+import { RecoilRoot, useRecoilValue } from 'recoil';
+
+import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
+import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
+import { RecordTableRowContextProvider } from '@/object-record/record-table/contexts/RecordTableRowContext';
+import { RecordTableRowDraggableContextProvider } from '@/object-record/record-table/contexts/RecordTableRowDraggableContext';
+import {
+ recordTableCellContextValue,
+ recordTableRowContextValue,
+ recordTableRowDraggableContextValue,
+} from '@/object-record/record-table/record-table-cell/hooks/__mocks__/cell';
+import { useMoveHoverToCurrentCell } from '@/object-record/record-table/record-table-cell/hooks/useMoveHoverToCurrentCell';
+import { recordTableHoverPositionComponentState } from '@/object-record/record-table/states/recordTableHoverPositionComponentState';
+import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope';
+import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
+
+const Wrapper = ({ children }: { children: React.ReactNode }) => (
+ {
+ set(currentHotkeyScopeState, {
+ scope: TableHotkeyScope.TableFocus,
+ customScopes: {},
+ });
+ }}
+ >
+
+
+
+
+ {children}
+
+
+
+
+
+);
+
+describe('useMoveHoverToCurrentCell', () => {
+ it('should work as expected', () => {
+ const { result } = renderHook(
+ () => {
+ const recordTableHoverPosition = useRecoilValue(
+ recordTableHoverPositionComponentState.atomFamily({
+ instanceId: 'test-record-table-instance-id',
+ }),
+ );
+ const { moveHoverToCurrentCell } = useMoveHoverToCurrentCell(
+ 'test-record-table-instance-id',
+ );
+
+ return {
+ moveHoverToCurrentCell,
+ recordTableHoverPosition,
+ };
+ },
+ {
+ wrapper: Wrapper,
+ },
+ );
+
+ act(() => {
+ result.current.moveHoverToCurrentCell({
+ column: 3,
+ row: 2,
+ });
+ });
+
+ expect(result.current.recordTableHoverPosition).toEqual({
+ column: 3,
+ row: 2,
+ });
+ });
+});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveSoftFocusToCurrentCellOnHover.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveSoftFocusToCurrentCellOnHover.test.tsx
deleted file mode 100644
index 3b5a5d94b..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useMoveSoftFocusToCurrentCellOnHover.test.tsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import { renderHook } from '@testing-library/react';
-import { act } from 'react';
-import { CallbackInterface, RecoilRoot } from 'recoil';
-
-import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
-import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
-import { RecordTableRowContextProvider } from '@/object-record/record-table/contexts/RecordTableRowContext';
-import { RecordTableRowDraggableContextProvider } from '@/object-record/record-table/contexts/RecordTableRowDraggableContext';
-import {
- recordTableCellContextValue,
- recordTableRowContextValue,
- recordTableRowDraggableContextValue,
-} from '@/object-record/record-table/record-table-cell/hooks/__mocks__/cell';
-import { useMoveSoftFocusToCurrentCellOnHover } from '@/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover';
-import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
-import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope';
-
-const mockSoftFocusPositionState = {
- key: 'softFocusPositionComponentState__{"instanceId":"scopeId"}',
-};
-const mockSoftFocusActiveState = {
- key: 'isSoftFocusActiveComponentState__{"instanceId":"scopeId"}',
-};
-const mockIsSoftFocusOnTableCellFamilyStateCurrentPosition = {
- key: 'isSoftFocusOnTableCellComponentFamilyState__{"familyKey":{"column":1,"row":0},"instanceId":"scopeId"}',
-};
-const mockIsSoftFocusOnTableCellFamilyStateNewPosition = {
- key: 'isSoftFocusOnTableCellComponentFamilyState__{"familyKey":{"column":3,"row":2},"instanceId":"scopeId"}',
-};
-const mockCurrentTableCellInEditModePositionState = {
- key: 'currentTableCellInEditModePositionComponentState__{"instanceId":"scopeId"}',
-};
-const mockIsTableCellInEditModeFamilyState = {
- key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":1,"row":0},"instanceId":"scopeId"}',
-};
-const mockCurrentHotKeyScopeState = {
- key: 'currentHotkeyScopeState',
-};
-
-const mockCallbackInterface = {
- set: jest.fn(),
- snapshot: {
- getLoadable: (recoilValue: { key: string }) => ({
- getValue: () => {
- if (recoilValue.key === mockSoftFocusPositionState.key)
- return { column: 1, row: 0 };
- if (recoilValue.key === mockCurrentTableCellInEditModePositionState.key)
- return { column: 1, row: 0 };
- else if (recoilValue.key === mockIsTableCellInEditModeFamilyState.key)
- return false;
- else if (recoilValue.key === mockCurrentHotKeyScopeState.key)
- return { scope: TableHotkeyScope.Table };
- },
- }),
- },
-} as unknown as CallbackInterface;
-
-const setSoftFocusPosition = jest.fn();
-const setOnColumnsChange = jest.fn();
-const setHotkeyScope = jest.fn();
-
-jest.mock('recoil', () => ({
- ...jest.requireActual('recoil'),
- useRecoilCallback: (
- callback: (
- _interface: CallbackInterface,
- ) => (newPosition: TableCellPosition) => void,
- ) => callback(mockCallbackInterface),
-}));
-jest.mock('@/object-record/record-table/hooks/useRecordTable', () => ({
- useRecordTable: () => ({
- setSoftFocusPosition,
- setOnColumnsChange,
- }),
-}));
-jest.mock('@/ui/utilities/hotkey/hooks/useSetHotkeyScope', () => ({
- useSetHotkeyScope: () => setHotkeyScope,
-}));
-
-const Wrapper = ({ children }: { children: React.ReactNode }) => (
-
-
-
-
-
- {children}
-
-
-
-
-
-);
-
-describe('useMoveSoftFocusToCurrentCellOnHover', () => {
- it('should work as expected', () => {
- const { result } = renderHook(
- () => useMoveSoftFocusToCurrentCellOnHover('scopeId'),
- { wrapper: Wrapper },
- );
-
- act(() => {
- result.current.moveSoftFocusToCurrentCell({
- column: 3,
- row: 2,
- });
- });
-
- expect(mockCallbackInterface.set).toHaveBeenNthCalledWith(
- 1,
- mockSoftFocusActiveState,
- true,
- );
-
- expect(mockCallbackInterface.set).toHaveBeenNthCalledWith(
- 2,
- mockIsSoftFocusOnTableCellFamilyStateCurrentPosition,
- false,
- );
-
- expect(mockCallbackInterface.set).toHaveBeenNthCalledWith(
- 3,
- mockSoftFocusPositionState,
- { column: 3, row: 2 },
- );
-
- expect(mockCallbackInterface.set).toHaveBeenNthCalledWith(
- 4,
- mockIsSoftFocusOnTableCellFamilyStateNewPosition,
- true,
- );
-
- expect(mockCallbackInterface.set).toHaveBeenNthCalledWith(
- 5,
- mockSoftFocusActiveState,
- true,
- );
-
- expect(setHotkeyScope).toHaveBeenCalledWith(
- TableHotkeyScope.TableSoftFocus,
- );
- });
-});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSelectedTableCellEditMode.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSelectedTableCellEditMode.test.tsx
deleted file mode 100644
index c0eb841e8..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSelectedTableCellEditMode.test.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import { act, renderHook } from '@testing-library/react';
-import { CallbackInterface, RecoilRoot } from 'recoil';
-
-import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
-
-import { useSelectedTableCellEditMode } from '../useSelectedTableCellEditMode';
-
-const scopeId = 'yourScopeId';
-
-const mockCallbackInterface = {
- set: jest.fn(),
- snapshot: {
- getLoadable: () => ({
- getValue: () => ({ row: 0, column: 0 }),
- }),
- },
-} as unknown as CallbackInterface;
-
-jest.mock('recoil', () => ({
- ...jest.requireActual('recoil'),
- useRecoilCallback: (
- callback: (
- _interface: CallbackInterface,
- ) => (newPosition: TableCellPosition) => void,
- ) => callback(mockCallbackInterface),
-}));
-
-describe('useSelectedTableCellEditMode', () => {
- it('should have property setSelectedTableCellEditMode', async () => {
- const tableCellPosition: TableCellPosition = {
- row: 1,
- column: 5,
- };
-
- const { result } = renderHook(
- () => useSelectedTableCellEditMode({ scopeId }),
- {
- wrapper: RecoilRoot,
- },
- );
-
- act(() => {
- result.current.setSelectedTableCellEditMode(
- tableCellPosition.row,
- tableCellPosition.column,
- );
- });
-
- expect(mockCallbackInterface.set).toHaveBeenCalledWith(
- {
- key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":0,"row":0},"instanceId":"yourScopeId"}',
- },
- false,
- );
-
- expect(mockCallbackInterface.set).toHaveBeenCalledWith(
- {
- key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":5,"row":1},"instanceId":"yourScopeId"}',
- },
- true,
- );
- });
-});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSetIsRecordTableFocusActive.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSetIsRecordTableFocusActive.test.tsx
new file mode 100644
index 000000000..4f7769ddb
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSetIsRecordTableFocusActive.test.tsx
@@ -0,0 +1,155 @@
+import { renderHook } from '@testing-library/react';
+import React, { act } from 'react';
+import { RecoilRoot, useRecoilValue } from 'recoil';
+
+import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
+import { useSetIsRecordTableFocusActive } from '@/object-record/record-table/record-table-cell/hooks/useSetIsRecordTableFocusActive';
+import { isRecordTableFocusActiveComponentState } from '@/object-record/record-table/states/isRecordTableFocusActiveComponentState';
+import { recordTableFocusPositionComponentState } from '@/object-record/record-table/states/recordTableFocusPositionComponentState';
+import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
+
+const mockClassList = {
+ add: jest.fn(),
+ remove: jest.fn(),
+};
+
+const mockGetElementById = jest.spyOn(document, 'getElementById');
+
+const Wrapper = ({ children }: { children: React.ReactNode }) => (
+ {
+ set(
+ isRecordTableFocusActiveComponentState.atomFamily({
+ instanceId: 'test-table-id',
+ }),
+ false,
+ );
+ set(
+ recordTableFocusPositionComponentState.atomFamily({
+ instanceId: 'test-table-id',
+ }),
+ {
+ column: 1,
+ row: 0,
+ },
+ );
+ }}
+ >
+
+ {children}
+
+
+);
+
+const renderHooks = () => {
+ const { result } = renderHook(
+ () => {
+ const { setIsFocusActive, setIsFocusActiveForCurrentPosition } =
+ useSetIsRecordTableFocusActive('test-table-id');
+ const isRecordTableFocusActive = useRecoilValue(
+ isRecordTableFocusActiveComponentState.atomFamily({
+ instanceId: 'test-table-id',
+ }),
+ );
+ const focusPosition = useRecoilValue(
+ recordTableFocusPositionComponentState.atomFamily({
+ instanceId: 'test-table-id',
+ }),
+ );
+ return {
+ setIsFocusActive,
+ setIsFocusActiveForCurrentPosition,
+ isRecordTableFocusActive,
+ focusPosition,
+ };
+ },
+ { wrapper: Wrapper },
+ );
+
+ return { result };
+};
+
+describe('useSetIsRecordTableFocusActive', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+
+ mockGetElementById.mockReturnValue({
+ classList: mockClassList,
+ } as unknown as HTMLElement);
+ });
+
+ it('should set focus active state and add class to cell element when focus is activated', () => {
+ const { result } = renderHooks();
+
+ const cellPosition: TableCellPosition = { column: 1, row: 0 };
+
+ act(() => {
+ result.current.setIsFocusActive(true, cellPosition);
+ });
+
+ expect(mockGetElementById).toHaveBeenCalledWith('record-table-cell-1-0');
+
+ expect(mockClassList.add).toHaveBeenCalledWith('focus-active');
+
+ expect(result.current.isRecordTableFocusActive).toBe(true);
+
+ expect(result.current.focusPosition).toEqual(cellPosition);
+ });
+
+ it('should remove focus-active class when focus is deactivated and update isRecordTableFocusActiveComponentState', () => {
+ const { result } = renderHooks();
+
+ const cellPosition: TableCellPosition = { column: 1, row: 0 };
+
+ act(() => {
+ result.current.setIsFocusActive(false, cellPosition);
+ });
+
+ expect(mockGetElementById).toHaveBeenCalledWith('record-table-cell-1-0');
+
+ expect(mockClassList.remove).toHaveBeenCalledWith('focus-active');
+
+ expect(result.current.isRecordTableFocusActive).toBe(false);
+
+ expect(result.current.focusPosition).toEqual(cellPosition);
+ });
+
+ it('should set focus for current position', () => {
+ const { result } = renderHooks();
+
+ act(() => {
+ result.current.setIsFocusActiveForCurrentPosition(true);
+ });
+
+ expect(mockGetElementById).toHaveBeenCalledWith('record-table-cell-1-0');
+
+ expect(mockClassList.add).toHaveBeenCalledWith('focus-active');
+
+ expect(result.current.isRecordTableFocusActive).toBe(true);
+
+ expect(result.current.focusPosition).toEqual({ column: 1, row: 0 });
+ });
+
+ it('should handle case when the cell element is not found', () => {
+ mockGetElementById.mockReturnValue(null);
+
+ const { result } = renderHooks();
+
+ const cellPosition: TableCellPosition = { column: 1, row: 0 };
+
+ act(() => {
+ result.current.setIsFocusActive(true, cellPosition);
+ });
+
+ expect(mockGetElementById).toHaveBeenCalledWith('record-table-cell-1-0');
+
+ expect(mockClassList.add).not.toHaveBeenCalled();
+
+ expect(result.current.isRecordTableFocusActive).toBe(true);
+
+ expect(result.current.focusPosition).toEqual(cellPosition);
+ });
+});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellInGroup.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellInGroup.test.tsx
index 20a6a7ef5..c6b6edd18 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellInGroup.test.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellInGroup.test.tsx
@@ -16,10 +16,8 @@ import {
recordTableRowDraggableContextValue,
} from '@/object-record/record-table/record-table-cell/hooks/__mocks__/cell';
import { useCloseRecordTableCellInGroup } from '@/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellInGroup';
-import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
-import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
+import { recordTableCellEditModePositionComponentState } from '@/object-record/record-table/states/recordTableCellEditModePositionComponentState';
import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect';
-import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
@@ -60,7 +58,7 @@ const Wrapper = ({ children }: { children: React.ReactNode }) => (
value={recordTableRowDraggableContextValue}
>
{children}
@@ -77,16 +75,12 @@ describe('useCloseRecordTableCellInGroup', () => {
const { result } = renderHook(
() => {
const currentTableCellInEditModePosition = useRecoilComponentValueV2(
- currentTableCellInEditModePositionComponentState,
- );
- const isTableCellInEditMode = useRecoilComponentFamilyValueV2(
- isTableCellInEditModeComponentFamilyState,
- currentTableCellInEditModePosition,
+ recordTableCellEditModePositionComponentState,
);
return {
...useCloseRecordTableCellInGroup(),
...useDragSelect(),
- isTableCellInEditMode,
+ currentTableCellInEditModePosition,
};
},
{
@@ -99,7 +93,7 @@ describe('useCloseRecordTableCellInGroup', () => {
});
expect(result.current.isDragSelectionStartEnabled()).toBe(true);
- expect(result.current.isTableCellInEditMode).toBe(false);
- expect(setHotkeyScope).toHaveBeenCalledWith('table-soft-focus');
+ expect(result.current.currentTableCellInEditModePosition).toBe(null);
+ expect(setHotkeyScope).toHaveBeenCalledWith('table-focus');
});
});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellNoGroup.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellNoGroup.test.tsx
index 88561640e..9045267ec 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellNoGroup.test.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellNoGroup.test.tsx
@@ -16,10 +16,8 @@ import {
recordTableRowDraggableContextValue,
} from '@/object-record/record-table/record-table-cell/hooks/__mocks__/cell';
import { useCloseRecordTableCellNoGroup } from '@/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellNoGroup';
-import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
-import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
+import { recordTableCellEditModePositionComponentState } from '@/object-record/record-table/states/recordTableCellEditModePositionComponentState';
import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect';
-import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
@@ -60,7 +58,7 @@ const Wrapper = ({ children }: { children: React.ReactNode }) => (
value={recordTableRowDraggableContextValue}
>
{children}
@@ -77,16 +75,13 @@ describe('useCloseRecordTableCellNoGroup', () => {
const { result } = renderHook(
() => {
const currentTableCellInEditModePosition = useRecoilComponentValueV2(
- currentTableCellInEditModePositionComponentState,
- );
- const isTableCellInEditMode = useRecoilComponentFamilyValueV2(
- isTableCellInEditModeComponentFamilyState,
- currentTableCellInEditModePosition,
+ recordTableCellEditModePositionComponentState,
);
+
return {
...useCloseRecordTableCellNoGroup(),
...useDragSelect(),
- isTableCellInEditMode,
+ currentTableCellInEditModePosition,
};
},
{
@@ -99,7 +94,7 @@ describe('useCloseRecordTableCellNoGroup', () => {
});
expect(result.current.isDragSelectionStartEnabled()).toBe(true);
- expect(result.current.isTableCellInEditMode).toBe(false);
- expect(setHotkeyScope).toHaveBeenCalledWith('table-soft-focus');
+ expect(result.current.currentTableCellInEditModePosition).toBe(null);
+ expect(setHotkeyScope).toHaveBeenCalledWith('table-focus');
});
});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellInGroup.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellInGroup.ts
index 9a985d8af..2070def65 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellInGroup.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellInGroup.ts
@@ -1,6 +1,6 @@
import { useRecoilCallback } from 'recoil';
-import { SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/SoftFocusClickOutsideListenerId';
+import { FOCUS_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/FocusClickOutsideListenerId';
import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
@@ -16,7 +16,7 @@ export const useCloseRecordTableCellInGroup = () => {
const { setDragSelectionStartEnabled } = useDragSelect();
const { toggleClickOutsideListener } = useClickOutsideListener(
- SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID,
+ FOCUS_CLICK_OUTSIDE_LISTENER_ID,
);
const closeCurrentTableCellInEditMode =
@@ -27,7 +27,7 @@ export const useCloseRecordTableCellInGroup = () => {
toggleClickOutsideListener(true);
setDragSelectionStartEnabled(true);
closeCurrentTableCellInEditMode();
- setHotkeyScope(TableHotkeyScope.TableSoftFocus);
+ setHotkeyScope(TableHotkeyScope.TableFocus);
},
[
closeCurrentTableCellInEditMode,
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellNoGroup.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellNoGroup.ts
index ba3dc25dc..97b69d490 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellNoGroup.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellNoGroup.ts
@@ -1,4 +1,4 @@
-import { SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/SoftFocusClickOutsideListenerId';
+import { FOCUS_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/FocusClickOutsideListenerId';
import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
@@ -16,7 +16,7 @@ export const useCloseRecordTableCellNoGroup = () => {
const { setDragSelectionStartEnabled } = useDragSelect();
const { toggleClickOutsideListener } = useClickOutsideListener(
- SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID,
+ FOCUS_CLICK_OUTSIDE_LISTENER_ID,
);
const closeCurrentTableCellInEditMode =
@@ -26,7 +26,7 @@ export const useCloseRecordTableCellNoGroup = () => {
toggleClickOutsideListener(true);
setDragSelectionStartEnabled(true);
closeCurrentTableCellInEditMode();
- setHotkeyScope(TableHotkeyScope.TableSoftFocus);
+ setHotkeyScope(TableHotkeyScope.TableFocus);
}, [
closeCurrentTableCellInEditMode,
setDragSelectionStartEnabled,
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useCurrentCellPosition.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useCurrentCellPosition.ts
deleted file mode 100644
index 383a81de4..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useCurrentCellPosition.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { useContext } from 'react';
-
-import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
-
-export const useCurrentTableCellPosition = () => {
- const { cellPosition } = useContext(RecordTableCellContext);
-
- return cellPosition;
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useCurrentTableCellEditMode.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useCurrentTableCellEditMode.ts
deleted file mode 100644
index fb4f77498..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useCurrentTableCellEditMode.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { useCallback } from 'react';
-
-import { useMoveEditModeToTableCellPosition } from '../../hooks/internal/useMoveEditModeToCellPosition';
-
-import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
-import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
-import { useCurrentTableCellPosition } from './useCurrentCellPosition';
-
-export const useCurrentTableCellEditMode = () => {
- const moveEditModeToTableCellPosition = useMoveEditModeToTableCellPosition();
-
- const currentTableCellPosition = useCurrentTableCellPosition();
-
- const isCurrentTableCellInEditMode = useRecoilComponentFamilyValueV2(
- isTableCellInEditModeComponentFamilyState,
- currentTableCellPosition,
- );
-
- const setCurrentTableCellInEditMode = useCallback(() => {
- moveEditModeToTableCellPosition(currentTableCellPosition);
- }, [currentTableCellPosition, moveEditModeToTableCellPosition]);
-
- return {
- isCurrentTableCellInEditMode,
- setCurrentTableCellInEditMode,
- };
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useIsSoftFocusOnCurrentTableCell.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useIsSoftFocusOnCurrentTableCell.ts
deleted file mode 100644
index 67605e093..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useIsSoftFocusOnCurrentTableCell.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { isSoftFocusOnTableCellComponentFamilyState } from '@/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState';
-import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
-import { useCurrentTableCellPosition } from './useCurrentCellPosition';
-
-export const useIsSoftFocusOnCurrentTableCell = () => {
- const currentTableCellPosition = useCurrentTableCellPosition();
-
- const isSoftFocusOnTableCell = useRecoilComponentFamilyValueV2(
- isSoftFocusOnTableCellComponentFamilyState,
- currentTableCellPosition,
- );
-
- return isSoftFocusOnTableCell;
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveHoverToCurrentCell.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveHoverToCurrentCell.ts
new file mode 100644
index 000000000..efb848e8d
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveHoverToCurrentCell.ts
@@ -0,0 +1,55 @@
+import { useRecoilCallback } from 'recoil';
+
+import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
+import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
+import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
+
+import { recordTableHoverPositionComponentState } from '@/object-record/record-table/states/recordTableHoverPositionComponentState';
+import { isSomeCellInEditModeComponentSelector } from '@/object-record/record-table/states/selectors/isSomeCellInEditModeComponentSelector';
+import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
+import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
+import { TableHotkeyScope } from '../../types/TableHotkeyScope';
+
+export const useMoveHoverToCurrentCell = (recordTableId: string) => {
+ const setHoverPosition = useSetRecoilComponentStateV2(
+ recordTableHoverPositionComponentState,
+ recordTableId,
+ );
+
+ const isSomeCellInEditModeSelector = useRecoilComponentCallbackStateV2(
+ isSomeCellInEditModeComponentSelector,
+ recordTableId,
+ );
+
+ const moveHoverToCurrentCell = useRecoilCallback(
+ ({ snapshot }) =>
+ (cellPosition: TableCellPosition) => {
+ const isSomeCellInEditMode = getSnapshotValue(
+ snapshot,
+ isSomeCellInEditModeSelector,
+ );
+
+ const currentHotkeyScope = getSnapshotValue(
+ snapshot,
+ currentHotkeyScopeState,
+ );
+
+ if (
+ currentHotkeyScope.scope !== TableHotkeyScope.TableFocus &&
+ currentHotkeyScope.scope !== TableHotkeyScope.CellEditMode &&
+ currentHotkeyScope.scope !== TableHotkeyScope.Table &&
+ currentHotkeyScope.scope !== AppHotkeyScope.CommandMenuOpen
+ ) {
+ return;
+ }
+
+ if (!isSomeCellInEditMode) {
+ setHoverPosition(cellPosition);
+ }
+ },
+ [isSomeCellInEditModeSelector, setHoverPosition],
+ );
+
+ return { moveHoverToCurrentCell };
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover.ts
deleted file mode 100644
index 60c4f1f13..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { useRecoilCallback } from 'recoil';
-
-import { useSetSoftFocus } from '@/object-record/record-table/record-table-cell/hooks/useSetSoftFocus';
-import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
-import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
-import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
-
-import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
-import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
-import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
-import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { TableHotkeyScope } from '../../types/TableHotkeyScope';
-
-export const useMoveSoftFocusToCurrentCellOnHover = (recordTableId: string) => {
- const setSoftFocus = useSetSoftFocus(recordTableId);
-
- const currentTableCellInEditModePositionState =
- useRecoilComponentCallbackStateV2(
- currentTableCellInEditModePositionComponentState,
- recordTableId,
- );
- const isTableCellInEditModeFamilyState = useRecoilComponentCallbackStateV2(
- isTableCellInEditModeComponentFamilyState,
- recordTableId,
- );
-
- const moveSoftFocusToCurrentCell = useRecoilCallback(
- ({ snapshot }) =>
- (cellPosition: TableCellPosition) => {
- const currentTableCellInEditModePosition = getSnapshotValue(
- snapshot,
- currentTableCellInEditModePositionState,
- );
-
- const isSomeCellInEditMode = snapshot
- .getLoadable(
- isTableCellInEditModeFamilyState(
- currentTableCellInEditModePosition,
- ),
- )
- .getValue();
-
- const currentHotkeyScope = snapshot
- .getLoadable(currentHotkeyScopeState)
- .getValue();
-
- if (
- currentHotkeyScope.scope !== TableHotkeyScope.TableSoftFocus &&
- currentHotkeyScope.scope !== TableHotkeyScope.CellEditMode &&
- currentHotkeyScope.scope !== TableHotkeyScope.Table &&
- currentHotkeyScope.scope !== AppHotkeyScope.CommandMenuOpen
- ) {
- return;
- }
-
- if (!isSomeCellInEditMode) {
- setSoftFocus(cellPosition);
- }
- },
- [
- currentTableCellInEditModePositionState,
- isTableCellInEditModeFamilyState,
- setSoftFocus,
- ],
- );
-
- return { moveSoftFocusToCurrentCell };
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts
index c000414fa..f90bf23de 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts
@@ -4,11 +4,12 @@ import { FieldContext } from '@/object-record/record-field/contexts/FieldContext
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { useRecordTableRowContextOrThrow } from '@/object-record/record-table/contexts/RecordTableRowContext';
-import { useCurrentTableCellPosition } from '@/object-record/record-table/record-table-cell/hooks/useCurrentCellPosition';
import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecordTableBodyContextOrThrow } from '@/object-record/record-table/contexts/RecordTableBodyContext';
+import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
+import { useSetRecordTableFocusPosition } from '@/object-record/record-table/hooks/internal/useSetRecordTableFocusPosition';
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
export const DEFAULT_CELL_SCOPE: HotkeyScope = {
@@ -33,7 +34,9 @@ export const useOpenRecordTableCellFromCell = () => {
const { onOpenTableCell } = useRecordTableBodyContextOrThrow();
- const cellPosition = useCurrentTableCellPosition();
+ const { cellPosition } = useContext(RecordTableCellContext);
+
+ const setFocusPosition = useSetRecordTableFocusPosition();
const openTableCell = (
initialValue?: string,
@@ -51,6 +54,8 @@ export const useOpenRecordTableCellFromCell = () => {
isActionButtonClick,
isNavigating,
});
+
+ setFocusPosition(cellPosition);
};
return {
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts
index 651d976fa..b09ca7623 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts
@@ -6,9 +6,8 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'
import { isFieldValueEmpty } from '@/object-record/record-field/utils/isFieldValueEmpty';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
-import { SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/SoftFocusClickOutsideListenerId';
+import { FOCUS_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/FocusClickOutsideListenerId';
import { useLeaveTableFocus } from '@/object-record/record-table/hooks/internal/useLeaveTableFocus';
-import { useMoveEditModeToTableCellPosition } from '@/object-record/record-table/hooks/internal/useMoveEditModeToCellPosition';
import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
@@ -21,14 +20,15 @@ import { useRecordIndexContextOrThrow } from '@/object-record/record-index/conte
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState';
import { RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/RecordTableClickOutsideListenerId';
+import { recordTableCellEditModePositionComponentState } from '@/object-record/record-table/states/recordTableCellEditModePositionComponentState';
import { getDropdownFocusIdForRecordField } from '@/object-record/utils/getDropdownFocusIdForRecordField';
import { getRecordFieldInputId } from '@/object-record/utils/getRecordFieldInputId';
import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious';
import { useClickOustideListenerStates } from '@/ui/utilities/pointer-event/hooks/useClickOustideListenerStates';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { useNavigate } from 'react-router-dom';
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
-
export const DEFAULT_CELL_SCOPE: HotkeyScope = {
scope: TableHotkeyScope.CellEditMode,
};
@@ -50,14 +50,16 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => {
useClickOustideListenerStates(RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID);
const { indexIdentifierUrl } = useRecordIndexContextOrThrow();
- const moveEditModeToTableCellPosition =
- useMoveEditModeToTableCellPosition(tableScopeId);
+ const setCurrentTableCellInEditModePosition = useSetRecoilComponentStateV2(
+ recordTableCellEditModePositionComponentState,
+ tableScopeId,
+ );
const { setDragSelectionStartEnabled } = useDragSelect();
const leaveTableFocus = useLeaveTableFocus(tableScopeId);
const { toggleClickOutsideListener } = useClickOutsideListener(
- SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID,
+ FOCUS_CLICK_OUTSIDE_LISTENER_ID,
);
const initDraftValue = useInitDraftValueV2();
@@ -148,7 +150,7 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => {
recordId,
});
- moveEditModeToTableCellPosition(cellPosition);
+ setCurrentTableCellInEditModePosition(cellPosition);
initDraftValue({
value: initialValue,
@@ -175,7 +177,7 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => {
getClickOutsideListenerIsActivatedState,
setDragSelectionStartEnabled,
openFieldInput,
- moveEditModeToTableCellPosition,
+ setCurrentTableCellInEditModePosition,
initDraftValue,
toggleClickOutsideListener,
setActiveDropdownFocusIdAndMemorizePrevious,
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode.ts
deleted file mode 100644
index d768c0617..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { useCallback } from 'react';
-
-import { useMoveEditModeToTableCellPosition } from '../../hooks/internal/useMoveEditModeToCellPosition';
-
-export const useSelectedTableCellEditMode = ({
- scopeId,
-}: {
- scopeId: string;
-}) => {
- const moveEditModeToTableCellPosition =
- useMoveEditModeToTableCellPosition(scopeId);
-
- const setSelectedTableCellEditMode = useCallback(
- (row: number, column: number) => {
- moveEditModeToTableCellPosition({ column, row });
- },
- [moveEditModeToTableCellPosition],
- );
-
- return { setSelectedTableCellEditMode };
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetIsRecordTableFocusActive.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetIsRecordTableFocusActive.ts
new file mode 100644
index 000000000..6461e3f1d
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetIsRecordTableFocusActive.ts
@@ -0,0 +1,51 @@
+import { isRecordTableFocusActiveComponentState } from '@/object-record/record-table/states/isRecordTableFocusActiveComponentState';
+import { recordTableFocusPositionComponentState } from '@/object-record/record-table/states/recordTableFocusPositionComponentState';
+import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
+import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
+import { useRecoilCallback } from 'recoil';
+
+export const useSetIsRecordTableFocusActive = (recordTableId?: string) => {
+ const isRecordTableFocusActiveState = useRecoilComponentCallbackStateV2(
+ isRecordTableFocusActiveComponentState,
+ recordTableId,
+ );
+
+ const focusPositionState = useRecoilComponentCallbackStateV2(
+ recordTableFocusPositionComponentState,
+ recordTableId,
+ );
+
+ const setIsFocusActive = useRecoilCallback(
+ ({ set }) =>
+ (isRecordTableFocusActive: boolean, cellPosition: TableCellPosition) => {
+ const cellId = `record-table-cell-${cellPosition.column}-${cellPosition.row}`;
+
+ const cellElement = document.getElementById(cellId);
+
+ if (isRecordTableFocusActive) {
+ cellElement?.classList.add('focus-active');
+ }
+
+ if (!isRecordTableFocusActive) {
+ cellElement?.classList.remove('focus-active');
+ }
+
+ set(isRecordTableFocusActiveState, isRecordTableFocusActive);
+ },
+ [isRecordTableFocusActiveState],
+ );
+
+ const setIsFocusActiveForCurrentPosition = useRecoilCallback(
+ ({ snapshot }) =>
+ (isRecordTableFocusActive: boolean) => {
+ const currentPosition = snapshot
+ .getLoadable(focusPositionState)
+ .getValue();
+
+ setIsFocusActive(isRecordTableFocusActive, currentPosition);
+ },
+ [setIsFocusActive, focusPositionState],
+ );
+
+ return { setIsFocusActive, setIsFocusActiveForCurrentPosition };
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocus.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocus.ts
deleted file mode 100644
index 62a9dd076..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocus.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { useRecoilCallback } from 'recoil';
-
-import { useSetSoftFocusPosition } from '@/object-record/record-table/hooks/internal/useSetSoftFocusPosition';
-import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
-import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
-
-import { isSoftFocusActiveComponentState } from '@/object-record/record-table/states/isSoftFocusActiveComponentState';
-import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
-import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
-import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { TableHotkeyScope } from '../../types/TableHotkeyScope';
-
-export const useSetSoftFocus = (recordTableId?: string) => {
- const setSoftFocusPosition = useSetSoftFocusPosition(recordTableId);
-
- const isSoftFocusActiveState = useRecoilComponentCallbackStateV2(
- isSoftFocusActiveComponentState,
- recordTableId,
- );
-
- const setHotkeyScope = useSetHotkeyScope();
-
- return useRecoilCallback(
- ({ snapshot, set }) =>
- (newPosition: TableCellPosition) => {
- setSoftFocusPosition(newPosition);
-
- set(isSoftFocusActiveState, true);
-
- if (
- snapshot.getLoadable(currentHotkeyScopeState).getValue().scope !==
- AppHotkeyScope.CommandMenuOpen
- ) {
- setHotkeyScope(TableHotkeyScope.TableSoftFocus);
- }
- },
- [setSoftFocusPosition, isSoftFocusActiveState, setHotkeyScope],
- );
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocusOnCurrentTableCell.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocusOnCurrentTableCell.ts
deleted file mode 100644
index 3bee41b33..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useSetSoftFocusOnCurrentTableCell.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { useSetSoftFocus } from '@/object-record/record-table/record-table-cell/hooks/useSetSoftFocus';
-
-import { useCurrentTableCellPosition } from './useCurrentCellPosition';
-
-export const useSetSoftFocusOnCurrentTableCell = () => {
- const setSoftFocus = useSetSoftFocus();
-
- const currentTableCellPosition = useCurrentTableCellPosition();
-
- return () => {
- setSoftFocus(currentTableCellPosition);
- };
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/tableCellWidthsComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableFocusActiveComponentState.ts
similarity index 50%
rename from packages/twenty-front/src/modules/object-record/record-table/states/tableCellWidthsComponentState.ts
rename to packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableFocusActiveComponentState.ts
index 54ab3dacf..36466471d 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/states/tableCellWidthsComponentState.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableFocusActiveComponentState.ts
@@ -1,8 +1,9 @@
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
-export const tableCellWidthsComponentState = createComponentStateV2({
- key: 'tableCellWidthsComponentState',
- defaultValue: [],
- componentInstanceContext: RecordTableComponentInstanceContext,
-});
+export const isRecordTableFocusActiveComponentState =
+ createComponentStateV2({
+ key: 'isRecordTableFocusActiveComponentState',
+ defaultValue: false,
+ componentInstanceContext: RecordTableComponentInstanceContext,
+ });
diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusActiveComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusActiveComponentState.ts
deleted file mode 100644
index a077573b2..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusActiveComponentState.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
-import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
-
-export const isSoftFocusActiveComponentState = createComponentStateV2({
- key: 'isSoftFocusActiveComponentState',
- defaultValue: false,
- componentInstanceContext: RecordTableComponentInstanceContext,
-});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState.ts
deleted file mode 100644
index 57ee967a2..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
-import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
-import { TableCellPosition } from '../types/TableCellPosition';
-
-export const isSoftFocusOnTableCellComponentFamilyState =
- createComponentFamilyStateV2({
- key: 'isSoftFocusOnTableCellComponentFamilyState',
- defaultValue: false,
- componentInstanceContext: RecordTableComponentInstanceContext,
- });
diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusUsingMouseState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusUsingMouseState.ts
deleted file mode 100644
index d1ad40261..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/states/isSoftFocusUsingMouseState.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { createState } from 'twenty-ui/utilities';
-export const isSoftFocusUsingMouseState = createState({
- key: 'isSoftFocusUsingMouseState',
- defaultValue: false,
-});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/isTableCellInEditModeComponentFamilyState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/isTableCellInEditModeComponentFamilyState.ts
deleted file mode 100644
index ec71ea571..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/states/isTableCellInEditModeComponentFamilyState.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
-import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
-import { TableCellPosition } from '../types/TableCellPosition';
-
-export const isTableCellInEditModeComponentFamilyState =
- createComponentFamilyStateV2({
- key: 'isTableCellInEditModeComponentFamilyState',
- defaultValue: false,
- componentInstanceContext: RecordTableComponentInstanceContext,
- });
diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/currentTableCellInEditModePositionComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/recordTableCellEditModePositionComponentState.ts
similarity index 62%
rename from packages/twenty-front/src/modules/object-record/record-table/states/currentTableCellInEditModePositionComponentState.ts
rename to packages/twenty-front/src/modules/object-record/record-table/states/recordTableCellEditModePositionComponentState.ts
index 77adc75b2..7cccbf1f7 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/states/currentTableCellInEditModePositionComponentState.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/states/recordTableCellEditModePositionComponentState.ts
@@ -2,12 +2,9 @@ import { RecordTableComponentInstanceContext } from '@/object-record/record-tabl
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
import { TableCellPosition } from '../types/TableCellPosition';
-export const currentTableCellInEditModePositionComponentState =
- createComponentStateV2({
- key: 'currentTableCellInEditModePositionComponentState',
- defaultValue: {
- row: 0,
- column: 1,
- },
+export const recordTableCellEditModePositionComponentState =
+ createComponentStateV2({
+ key: 'recordTableCellEditModePositionComponentState',
+ defaultValue: null,
componentInstanceContext: RecordTableComponentInstanceContext,
});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/softFocusPositionComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/recordTableFocusPositionComponentState.ts
similarity index 82%
rename from packages/twenty-front/src/modules/object-record/record-table/states/softFocusPositionComponentState.ts
rename to packages/twenty-front/src/modules/object-record/record-table/states/recordTableFocusPositionComponentState.ts
index c59f2cd1f..c479676fe 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/states/softFocusPositionComponentState.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/states/recordTableFocusPositionComponentState.ts
@@ -2,9 +2,9 @@ import { RecordTableComponentInstanceContext } from '@/object-record/record-tabl
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
import { TableCellPosition } from '../types/TableCellPosition';
-export const softFocusPositionComponentState =
+export const recordTableFocusPositionComponentState =
createComponentStateV2({
- key: 'softFocusPositionComponentState',
+ key: 'recordTableFocusPositionComponentState',
defaultValue: {
row: 0,
column: 1,
diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/recordTableHoverPositionComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/recordTableHoverPositionComponentState.ts
new file mode 100644
index 000000000..f4ab8da5c
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/states/recordTableHoverPositionComponentState.ts
@@ -0,0 +1,10 @@
+import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
+import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
+import { TableCellPosition } from '../types/TableCellPosition';
+
+export const recordTableHoverPositionComponentState =
+ createComponentStateV2({
+ key: 'recordTableHoverPositionComponentState',
+ defaultValue: null,
+ componentInstanceContext: RecordTableComponentInstanceContext,
+ });
diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/selectors/isSomeCellInEditModeComponentSelector.ts b/packages/twenty-front/src/modules/object-record/record-table/states/selectors/isSomeCellInEditModeComponentSelector.ts
new file mode 100644
index 000000000..17ef7c8cb
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/states/selectors/isSomeCellInEditModeComponentSelector.ts
@@ -0,0 +1,20 @@
+import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
+import { recordTableCellEditModePositionComponentState } from '@/object-record/record-table/states/recordTableCellEditModePositionComponentState';
+import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
+import { isDefined } from 'twenty-shared/utils';
+
+export const isSomeCellInEditModeComponentSelector = createComponentSelectorV2({
+ key: 'isSomeCellInEditModeComponentSelector',
+ componentInstanceContext: RecordTableComponentInstanceContext,
+ get:
+ ({ instanceId }) =>
+ ({ get }) => {
+ const currentTableCellInEditModePosition = get(
+ recordTableCellEditModePositionComponentState.atomFamily({
+ instanceId,
+ }),
+ );
+
+ return isDefined(currentTableCellInEditModePosition);
+ },
+});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/tableRecordGroupIdsComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/tableRecordGroupIdsComponentState.ts
deleted file mode 100644
index fd6f666a9..000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/states/tableRecordGroupIdsComponentState.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
-import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
-import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
-
-export const tableRecordGroupIdsComponentState = createComponentStateV2<
- RecordGroupDefinition['id'][]
->({
- key: 'tableRecordGroupIdsComponentState',
- defaultValue: [],
- componentInstanceContext: RecordTableComponentInstanceContext,
-});
diff --git a/packages/twenty-front/src/modules/object-record/record-table/types/TableHotkeyScope.ts b/packages/twenty-front/src/modules/object-record/record-table/types/TableHotkeyScope.ts
index 37c831819..b1bae4957 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/types/TableHotkeyScope.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/types/TableHotkeyScope.ts
@@ -2,6 +2,6 @@ export enum TableHotkeyScope {
CellDoubleTextInput = 'cell-double-text-input',
CellEditMode = 'cell-edit-mode',
CellDateEditMode = 'cell-date-edit-mode',
- TableSoftFocus = 'table-soft-focus',
+ TableFocus = 'table-focus',
Table = 'table',
}
diff --git a/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx b/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx
index 93315ff85..0fa6d1ff8 100644
--- a/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx
+++ b/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx
@@ -85,7 +85,7 @@ const InternalTableContextProviders = ({
onOpenTableCell: () => {},
onActionMenuDropdownOpened: () => {},
onMoveFocus: () => {},
- onMoveSoftFocusToCurrentCell: () => {},
+ onMoveHoverToCurrentCell: () => {},
}}
>
{children}