Skip to content

Replace the dropdowns with banks and machined windows - #113

Merged
LynxTWO merged 4 commits into
masterfrom
feat/slice-016-selectors
Aug 24, 2026
Merged

LynxTWO merged 4 commits into
masterfrom
feat/slice-016-selectors

Conversation

@LynxTWO

@LynxTWO LynxTWO commented Aug 23, 2026

Copy link
Copy Markdown
Owner

Builds SLICE-016, approved 2026-08-23. Stacked on #112 (uses the KeyStandby tokens from it), so merge that first.

Every selector now sits in one of two controls. Eleven of fifteen were never lists - a dropdown hides its options behind a click, which is right for a drive list and wrong for three fixed choices that fit on one line.

Neither is a new control class

  • Bank = ListBox Classes="bank". Arrow-key selection, per-key accessible name and selected state, and the same ItemsSource/SelectedItem/SelectedIndex the combos were bound to all come with ListBox, so most call sites change one element name and keep their bindings. Each key is the SLICE-014 machined cap plus the switch lamp pip.
  • Window = ComboBox Classes="window" template restyle, so opening, keyboard handling and the accessible role are untouched. counted adds the tape-counter readout, opt-in per site.

Sixteen sites converted: six banks (quality, layout on Rip and Settings, metadata search, album art search, network), ten windows.

The first render clipped "Salvage"

Worth recording, because the design doc claimed the Rip page "has room at its 1200 pixel default". That was the page width, not the width the control gets. The rail is 300 DIP, ~274 usable, and a four-key bank beside its own label does not fit at any padding worth having.

Three fixes, all in: label goes above the bank in the rail (+58 DIP), a compact variant tightens the keys (all four quality positions then fit on one line), and the items panel is a WrapPanel so a bank that genuinely cannot fit becomes a two-row keypad instead of losing a position.

Two real bugs surfaced on the way: the key template hardcoded Padding="12,5" instead of using TemplateBinding, so the compact variant did nothing.

Why the suite did not catch it

The scale matrix asserts the page does not overflow its viewport. A bank inside a fixed-width column overflows the column while the page stays exactly as wide as before, so the clipped render was green on every other assertion in the suite. Two new layout tests now look inside the bank: no position cut off at any of the five supported widths in either theme, and every position visible, non-empty and reachable.

189 tests green. Rendered both themes at 1200 DIP (Rip rail and Advanced rows); the existing scale matrix passes unchanged, which matters because banks are wider than what they replaced.

Dragging a few hundred pixels off a key while holding it looked fine on
long keys and got progressively stranger the shorter the key was. That
is a real defect, not taste.

The tilt term divides the press offset by the key's own half-diagonal,
so a press point off the key drives that ratio past 1 with nothing
stopping it - 500 DIP off a 40x30 key reaches 20 - and tilt scales on
it directly. Worst displacement measured 14.79 DIP against a 6.0
budget, and it worsens as the key shrinks because the same drag divides
by a smaller half-diagonal and projects onto a shorter reach. Long keys
are not exempt, just slower to break.

The model gains the two terms it was missing, both physical. A finger
cannot load a point that is not on the cap, so contact clamps to the
key's rectangle. And sliding a finger off a key you are holding
transfers the pressure off it, so the load eases away over 14 DIP and
the key rises. That second one also stops the key lying about what
happens next, since releasing out there does not activate it. Drag back
on and it presses again.

The old budget test only ever pressed points inside the key, which is
why it never saw this. Six tests now cover the drag.
The off look was right and the letters could not be read. Measured,
they sat at 1.2:1 on the dark key face and 1.5:1 on the light one,
against 14:1 and 16:1 for a live key. That is not dim, it is invisible:
the legend had drifted to the brush meant for hairlines.

On a real console the legend is a translucent window in an opaque cap
with a bulb behind it, and turning the key off turns that bulb down to
standby rather than out, so the letters keep a faint light of their own
and you can still find the key in the dark. That is what this does: new
KeyStandby and KeyStandbyGlow tokens per theme, plus a zero-offset drop
shadow in the lamp colour, which is what makes it read as light coming
through the letters rather than grey ink sitting on them.

Bounded on both sides and pinned by test, because either failure is
easy to reach: at least 3.0:1 so it reads, and no more than two fifths
of the live key's ratio so it still looks unpowered, across both the
resting and pressed faces in both themes. The pressed face binds on the
light bench, since a key disabled mid-press takes the dead release
while its face is still dark. A second test pins the hue - a neutral
grey would clear the contrast bounds and lose the entire point.

WCAG exempts disabled controls, which is why none of this was ever
measured. The exemption says an inactive control need not meet AA. It
does not say it may be unreadable.
D-085 is the one that matters: the owner's gate question on the
flag-gated build was whether the shaded dip reads as below the console
surface or whether the outline has to move, and it reads as below. So
the mesh renderer, the custom draw operation, the Skia-lane test
project and the supersampled output path are all unfunded. The
projective homography over a pinned rim is the shipping technique.

D-086 and D-087 record the drag defect and the dead legend, including
the numbers, so neither gets tuned back by someone who did not measure
them.
Every selector in the app now sits in one of two controls instead of a
stock combo. Eleven of the fifteen were never lists: a dropdown hides
its options behind a click, which is right for a drive list and wrong
for three fixed choices that fit on one line.

Neither is a new control class. The bank is a ListBox, which brings
arrow-key selection, a per-key accessible name and selected state, and
the same ItemsSource/SelectedItem/SelectedIndex the combos were already
bound to, so most call sites change one element name and keep their
bindings. The window is a ComboBox template restyle, so opening,
keyboard handling and the accessible role are untouched. Each bank key
is the machined cap from SLICE-014 with the lamp pip from the switches.

Sixteen sites converted, six to banks and ten to windows.

The first render clipped Salvage off the quality bank, which is worth
recording because the design doc had cheerfully claimed the Rip page
had room at 1200. It does not: the rail is 300, and the measurement
that mattered was never taken. The label moves above the bank there,
a compact variant tightens the keys, and the items panel wraps so a
bank that truly cannot fit becomes a two-row keypad rather than losing
a position. Two things also turned out to be real bugs - the key
template hardcoded its padding instead of binding it, so the compact
variant did nothing at all.

The scale matrix could not catch any of this. It asserts the page does
not overflow its viewport, and a bank inside a fixed-width column
overflows the column while the page stays exactly as wide as before.
The clipped render was green on every other assertion in the suite, so
there are now two layout tests that look inside the bank.
@LynxTWO
LynxTWO force-pushed the feat/slice-016-selectors branch from 4cf0f28 to 993a984 Compare August 23, 2026 20:42
@LynxTWO
LynxTWO merged commit f2e8401 into master Aug 24, 2026
6 checks passed
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