mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Chart builder: SelectControl pickers, channel chooser, per-type aggregates
This commit is contained in:
@@ -421,6 +421,13 @@ open, wraps `Tab`/`Shift+Tab` within the modal, and restores focus on close. The
|
||||
optional `initialSelector` picks _which_ child takes focus (e.g. Cancel for a
|
||||
destructive confirm); it falls back to the first focusable child.
|
||||
|
||||
The trap wraps Tab **only within the shell element**: content portaled to
|
||||
`<body>` (a `SelectControl` panel or other disclosure popover opened from inside
|
||||
a modal) is outside both the trap's DOM subtree and its keydown listener. Such
|
||||
popovers must therefore handle Tab themselves — close and refocus their trigger
|
||||
(the native-select convention) — so focus can't strand outside the dialog while
|
||||
it is open.
|
||||
|
||||
```ts
|
||||
// src/app/hooks/useFocusTrap.ts
|
||||
import { useRef, useEffect } from 'react';
|
||||
|
||||
@@ -471,6 +471,10 @@ the existing view is re-measured via a `ResizeObserver`-driven event — see §8
|
||||
- **Don't** put reference resolution or fit-mode logic in the renderer — it is
|
||||
pure core logic and must be unit-testable without a DOM.
|
||||
- **Don't** mutate the input spec anywhere in the pipeline.
|
||||
- **Fit modes overwrite the spec's own sizing** (Width replaces `width` _and
|
||||
deletes_ `height`, etc.), so a surface that lets the user set an explicit
|
||||
width/height must pass `fitMode: 'default'` while either is set and reserve the
|
||||
container fit for auto sizing — the Chart Builder preview does exactly this.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user