Masonry goes column-major — cards read top-down, then across
Replaces the pathfinder-inherited round-robin deal (child i -> column i % C) with contiguous column segments: base = n/C, the first n%C columns take one more, and logical order runs down each column before crossing to the next. Only the geometric mapping changes -- ranks, selection flatten, and VoiceOver order are untouched, and MasonryPlacement stays the single placement function both the Layout and the drop model replay. Why: an insertion under round-robin shifted every later card across columns; under the column-major deal later cards slide within their column and at most one card crosses each boundary, so the drag reflow is far calmer. Drop-slot math gets simpler too -- a column's cards are one contiguous range, a non-final column's tail is now a genuine mid-list position, and only the last column's tail means append. DropSlotMathTests recomputed and extended (46 -> 50): the uneven-fill deal, boundary positions, the shared tail/head boundary index, and a placement/ drop-model shadow-agreement check. DRAG-REORDER.md and DESIGN/10 amendments are listed for ratification, deliberately not edited here. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -704,20 +704,18 @@ struct LaneView: View {
|
||||
// holds identically under Reduce Motion: a transition that does not fire has no
|
||||
// variant to choose between.
|
||||
.transition(Motion.cardTransition(reduced: reduceMotion))
|
||||
// **VoiceOver reads the masonry by `order`, not by column** — 10-accessibility.md
|
||||
// ▸ Logical order, not masonry position (decided): "within a wide lane,
|
||||
// VoiceOver reads cards by `order` — the interior grid columns are presentation
|
||||
// only. This deliberately diverges from on-screen geometry."
|
||||
// **VoiceOver reads the masonry by `order`, not by drawn position** —
|
||||
// 10-accessibility.md ▸ Logical order, not masonry position (decided).
|
||||
//
|
||||
// The divergence is real and it is why an explicit priority is needed at all:
|
||||
// `MasonryLayout` assigns child `i` to column `i % columns`, so in a 3-unit lane
|
||||
// the second card by `order` is drawn to the *right* of the first, not below it
|
||||
// — and an accessibility tree sorted by geometry (which is what a container does
|
||||
// without this) would read the board column-major: 1, 4, 7, 2, 5, 8 …, an order
|
||||
// that exists nowhere in the model, on disk, or in the keyboard grammar.
|
||||
// Priority descends with the slot index, so the highest reads first and the list
|
||||
// is exactly `slots` — the same sequence the masonry is handed and the same one
|
||||
// `SelectionGrammar` flattens.
|
||||
// The divergence narrowed when the masonry went column-major — walking down
|
||||
// one column now *is* consecutive `order` — but it is still real, and it is
|
||||
// why an explicit priority is needed at all: a geometry-sorted accessibility
|
||||
// tree (which is what a container does without this) sweeps in reading order,
|
||||
// left-to-right then down, which over a column-major grid interleaves the
|
||||
// columns: 1, 4, 7, 2, 5, 8 …, an order that exists nowhere in the model, on
|
||||
// disk, or in the keyboard grammar. Priority descends with the slot index, so
|
||||
// the highest reads first and the list is exactly `slots` — the same sequence
|
||||
// the masonry is handed and the same one `SelectionGrammar` flattens.
|
||||
//
|
||||
// The drag shadows are inert here: `DragShadow` hides itself from the tree, and
|
||||
// a slot that is not an element consumes no priority.
|
||||
|
||||
Reference in New Issue
Block a user