Skip to content

feat(datagrid): reorder filter rows by drag or the row menu - #2001

Merged
datlechin merged 1 commit into
mainfrom
feat/filter-row-reorder
Jul 30, 2026
Merged

feat(datagrid): reorder filter rows by drag or the row menu#2001
datlechin merged 1 commit into
mainfrom
feat/filter-row-reorder

Conversation

@datlechin

Copy link
Copy Markdown
Member

Filter rows could only be ordered by the order they were created. Moving a condition meant deleting and recreating it, which risks changing an operator or value by accident.

Rows can now be reordered three ways, all going through one model API:

  • Drag the grip at the left of a row onto another row. It takes that row's position, carrying the whole condition (column, operator, value, enabled flag) unchanged.
  • Right-click a row and pick Move Up or Move Down.
  • VoiceOver rotor actions "Move Filter Up" and "Move Filter Down".

The grip appears once there are two or more rows. Its gutter is always reserved, so rows do not shift when the second one is added.

Why not List + .onMove

.onMove only works inside a List, and the API that lifts that restriction (.reorderable() / reorderContainer) is macOS 27. This app targets macOS 14.

Moving the panel into a List would have meant putting FilterValueTextField, a 587-line NSViewRepresentable with its own focus-claim state machine and an attached autocomplete panel, inside a control with documented macOS List/TextField editing friction (click, then wait, before the field takes text). It would also have invalidated the panel's height measurement and conditional scroll view. Rewriting onto NSTableView would re-host that same focus machinery for a bigger cost.

So the panel keeps its VStack, and reordering is additive: Transferable payload, .draggable(_:preview:) on the grip, .dropDestination per row. Because it is a real system drag session, VoiceOver's own drag and drop works against it, which a hand-rolled DragGesture would have broken silently.

Notes

  • Order is organizational only. Every row is joined by the same Match all / Match any setting, so a move can never change which rows the query returns. No AND/OR rebalancing exists to get wrong, and a test pins that.
  • No persistence or query changes. A reorder mutates state like editing a value does, and rides the existing save paths (Apply, tab switch, navigate away).
  • The drop target only accepts com.tablepro.filter-row, so text drags still pass through to the value field.
  • A drag whose payload is not in the current filter set is a no-op, which is what makes a drag between windows safe.
  • No undo stack. The panel has none today (removing a filter is not undoable either), and Move Up / Move Down makes a mistake trivially reversible.

Tests

30 passing across FilterMoveTests (new, 11 cases) and FilterSettingsStorageTests (added a 3-filter order round-trip; every existing fixture used a single filter). Covers both drop directions, both menu directions, every no-op path, whole-condition preservation, and WHERE-clause equivalence after a move.

No UI automation for the drag gesture: AppKit/SwiftUI drag sessions do not run deterministically under XCUITest, so the pure move logic carries the coverage.

Design note

The grip is a judgement call, not an Apple convention. The HIG has no macOS drag-handle concept (showsReorderControl is iOS-only), and whole-row dragging is the stated convention. But whole-row dragging is not available here: a mousedown in the value field starts text selection and the pickers consume clicks, so most of each row cannot begin a drag. A narrow dedicated gutter resolves that. No SF Symbol matches a 2x3 dot grid, so it is drawn as six circles. The pointer stays an arrow, since the HIG assigns hand cursors to content panning.

Requested in TablePlus/TablePlus#3890.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@mintlify

mintlify Bot commented Jul 30, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
TablePro 🟢 Ready View Preview Jul 30, 2026, 6:47 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@datlechin
datlechin merged commit bb22218 into main Jul 30, 2026
3 checks passed
@datlechin
datlechin deleted the feat/filter-row-reorder branch July 30, 2026 18:48
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