Skip to content

feat(table): column drag-and-drop reorder#3738

Merged
waleedlatif1 merged 5 commits intostagingfrom
waleedlatif1/table-column-drag-reorder
Mar 24, 2026
Merged

feat(table): column drag-and-drop reorder#3738
waleedlatif1 merged 5 commits intostagingfrom
waleedlatif1/table-column-drag-reorder

Conversation

@waleedlatif1
Copy link
Collaborator

Summary

  • Add drag-and-drop column reordering to tables
  • Column order persisted to table metadata
  • Visual drop indicator (left/right) during drag
  • Handles column rename, insert, and delete with order sync
  • Resize handle conflict prevention

Type of Change

  • New feature

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Mar 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Mar 24, 2026 5:15pm

Request Review

@cursor
Copy link

cursor bot commented Mar 24, 2026

PR Summary

Medium Risk
Adds a new persisted UI metadata field (columnOrder) and updates table interactions (drag, rename, insert, delete) to mutate it, which could affect how columns render and how selection/index-based logic behaves. Risk is mostly UI/state consistency; no auth or data-model writes beyond metadata merging.

Overview
Adds drag-and-drop column reordering in the table UI and persists the chosen order via a new TableMetadata.columnOrder field.

Updates table rendering and selection logic to use displayColumns (schema columns ordered by columnOrder with a fallback for missing/new columns), and syncs metadata updates on drag end as well as on column rename/insert/delete. The table metadata API now validates and accepts columnOrder alongside columnWidths.

Written by Cursor Bugbot for commit 12ced58. Configure here.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 24, 2026

Greptile Summary

This PR adds native HTML5 drag-and-drop column reordering to the table component. A displayColumns memo computes the visual order from a persisted columnOrder array, and the drag lifecycle (dragstartdragoverdrop/dragend) updates that array both locally and via the existing metadata API. The feature integrates cleanly with the existing column rename, insert-left/right, and delete flows, keeping columnOrder in sync with each operation.

Key changes:

  • displayColumns memo correctly falls back to schema order when no order is set, and appends unknown columns at the tail
  • Resize-handle conflict is prevented with draggable={false} + e.stopPropagation() on the resize thumb
  • deleteColumnMutation now updates columnOrder in onSuccess (fixing a prior optimistic-update bug)
  • insertColumnInOrder correctly no-ops when columnOrderRef.current is null (first-drag captures order)
  • One outstanding issue: in the columnRename handler, updateMetadataRef.current is only called when columnOrderRef.current is non-null, so a column that has a custom width but was renamed before any drag has occurred will lose its width on the next page load

Confidence Score: 4/5

  • Safe to merge after the rename-path width persistence fix; all prior review concerns have been resolved.
  • The drag-and-drop logic is well-structured, prior issues (double invocation, optimistic delete rollback) have been addressed, and the type/API changes are minimal. One concrete P1 remains: renaming a column with a custom width before any drag has occurred skips updateMetadataRef.current, causing the width to be lost on the next page load. That fix is a one-liner in the rename handler.
  • apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table/table.tsx — specifically the columnRename.onSave handler around line 369

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table/table.tsx Core drag-and-drop implementation: new drag state, displayColumns memo, resize-handle conflict prevention, and sync of column order across rename/insert/delete. One bug: updateMetadataRef.current is not called during rename when columnOrderRef.current is null, so a custom column width is not persisted when the user renames before ever dragging.
apps/sim/app/api/table/[tableId]/metadata/route.ts Adds columnOrder: z.array(z.string()).optional() to the Zod schema — a minimal, safe change that correctly exposes the new field through the existing PUT handler without touching auth or access-control logic.
apps/sim/lib/table/types.ts Adds columnOrder?: string[] to TableMetadata — a non-breaking additive change consistent with the existing optional columnWidths field.

Sequence Diagram

sequenceDiagram
    participant User
    participant TH as ColumnHeaderMenu (th)
    participant Table as Table (parent)
    participant API as /api/table/[id]/metadata

    User->>TH: dragstart
    TH->>Table: onDragStart(columnName)
    Table->>Table: setDragColumnName(columnName)

    User->>TH: dragover (hover target column)
    TH->>TH: compute side (left/right) from clientX
    TH->>Table: onDragOver(targetName, side)
    Table->>Table: setDropTargetColumnName / setDropSide
    TH-->>User: show drop indicator (2px line)

    User->>TH: drop (release)
    TH->>TH: handleDrop (e.preventDefault only)

    User->>TH: dragend (fires on source)
    TH->>Table: onDragEnd()
    Table->>Table: compute newOrder from columnOrderRef / displayColumns
    Table->>Table: setColumnOrder(newOrder)
    Table->>API: PUT metadata {columnWidths, columnOrder}
    API-->>Table: { success: true }
    Table->>Table: setDragColumnName(null) / setDropTargetColumnName(null)
Loading

Reviews (4): Last reviewed commit: "fix(table): prevent stale refs during co..." | Re-trigger Greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Fix two bugs in column drag-and-drop:
1. Stale columnWidths ref during rename - compute updated widths inline
   before passing to updateMetadata
2. Escape-cancelled drag still reorders - update dropTargetColumnNameRef
   directly in handleColumnDragLeave to prevent handleColumnDragEnd from
   reading stale ref value

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

When the anchor column isn't in columnOrder, add it first then insert
the new column relative to it, so 'right' insertions appear after the
anchor as expected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1 waleedlatif1 merged commit b09a073 into staging Mar 24, 2026
6 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/table-column-drag-reorder branch March 24, 2026 17:15
Sg312 pushed a commit that referenced this pull request Mar 24, 2026
* feat(table): column drag-and-drop reorder

* fix(table): remove duplicate onDragEnd call from handleDrop

* fix(table): persist columnOrder on rename/delete and defer delete to onSuccess

* fix(table): prevent stale refs during column drag operations

Fix two bugs in column drag-and-drop:
1. Stale columnWidths ref during rename - compute updated widths inline
   before passing to updateMetadata
2. Escape-cancelled drag still reorders - update dropTargetColumnNameRef
   directly in handleColumnDragLeave to prevent handleColumnDragEnd from
   reading stale ref value

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(table): insert column at correct side when anchor is unordered

When the anchor column isn't in columnOrder, add it first then insert
the new column relative to it, so 'right' insertions appear after the
anchor as expected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant