Put the adjustment groups in the rail where a finger is driving

Reported from the tablet: the tool rail is very useful there, and the same
interface under a mouse and keyboard is not. That is `ui-navigation.md` D-N2's
central assumption failing in use, and the interesting part is which half of
it failed.

D-N2 was right that platform is the wrong axis and width is the wrong axis: a
tablet in landscape wants what a desktop wants, and a desktop window dragged
narrow wants what a small screen wants. `apply_layout_class` still decides the
layout class from the window and nothing here changes that. What D-N2 got
wrong is the sentence "touch changes hit regions, not layout" — it identified
input as the real difference between the targets and then assumed that
difference could never reach the layout.

Two controls answer one question — which group of adjustments am I looking at
— and neither is better in general. A horizontal strip above the column is one
gesture to a target the eye has already found, and it pans when the operation
set is rich, so a group can sit off the end with nothing saying so: a pointer
user tolerates that, a finger user never discovers it. The same list down the
rail is every entry visible at once, each finger-sized, on the edge of the
screen the hand is already holding, and it costs no width because the rail is
already there.

So `ToolRail` grows a second section, and `GroupStrip` stands down when it
does. The two are never both on screen, which is why they can share
`adjust-tab-picked`: Rust is not told which was pressed and has no reason to
want to. Mode and group stay independent axes as N1 requires — one entry lit
in each section, and choosing a group while a tool is held still filters
without putting the tool down.

They stay drawn differently, which N1 also required. The tools fill with
`active-dim` and invert their ink; the groups take a bar down the leading
edge — the strip's underline turned ninety degrees — so a lit entry says which
kind of state it is without the reader having to remember which section it was
in. The rule between the sections is the second signal.

The rail scrolls now. Its own note argued against a Flickable because "this
list is four entries written in this file"; with the groups in it the list
comes from the operation set, which is exactly the "something the user's data
decides" that note excluded this control from.

The axis is input, and it is a preference because the automatic answer is a
guess that cannot be made reliable. Neither platform can be asked what the
user is holding: an Android tablet in a keyboard case is being driven like a
desktop, and a touchscreen laptop is whichever its owner says.
`dr_plat::is_touch_first` reports the usual case per platform, and
`GroupNavigation` lets it be overridden. Settings names what Automatic
resolves to on this device rather than leaving it to be found by pressing.

D-N6 records the reversal beside the decision it reverses, including the half
that still stands and the question it opens: whether Local is a mode at all,
or a scope that would collapse the two sections into one list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-05 18:14:03 +02:00
co-authored by Claude Opus 5
parent 474dcf0bf6
commit 6a97fdf6f9
10 changed files with 573 additions and 22 deletions
+70 -1
View File
@@ -147,7 +147,12 @@ describe what is being looked at — and without it the instrument and the
controls disagree about what they are measuring. Costs a mask term in the
histogram reduction, which already runs per frame over the displayed frame.
### D-N2 — One layout, because both targets are wide · **DECIDED**
### D-N2 — One layout, because both targets are wide · **PARTLY REVERSED**
> **Reversed for navigation, 2026-09-05, by use.** The reasoning below is
> still right about *size* and still right that `cfg(target_os)` is the wrong
> axis. It is wrong in one place, and the wrong bit is the sentence "touch
> changes **hit regions, not layout**". See D-N6.
The question was whether desktop and Android should diverge. The answer turns
out to be that **neither the platform nor the width axis separates DarkRoom's
@@ -196,6 +201,70 @@ throughout.** The consequences worth stating:
and nothing about them is qualified by a modifier: what is drawn is all there
is.
### D-N6 — The groups move to the rail under a finger · **DECIDED**
Reported from a tablet: the tool rail is *"very useful"* there, and the same
interface with a mouse and keyboard is not ergonomic. That is D-N2's assumption
failing in the field, and it is worth being precise about which half failed.
**What D-N2 got right.** Platform is the wrong axis, and width is the wrong
axis. A tablet in landscape wants what a desktop wants; a desktop window
dragged narrow wants what a small screen wants. `apply_layout_class` still
decides the layout class from the window, and nothing here changes that.
**What it got wrong.** It identified input as the real difference between the
targets and then concluded that input changes only hit regions. Two controls
answering one question — *which group of adjustments am I looking at* —
disprove it:
- **A horizontal strip above the column.** One gesture to a target the eye has
already found; costs one row of a column with height to spare. It pans when
the operation set is rich, so a group can be off the end with nothing saying
so — which a pointer user tolerates and a finger user does not discover.
- **A vertical run down the rail.** Every entry visible at once, each a
finger-sized target, on the edge of the screen the hand is already holding.
Costs nothing extra in width, because the rail is already there and already
mandated.
Neither is better in general. The first is better with a pointer and the second
is better with a finger, which is a divergence on **input modality** — the axis
D-N2 itself named.
**The shape.** `ToolRail` grows a second section below a rule: the same
`adjust-tabs` model the strip takes, plus "All". `GroupStrip` stands down when
the rail carries them, so the two are never both on screen and there is no
state to keep in step. Mode and group stay independent axes exactly as N1
requires — one entry lit in each section, and picking a group while a tool is
held still filters without putting the tool down.
**Drawn differently, still.** N1 insisted a mode and a filter must not be told
apart by the shape of their highlight alone. The tools fill with `active-dim`
and invert their ink; the groups take a bar down the leading edge — the
underline from the horizontal strip, turned ninety degrees. The rule between
the sections is the second signal.
**The rail scrolls now.** Its own note argued against a Flickable on the
grounds that four entries were written in the file. With the groups in it the
list is generated from the operation set, which is exactly the "something the
user's data decides" the note excluded it from.
**And it is a preference, because the automatic answer is a guess.** Neither
platform can be asked what the user is actually holding — an Android tablet in
a keyboard case is being driven like a desktop, and a touchscreen laptop is
whichever its owner says. `dr_plat::is_touch_first` reports the usual case per
platform and `dr_types::GroupNavigation` lets it be overridden; Settings names
what Automatic resolves to on this device rather than leaving it to be found by
pressing.
**Still open: whether Local is a mode at all.** The rail now holds two kinds of
entry, and a third reading is available — that Compose and Repair are
categories with a canvas gesture attached, while Local edits *nothing* and
instead changes what every other category applies to. That would make it a
**scope**, not a peer of the tools, and would collapse the two sections into
one list of seven. It is the tidier model and a much larger change; deferred
until the two-section rail has been lived with. §1.1's complaint was that scope
was invisible, so this is the same argument arriving from the other end.
### D-N3 — Collapsible panels, not tool tabs · **OPEN**
For the expanded layout, extend `ui-refinement.md` Workstream C from