From cc951ae883059ce9d3fcf26d25be0b95b103c43c Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 15 Jun 2026 03:59:03 +0100 Subject: [PATCH] feat(base): keyboard-navigate the row-number column for selection --- .../base/components/grid/grid-container.tsx | 14 +++++++- .../base/components/grid/grid-header-cell.tsx | 15 +++++--- .../base/components/grid/row-number-cell.tsx | 36 +++++++++++++++++-- .../grid/row-number-header-cell.tsx | 1 + .../ee/base/hooks/use-grid-keyboard-nav.ts | 30 ++++++++++++---- .../client/src/ee/base/styles/grid.module.css | 13 +++++++ 6 files changed, 95 insertions(+), 14 deletions(-) diff --git a/apps/client/src/ee/base/components/grid/grid-container.tsx b/apps/client/src/ee/base/components/grid/grid-container.tsx index 336d0e413..e12030c04 100644 --- a/apps/client/src/ee/base/components/grid/grid-container.tsx +++ b/apps/client/src/ee/base/components/grid/grid-container.tsx @@ -125,7 +125,7 @@ export function GridContainer({ const editingCellRef = useRef(editingCell); editingCellRef.current = editingCell; - const { selectionCount, clear: clearSelection } = useRowSelection(pageId); + const { selectionCount, clear: clearSelection, toggle: toggleRow } = useRowSelection(pageId); const { deleteSelected } = useDeleteSelectedRows(pageId); const { t } = useTranslation(); @@ -323,6 +323,17 @@ export function GridContainer({ [editable, properties, setPendingTypeInsert, setEditingCell, openEditor], ); + const toggleRowSelection = useCallback( + (rowId: string) => { + toggleRow(rowId, { + shiftKey: false, + rowIndex: rowIdsRef.current.indexOf(rowId), + orderedRowIds: rowIdsRef.current, + }); + }, + [toggleRow], + ); + const prevEditingRef = useRef(editingCell); useEffect(() => { const prev = prevEditingRef.current; @@ -373,6 +384,7 @@ export function GridContainer({ selectionCount, clearSelection, deleteSelected, + toggleRowSelection, }); const activeCell = editingCell ?? focusedCell; diff --git a/apps/client/src/ee/base/components/grid/grid-header-cell.tsx b/apps/client/src/ee/base/components/grid/grid-header-cell.tsx index 77773e97c..2bd5b84c4 100644 --- a/apps/client/src/ee/base/components/grid/grid-header-cell.tsx +++ b/apps/client/src/ee/base/components/grid/grid-header-cell.tsx @@ -57,10 +57,12 @@ export const GridHeaderCell = memo(function GridHeaderCell({ const isRowNumber = header.column.id === "__row_number"; const isPinned = header.column.getIsPinned(); const pinOffset = isPinned ? header.column.getStart("left") : undefined; - const { selectionCount } = useRowSelection(pageId); + const { selectionCount, toggleAll } = useRowSelection(pageId); const hasSelection = selectionCount > 0; const editable = useBaseEditable(); const isHeaderInteractive = editable && !!property && !isRowNumber; + const isRowNumberHeaderInteractive = + isRowNumber && editable && loadedRowIds.length > 0; const [activePropertyMenu, setActivePropertyMenu] = useAtom(activePropertyMenuAtomFamily(pageId)) as unknown as [string | null, (val: string | null) => void]; const menuOpened = activePropertyMenu === header.column.id; @@ -209,9 +211,10 @@ export const GridHeaderCell = memo(function GridHeaderCell({ return (