ui-primitives¶
Provenance¶
- Source:
.spec/spexcode/spec-dashboard/dashboard-ui/ui-primitives/spec.md - Source SHA-256:
c4a2b825fff1fbc8841cbb668bb0e1b7f93af869791e42f485cb8ba8fa024a9c
Every node here exists for the same reason: a thing more than one surface needs, held to one implementation so those surfaces cannot drift into dialects. None of them was designed up front — each was extracted after the scattered version had already gone wrong. Hand-drawn SVGs with different stroke widths and icon buttons with no accessible name. Per-overlay Escape handlers whose winner was decided by registration order. Three textareas measuring growth three ways. Three markdown parsers rendering the same prose three ways. The pattern is the point: the second copy is where the defect enters.
- [[icon-system]] — the one glyph vocabulary, and the icon-only button that cannot ship without a tooltip and an accessible name.
- [[tooltip]] — the one themed singleton bubble any
data-tipelement participates in. - [[context-menu-chrome]] — the one right-click menu shell: icon-led rows, groups, separators, and theme-native states.
- [[composer]] — the one auto-growing editor shell every dashboard-authored composer mounts.
- [[prose-renderer]] — the one prose renderer and its dialect marks, so authored text means the same thing wherever it is read.
- [[esc-layers]] — the one LIFO Escape stack, so a press peels the layer in front and never the surface behind it.
- [[resizable-panes]] — the one pane-resize mechanism: divider, clamp, persistence, and reset gesture.
- [[transient-notices]] — the one short-lived result surface: a themed, dismissible stack with one default timeout instead of each page pinning an ad-hoc acknowledgement into its layout.
What keeps this from becoming a junk drawer is a real admission test, applied twice. A node belongs here only when it is owned by no single surface — a widget only one page will ever mount belongs to that page, not here — and when its whole contract is the mechanism rather than a product decision. That second half is also where reuse stops: the composer owns geometry, measurement, and the IME boundary but never what Enter means; the menu chrome owns the row grammar but never which commands exist; the thread, the rail, and the review rows are surfaces built with these, not more of them. A primitive that starts growing a parameter per caller has crossed back over that line.
This node owns no source of its own — each child keeps its files, [[links]], and drift.