From 1b5c081e1e1b7fb7a5af4eb3151846928d55c265 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 15 Jun 2026 04:54:23 +0100 Subject: [PATCH] fix(base): tab from long-text editor moves to next cell instead of leaving the table --- .../base/components/cells/cell-long-text.tsx | 8 +++++- .../src/ee/base/components/grid/grid-cell.tsx | 27 +++++++++++++++++++ .../property-type.descriptor.ts | 1 + 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/apps/client/src/ee/base/components/cells/cell-long-text.tsx b/apps/client/src/ee/base/components/cells/cell-long-text.tsx index 756ec09f7..2c3900562 100644 --- a/apps/client/src/ee/base/components/cells/cell-long-text.tsx +++ b/apps/client/src/ee/base/components/cells/cell-long-text.tsx @@ -13,6 +13,7 @@ type CellLongTextProps = { onCommit: (value: unknown) => void; onValueChange: (value: unknown) => void; onCancel: () => void; + onTabNavigate?: (shiftKey: boolean) => void; }; const toText = (value: unknown) => (typeof value === "string" ? value : ""); @@ -27,6 +28,7 @@ export function CellLongText({ onCommit, onValueChange, onCancel, + onTabNavigate, }: CellLongTextProps) { const [draft, setDraft] = useState(() => toText(value)); const cancelledRef = useRef(false); @@ -127,7 +129,11 @@ export function CellLongText({ }} onKeyDown={(e) => { e.stopPropagation(); - if (e.key === "Escape") { + if (e.key === "Tab") { + e.preventDefault(); + commit(); + onTabNavigate?.(e.shiftKey); + } else if (e.key === "Escape") { e.preventDefault(); cancel(); } else if ((e.metaKey || e.ctrlKey) && e.key === "Enter") { diff --git a/apps/client/src/ee/base/components/grid/grid-cell.tsx b/apps/client/src/ee/base/components/grid/grid-cell.tsx index 90243a0a6..07a3d754d 100644 --- a/apps/client/src/ee/base/components/grid/grid-cell.tsx +++ b/apps/client/src/ee/base/components/grid/grid-cell.tsx @@ -18,6 +18,7 @@ import { getDescriptor, } from "@/ee/base/property-types/property-type.registry"; import { cellValuesEqual } from "@/ee/base/components/cells/cell-value-equal"; +import { computeNextCell } from "@/ee/base/utils/grid-cell-nav"; import { useBaseEditable } from "@/ee/base/context/base-editable"; import { useRowExpand } from "@/ee/base/context/row-expand"; import { RowNumberCell } from "./row-number-cell"; @@ -132,6 +133,31 @@ export const GridCell = memo(function GridCell({ setEditingCell(null); }, [setEditingCell]); + const handleTabNavigate = useCallback( + (shiftKey: boolean) => { + if (!property) return; + const tableInstance = cell.getContext().table; + const colIds = tableInstance + .getVisibleLeafColumns() + .filter((c) => c.id !== "__row_number") + .map((c) => c.id); + const rowIds = tableInstance.getRowModel().rows.map((r) => r.id); + const next = computeNextCell( + rowIds, + colIds, + { rowId, propertyId: property.id }, + 0, + shiftKey ? -1 : 1, + true, + ); + if (next) { + setEditingCell(next); + setFocusedCell(next); + } + }, + [cell, rowId, property, setEditingCell, setFocusedCell], + ); + if (isRowNumber) { return ( {property.isPrimary && onExpandRow && !isEditing && ( diff --git a/apps/client/src/ee/base/property-types/property-type.descriptor.ts b/apps/client/src/ee/base/property-types/property-type.descriptor.ts index 28e9fc275..8b33ad110 100644 --- a/apps/client/src/ee/base/property-types/property-type.descriptor.ts +++ b/apps/client/src/ee/base/property-types/property-type.descriptor.ts @@ -17,6 +17,7 @@ export type CellComponentProps = { onCommit: (value: unknown) => void; onValueChange: (value: unknown) => void; onCancel: () => void; + onTabNavigate?: (shiftKey: boolean) => void; }; export type FilterInputKind =