Add pane show/hide toggle strip with persisted visibility (M6, §01A)

A persistent left-rail toolbar (APG toolbar + roving tabindex) toggles the
library / editor / preview panes; a hidden pane frees its space and the rest
redistribute proportionally to their remembered widths. Visibility persists to
astrolabe:ux-prefs (separate key from widths, so a hidden pane keeps its width).
Adds the positional pane-* glyph sub-family to Icon and a Datasets shortcut
button in the strip.
This commit is contained in:
2026-06-07 17:15:58 +03:00
parent f92118712c
commit 8c0a6b9239
11 changed files with 601 additions and 45 deletions
@@ -162,13 +162,41 @@ lives in [04 · Routing & Global Events](04-routing-and-events.md).
is unit-tested, not trapped in the component); the live value needs the container width,
observed via `ResizeObserver` so it tracks window resizes, not just drags.
- `aria-controls` points at the pane it sizes (`pane-library` / `pane-preview`).
- **Keyboard**: ←/→ nudge; **Home** → smallest pane size, **End** → largest. **Enter-to-collapse
is deferred to M6** with the pane-visibility / toggle strip — collapsing needs a
hidden-pane state that doesn't exist yet, so we don't fake it.
- **Keyboard**: ←/→ nudge; **Home** → smallest pane size, **End** → largest. **Enter-to-collapse**
now has a home — the hidden-pane state landed in M6 with the toggle strip (below). The strip
owns show/hide; wiring the splitter's Enter to it is an optional convenience, not required.
_(Consulted via `/council` → WAI-ARIA APG `windowsplitter`. This bullet is the contract;
cite it, not the APG file.)_
**Resolved — pane toggle strip.** The persistent show/hide strip (spec §01A) is a **WAI-ARIA
APG `toolbar`** (`role="toolbar"`, `aria-orientation="vertical"`, an `aria-label` such as
"Workspace panes") — **not** a row of independently-tabbable buttons. Grouping into a toolbar
gives the cluster a **single tab stop** with a **roving tabindex**, which APG names as the way
to reduce tab stops for a control group. Vertical keyboard model: **Up/Down** move among
controls, **Home/End** jump to first/last, **Tab/Shift+Tab** move into/out and restore the
last-focused control on re-entry.
- The three pane controls are **toggle buttons**`aria-pressed` with a **stable** accessible
name that does **not** change with state (`aria-pressed="true"` ⇔ pane visible; the name stays
"Library pane" / "Editor pane" / "Preview pane"; only the icon may swap). This matches the
`ThemeToggle` precedent and APG's toggle-button rule — _"it is critical the label on a toggle
does not change when its state changes."_ These are **independent booleans**, so toggle
buttons — never a radio/segmented group; reserve `role="switch"` for genuine single-setting
on/off.
- The **Datasets** control is a plain **command button** (no `aria-pressed`) in the _same_
toolbar — APG permits mixed control types — set off from the toggles by a visual divider (and
optionally a nested `role="group"`), but kept in the roving sequence as its last element.
- **Focus**: show/hide is only ever initiated **from the strip**, so the activating toggle
already holds focus when its pane disappears and **retains it** (the button stays, flips to
not-pressed) — no orphaned focus, no restoration logic. The strip is **never itself hidden**,
so even with **all panes hidden** it stays the always-reachable "emergency exit" (NN/g #3 user
control). The pane appearing/disappearing plus the `aria-pressed` flip is the status feedback
(NN/g #1 visibility of system status).
_(Consulted via `/council` → WAI-ARIA APG `toolbar` + `button` (toggle); NN/g #1/#3. This
bullet is the contract; cite it, not the APG files.)_
**Resolved — segmented (single-select) controls.** A "pick one of N" control (fit modes,
the Draft/Published view) is a **radio group**, never a row of `aria-pressed` toggles
(those model N independent booleans). Use the shared `SegmentedControl`: `role="radiogroup"`