feat(datagrid): reorder filter rows by drag or the row menu - #2001
Merged
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
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.onMoveonly works inside aList, and the API that lifts that restriction (.reorderable()/reorderContainer) is macOS 27. This app targets macOS 14.Moving the panel into a
Listwould have meant puttingFilterValueTextField, a 587-lineNSViewRepresentablewith 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 ontoNSTableViewwould re-host that same focus machinery for a bigger cost.So the panel keeps its
VStack, and reordering is additive:Transferablepayload,.draggable(_:preview:)on the grip,.dropDestinationper row. Because it is a real system drag session, VoiceOver's own drag and drop works against it, which a hand-rolledDragGesturewould have broken silently.Notes
com.tablepro.filter-row, so text drags still pass through to the value field.Tests
30 passing across
FilterMoveTests(new, 11 cases) andFilterSettingsStorageTests(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 (
showsReorderControlis 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.