feat(tables): column selection, keyboard shortcuts, drag reorder, and undo improvements#4222
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Column operations are expanded and integrated with undo/redo. Column drag-reorder is improved (body-level drop targeting, clearer indicators, Escape-to-cancel) and now records a Data/UX correctness fixes. Reviewed by Cursor Bugbot for commit b82a062. Configure here. |
…heets-aligned operations Click column headers to select entire columns, shift-click to extend to a column range. Delete, cut, and copy operations work on column selections with full undo/redo support. Adds Home, End, Ctrl+Home, Ctrl+End, PageUp, PageDown, Ctrl+Space, and all Shift variants. Changes Ctrl+A to select all cells instead of checkbox rows. Column header dropdown menu now opens on right-click instead of left-click. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split column header into label area (click to select, draggable for reorder) and chevron button (click to open dropdown menu). Remove the grip handle — dragging the header itself now reorders columns. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the thin 2px line drop indicator with a full-column highlight that spans the entire table height, matching Google Sheets behavior. The insertion line is still shown at the drop edge for precision. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Suppress drop indicator when drag would result in no position change (dragging onto self or adjacent no-op positions). Dim the source column body cells during drag with a background overlay. Skip the API call when the computed order is identical to the current order. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cape cancel Column drag-and-drop now supports dropping anywhere in a column (not just headers), pressing Escape to cancel a drag, and full undo/redo integration for column reordering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…a loss When Mothership called updateRow directly (bypassing the PATCH API route), it passed only the changed fields — which were written as the entire row, wiping all other columns. Move the merge logic into updateRow itself so all callers get correct partial-update semantics, and remove the now-redundant pre-merge from both PATCH routes.
Covers the bug where partial updates wiped unmentioned columns — verifies that fields not in the update payload are preserved, nulling a field works, full-row updates are idempotent, and missing rows throw correctly.
…comprehensive row ID patching - Delete column now captures column definition, cell data, order, and width for full undo/redo - Column rename undo/redo now properly syncs columnWidths and columnOrder metadata - patchRedoRowId/patchUndoRowId extended to handle all action types containing row IDs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only show the insertion line at the drop position, matching Google Sheets behavior. Remove dragSourceBounds memo and isDragging prop. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-click, fix escape during drag - Right-clicking within an existing selection now preserves it instead of resetting to a single cell, so context menu operations apply to the full range - Double-clicking a column border auto-resizes the column to fit its content - Escape during column drag now immediately clears refs before state update, preventing the dragend handler from executing the reorder Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ccessibility Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reduce header padding from +48px to +36px (icon + cell padding) and cell padding from +20px to +17px (cell padding + border) for a snug fit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create a minimal custom drag image showing only the column name instead of the browser's default ghost that includes adjacent columns/checkboxes - Clear any existing cell/column selection when starting a column drag to prevent stale highlights from persisting during reorder Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shift+Space now selects the entire row (all columns) instead of toggling a checkbox, matching Google Sheets behavior. Ctrl+D copies the top cell's value down through the selected range with full undo/redo support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The server validates type compatibility and returns a clear error message (e.g. "3 row(s) have incompatible values"), but the client was silently swallowing it. Now surfaces the error via toast notification. Also moved the undo push to onSuccess so a failed type change doesn't pollute the undo stack. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…elete-column undo timing - Scroll-into-view now tracks selectionFocus (not just anchor), so Shift+Arrow extending selection off-screen properly auto-scrolls - Shift+Home/End now uses the current focus as origin (matching Shift+Arrow behavior) instead of always using anchor - Delete column undo entry is now pushed in onSuccess, preventing a corrupted undo stack if the server rejects the deletion - Dialog copy updated from "cannot be undone" to "You can undo this action" since undo/redo is supported Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
f97bc0f to
d05bb81
Compare
Greptile SummaryThis PR adds column selection (click/Shift+click header, Ctrl+Space), column drag reorder with undo/redo, a full suite of keyboard shortcuts (Home/End/PageUp/PageDown/Ctrl+D fill-down/Shift+Space row-select), auto-resize on double-click, and fixes Confidence Score: 5/5Safe to merge; all prior P0/P1 findings are resolved and no new blocking issues were found. All six issues flagged in the previous review round have been addressed in follow-up commits (column-width wipe, DOM span leak, columnRequired capture, stale position on multi-delete, cell-data restoration error handling, duplicate undo on drag). The remaining findings are P2: a stale closure in a cleanup effect, a cosmetic drag-ghost edge case, and a harmless redundant state reset on the Escape-cancel path. None affect correctness of the primary table operations. apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-file-attachments.ts — cleanup effect stale closure. Important Files Changed
Sequence DiagramsequenceDiagram
participant U as User
participant CH as ColumnHeaderMenu
participant T as Table (handleColumnDragEnd)
participant US as useTableUndo
participant API as Metadata API
U->>CH: dragstart on grip handle
CH->>CH: didDragRef = true
CH->>T: onDragStart(columnName)
T->>T: setDragColumnName, clear selection
U->>CH: dragover target column
CH->>T: onDragOver(targetCol, side)
T->>T: setDropTargetColumnName, setDropSide
U->>CH: drop / dragend
CH->>CH: didDragRef = false
CH->>T: onDragEnd()
T->>T: dragColumnNameRef = null (early reset)
T->>T: compute newOrder from previousOrder
T->>US: pushUndo(reorder-columns)
T->>T: setColumnOrder(newOrder)
T->>API: updateMetadata(columnOrder, columnWidths)
T->>T: clear drag state
Note over U,T: Escape path
U->>T: keydown Escape
T->>T: dragColumnNameRef = null, clear drag state
Note right of T: browser fires dragend
CH->>T: onDragEnd() → dragged is null → early return
Note over US,API: Undo reorder
U->>T: Ctrl+Z
T->>US: undo()
US->>US: popUndo → reorder-columns action
US->>T: onColumnOrderChange(previousOrder)
US->>API: updateMetadata(previousOrder)
Reviews (12): Last reviewed commit: "fix(tables): reset didDragRef in handleD..." | Re-trigger Greptile |
…or auto-resize - Delete-column undo now reads current column widths via getColumnWidths callback and merges the restored column's width into the full map, preventing other columns' widths from being wiped - Auto-resize measurement span is now wrapped in try/finally to ensure DOM cleanup if an exception occurs during measurement Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@greptile |
|
@cursor review |
|
@greptile |
|
@cursor review |
deleteTableMutation is not referentially stable — only .mutateAsync() is. Including the mutation object causes unnecessary callback recreation on every mutation state change. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@greptile |
|
@cursor review |
…ata logic Increase header text measurement padding from 36px to 57px to account for the chevron dropdown button (pl-0.5 + 9px icon + pr-2.5) that always occupies layout space. Prevents header text truncation on auto-resize. Deduplicate column rename metadata logic by having columnRename.onSave call handleColumnRename instead of reimplementing the same width/order transfer and metadata persist. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@greptile |
|
@cursor review |
Add onError handler to the batchUpdateRowsMutation inside delete-column undo so failures are logged instead of silently swallowed. The column schema restores first, and the cell data restoration is a separate async call that the outer try/catch cannot intercept. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@greptile |
|
@cursor review |
- Add missing bounds check in handleCopy (c >= cols.length) matching handleCut for defensive consistency - Clear lastCheckboxRowRef in Ctrl+Space and Shift+Space to prevent stale shift-click checkbox range after keyboard selection - Fix stale snapshot race in patchRedoRowId/patchUndoRowId by reading state inside the set() updater instead of via get() outside it - Add metadata cleanup to create-column undo so column width is removed from both local state and server, symmetric with delete-column redo - Remove stale width key from columnWidths on column delete instead of persisting orphaned entries - Normalize undefined vs null in handleInlineSave change detection to prevent unnecessary mutations when oldValue is undefined - Use ghost.parentNode?.removeChild instead of document.body.removeChild in drag ghost cleanup to prevent throw on component unmount Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b82a062. Configure here.

Summary
updateRownow merges partial updates to prevent column data loss from Mothership callsaria-hiddenvalues andaria-labelon column header controlsTest plan