feat(ui): add Phase 2 stateless reference components (ActionBar/Header/BrandMark/StatusChip)
First catalog components on the Canvas + DeviceProfile foundation
(plan/ui-library-modular-reimpl.md Phase 2). Stateless: props in ->
draw via Canvas -> return, reading the orthogonal DeviceProfile for
device adaptation. Purely additive — no existing screen/state/widget/
Canvas changed.
- ActionBar (action_bar_component): affordance-driven footer hints. The
same ActionBarProps render the device-correct presentation picked from
the profile capabilities — 2-button A/B, 3-button A/B/C, CoreInk dial
^/O/v, keyboard key hints, touch bare labels. Mono1/e-paper path uses a
top divider rule + cell inversion instead of the SURFACE fill + ACCENT
hold-fill.
- Header (header_component): title + subtitle + right-packed status
cluster (battery %, BLE, WiFi, lock). Density/orientation-aware via
LayoutContext; Mono1 uses a bottom divider rule, ink-only tokens.
- BrandMark (brand_mark_component): credential brand badge. Reuses the
brands::findBrand/drawBrand registry+atlas on device; falls back to a
deterministic per-domain letter tile (host-testable). Mono1 outlines.
- StatusChip (status_chip_component): self-sizing status pill using
radius.pill (clamped), token color per ChipStyle, knockout/outline text.
Tests (host, RecordingCanvas): 30 new cases across 4 suites, incl. the
per-affordance ActionBar assertions (2btn/3btn/dial/keyboard/touch), the
Mono1 branches, brand letter-fallback + deterministic color, and chip
sizing/geometry. Shared per-variant DeviceProfile factories in
test/support/device_profiles.h.
Verified: fleet 5/5 -Werror (sticks3/gray/cardputer/tdeck/m5core_ink),
native 720/720 (+30), pio check 3 pre-existing HIGH only, all guards +
pre-commit pass.