Skip to content

sparkles:ui — Feature Specification

Status: living inventory · Date: 2026-08-05 · Scope: libs/ui (libs/ui/src/sparkles/ui/*.d), the sibling backend adapters (sparkles:ui-raylib, sparkles:ui-tui), and sparkles:input — the shared visual language behind every sparkles UI.

sparkles:ui is a canvas-first UI toolkit: one widget tree, laid out once, painted by pluggable backends. A widget names a semantic Slot, never a concrete color; a backend supplies only draw primitives and input events. The pipeline is view() → layout() → buildDisplayList() → paint(canvas), and every stage before paint is @safe and GL-free, so the whole toolkit is unit-testable through a RecordingCanvas with no window and no terminal.

This spec is the source of truth for the toolkit and the decision record for the choices behind it — in particular the layout model (LAY2), which requirement pre-narrowed to a survey of docs/research/ui-layout/ and which is settled here.

It supersedes docs/specs/hue/ui-architecture.md, which proposed the library before it existed; that page now holds only hue's own consumption requirements.

Design sources

The toolkit's design is grounded in three research catalogs in this repository. Where a requirement below cites one, the catalog is the evidence, this spec is the decision.

SourceWhat it grounds
UI layout catalogthe layout model — 24 engines surveyed across box-flow, flexbox, constraints-down, solver, retained, immediate and tiling families (LAY)
Sean Parent catalogthe architectural rules — Whole/Part ownership, value semantics, explicit relationships, illegal states unrepresentable (PRN)
Tree-view case studythe view-model/view split, exemplified by the tree widget (WGT, VMD)

Documentation map

PageWhat it covers
Overview (this page)what the toolkit is · the three levels · the package graph · the status/ID/traceability scheme · module coverage
Feature requirementslibrary-wide requirements: the three levels, the canvas-first contract, the package graph and its dependency-cycle constraints, build/@nogc posture
Architectural principlesthe binding rules the toolkit is held to, each traced to its source in the Sean Parent catalog — no incidental data structures, value semantics, explicit relationships, narrow contracts
Layoutthe LAY2 decision record — the surveyed families, the verdict (box-flow + orientation-aware measure + clip), the integer-unit rule, and the explicit list of what is not implemented
Themethe unified runtime-swappable design language — syntax rules, semantic slots, glyph sets and metrics in one value, gated by terminal capabilities
Widgetsthe view-model/view split, the widget catalog, Props vs handlers, keys and element identity
Inputthe abstract event vocabulary, the tier-0/1/2 capability ladder, and the backend adapter contracts
State machinespresentation-free behavior: scrollbar, selection, hover, focus, disclosure, timeline
Containersthe container tier: ScrollView (owned scrolling) and the single-window docking layout (splits, tabbed groups, drag-to-redock, focus/capture ownership) — SCV/DCK
Editor (planned)the editable-text component — the EditorState machine (EDT), per-backend text input incl. IME/soft-keyboard phasing (EDI), the editor widget (EDR), and its consumers (EDU) — the capability behind hue's diff write wave (UIA9)
Backendsthe isCanvas seam, the shipped targets, per-backend declared capabilities, and forward-compatibility rules for additional GPU backends
Open implementation issuesconcrete deferred gaps: Whole/copy semantics, the closed widget sum, and the native pointer grab
Interaction reviewthe 2026-07-31 audit of every pointer/keyboard behavior: where it lives (toolkit vs apps/hue), the GUI/TUI divergences, and the Phase B redesign scope (IXR/IXB)
Migrationabsorbing core-cli's UI components and porting apps/hue onto the toolkit — the milestone plan
Application host (proposed)the sibling sparkles:ui-app package: backend selection, the shared window/font CLI, and the frame/event loop — the layer above the canvases, so an application never names one

The three levels

Each lower level is usable independently and free of presentation:

LevelContentSpec
1 — state machinespure logic over abstract input → state + derived geometry, in abstract unitsSTM
2 — layoutrenderer-agnostic containers and sizing, producing rectanglesLAY
3 — widgetsview(state) → WidgetTree, composing levels 1 and 2 with draw primitivesWGT

Beneath them sit two cross-cutting concerns — the theme (THM), which resolves a widget's semantic slot to concrete appearance, and input (INP), which feeds the state machines.

Render targets

The toolkit itself is backend-agnostic; a target is a type satisfying isCanvas!T plus, for interactive targets, an input adapter.

TargetPackageCanvasNotes
TUIsparkles:ui-tuiGridCanvascell grid over sparkles:tui; retained via the cell-diff compositor
GUIsparkles:ui-raylibRaylibCanvasGPU quads over sparkles:raylib-text; immediate mode
HTMLsparkles:uiinterp/htmlserializes the tree to markup + CSS; pure-CSS interactivity where possible
testingsparkles:uiRecordingCanvascaptures a DrawOp[]; the GL-free seam every unit test renders through

Status scheme

Every requirement row carries one Status:

StatusMeaning
not startedno implementation yet.
researcheddesign/notes exist (in code comments or a sibling doc), but no implementation.
partialimplemented with a documented limitation or missing sub-case (the row's notes say what is missing).
full (<sha>)fully implemented; <sha> is the primary commit (the "commit hash evidence"). Where several commits contributed, the earliest feature commit is cited and later refinements are noted.
decideda decision requirement rather than an implementation one — the choice is settled and recorded on the page itself. Used only where there is nothing to implement, e.g. "the layout model is box-flow".

This matches the hue spec's scheme so the two trees can cross-reference status without translation.

ID scheme

Requirement IDs are <AREA><n> — a short area mnemonic plus a number, unique within a document (e.g. LAY4, WGT2, TGT1). Areas: UIA/PKG/NFR (library-wide), PRN (principles), LAY (layout), THM (theme), WGT/VMD (widgets and view models), INP (input), STM (state machines), TGT (backends), MIG (migration). Each area's mnemonic is expanded at its section heading.

Traceability

Every source file under libs/ui/src/, libs/input/src/ and the backend adapter packages is covered by at least one requirement. The Module coverage table at the foot of each spec lists each file against the requirement IDs that own it, so coverage is auditable in both directions: requirement → code (the "Traces to" column of every row) and code → requirement (the coverage tables).

Source filePrimary spec + areas
libs/ui/src/sparkles/ui/geometry.dlayoutLAY3, LAY6
libs/ui/src/sparkles/ui/layout.dlayoutLAY1LAY8, LAY11, LAY12
libs/ui/src/sparkles/ui/wrap.dlayoutLAY10
libs/ui/src/sparkles/ui/tracks.dlayoutLAY9
libs/ui/src/sparkles/ui/style.dthemeTHM1THM5
libs/ui/src/sparkles/ui/theme.dthemeTHM6THM9
libs/ui/src/sparkles/ui/canvas.dbackendsTGT1, TGT5
libs/ui/src/sparkles/ui/widget.dwidgetsWGT1WGT6
libs/ui/src/sparkles/ui/display_list.dbackendsTGT2
libs/ui/src/sparkles/ui/state.dstate machinesSTM1STM7
libs/ui/src/sparkles/ui/interp/immediate.dbackendsTGT3
libs/ui/src/sparkles/ui/interp/cells.dbackendsTGT6; superseded by the cell adapter and retired with it
libs/ui/src/sparkles/ui/interp/html.dbackendsTGT4, TGT7
libs/ui/src/sparkles/ui/components/widgetsVMD*, WGT7+
libs/input/src/sparkles/input/inputINP1INP9
libs/ui-tui/src/backendsTGT6
libs/ui-raylib/src/backendsTGT6

Feature requirements · Principles · Layout · Widgets