Chart builder: SelectControl pickers, channel chooser, per-type aggregates

This commit is contained in:
2026-06-12 14:45:31 +03:00
parent 4dcff4601d
commit ed66fe9c05
15 changed files with 1232 additions and 276 deletions
@@ -418,6 +418,34 @@ _(Consulted via /council → NN/g #4 consistency, #6 recognition-over-recall, #8
WAI-ARIA APG disclosure + menu-and-menubar; Carbon popover/overflow-menu/text-toolbar. This
bullet is the contract.)_
**Resolved — value pickers are the SelectControl disclosure, not native `<select>`.** A
native select's popup can't be token-styled and renders differently on every browser/OS — a
foreign object inside a designed surface — so anywhere a control is part of one,
`SelectControl` replaces it: the same disclosure primitive as the settings popovers (trigger
with `aria-expanded`/`aria-controls`; portaled, `fixed`-positioned panel; labelled `group` of
option buttons — **not** an ARIA menu or combobox; single-open registry; Esc closes and
refocuses the trigger; outside press closes; open lands focus on the selected option;
Arrow/Home/End rove). The selected option carries `aria-current` and a visible ✓, never
colour alone. The same control doubles as an **action picker** (no `value`; e.g. "Add field
to which channel?"). A custom `triggerClassName` _replaces_ the default trigger styling, so
chip-styled triggers (the pill's type chip, the shelf's field chips) stay chips.
_(Consulted via /council → WAI-ARIA APG disclosure/menu-button/radio, Carbon, NN/g #4. This
bullet is the contract; cite it, not the source.)_
**Resolved — field→channel assignment: explicit choice, visible armed state.** Clicking a
shelf field with no channel armed opens an explicit **channel chooser** (the channels that
accept the field; an occupied one is labelled with what it replaces) — never a silent
first-empty-seat grab (NN/g #3, user control). Arming a channel slot short-circuits the
chooser (the fast path) and **must be visible where the next click happens**: the shelf
gains an accent ring plus a polite `role="status"` line naming the target ("Assigning to X —
choose a field below. Esc cancels"); **Esc disarms** without closing the modal (captured
before the dialog's own Escape handling). Chart-level properties (title/subtitle,
width/height) live **on the chart side**, in a strip under the preview — a chart property
belongs on the chart (NN/g #4; the Tableau/Lyra convention). A link-styled affordance that
_acts_ rather than navigates is mis-dressed: such actions are **ghost buttons** with
verb-first labels (Carbon links-vs-buttons; "Use a constant"). _(Consulted via /council →
NN/g #1/#3/#4, Carbon button/link usage. This bullet is the contract.)_
**Resolved — an error names the right fix, not a boilerplate one.** Don't staple a generic
remedy onto every failure. A missing dataset reference is **not** a JSON/spec syntax problem,
so the preview gives it a tailored, fixable line — _"Dataset «X» not found. Create it from