song grid: reorder rows (move a sound up/down the song) nf-h648 ← Beads

open priority 2 task unassigned

Twinned from https://github.com/cfsh/ninefold/issues/395 by tools/beads/import_github.py's reconcile pass.

Follow-up from #321, never filed at the time. Originally proposed as suggestion 2 in [this comment](https://github.com/cfsh/ninefold/issues/321#issuecomment-5107968236): *"row reordering becomes cheap to express (hold-X on a row label + d-pad up/down) since the grid is now a first-class focus area with its own input mode."*

Why it's cheap now. #335 made the SONG grid a real focus area with its own input mode and a wired focus chain, and the sticky-mode machinery (#195/#303: arm a mode, d-pad drives it, ◯ = done, amber butterbar coaches) already exists and is probe-gated. Row reorder is another instance of that pattern rather than new grammar.

Sketch (not a decision): - Controller: focus a row's cell (or the row label), long-press ✕ to open the cell radial — add a ⇅ move row wedge — then ▲/▼ move the row and ◯ commits. Alternative with no radial round-trip: a MOVING sticky mode armed the same way the other modes are, so the butterbar reads MOVING · ▲▼ move · ◯ done. - KVM: drag a row label, or right-click → move up/down. - Visual: the moving row keeps its accent and slides; neighbours part around it. FocusGlide already animates focus moves, so a row slide should borrow that easing rather than teleport.

What makes this more than cosmetic: row order is the visual grammar of the song — kids read top-to-bottom as "drums at the bottom, melody on top". Today the only way to reorder is delete-and-recreate, which destroys the row's patterns.

Model questions to settle first: 1. What actually moves? Song.Rows is the ordered list, and TonapseStyle.SoundColor(rowIdx) derives a row's *accent from its index* — so a naive reorder recolours every row it passes, which would be jarring and would break the pennant-ink work (#338) that assumes a stable sound↔colour mapping. Either move the colour with the sound (store an accent/index on the sound) or accept recolouring — this is the crux of the issue and worth deciding before any UI work. 2. Does anything else key off row index? SoundPicker.ChipAt(row) (1:1 chips), _lastFocusCoords, EditorState.CurrentSoundIdx, and the #335 open-pattern targeting all index by row — each needs to follow the move or be re-derived after it. 3. Persistence: row order is already implicit in Song.Rows serialization, so no schema change expected — worth confirming against #250's versioning rules (a pure reorder of an existing list is not a reinterpretation, so likely no Migrations.Current bump).

Probe-gateable the same way the other sticky modes are (sticky-modes.json is the template): arm, move, assert the row order and that focus/selection followed the moved row.

Unclaimed — filed so it isn't lost now that #321 is closed.

Dependencies

None.

Comments

No comments.

Add a comment