Kleidos UI Library#
The in-house, immediate-mode graphics library that draws every on-device screen
across the Kleidos fleet (135×240 sticks, 320×240 Gray / CoreS3 / T-Deck, 240×135
Cardputer, 200×200 CoreInk e-paper). It is not LVGL, M5GFX, or any third-party
UI toolkit — it is a small, host-testable, multi-backend renderer built directly
on the display:: HAL.
This directory is the conceptual + architectural + component guide. Per function and per type API reference is generated by Doxygen (see
docs/doxygen*and the@ingroup ui_*groups). The design tokens of record live in.claude/skills/kleidos-design-system/assets/tokens.json; this guide documents how the firmware consumes them. Reference screenshots are intentionally out of scope for now and will be added near production.
What it is#
- Immediate-mode. There is no retained widget tree. A screen, every frame,
computes geometry and calls stateless component functions (
drawHeader,drawMenuList,drawButton, …) that emit draw calls and return. There is no component state to invalidate, diff, or leak. - In-house. Icons are drawn from primitives (no glyph font), shapes from the
display::HAL, text from generated AA atlases. There is no external UI dependency; every device is direct-draw through this library. - Multi-backend. The same component definition renders on a 16-bit color TFT
(
ColorMode::Rgb565, anti-aliased over a RAM shadow framebuffer) and on a 1-bit e-paper panel (ColorMode::Mono1, crisp ink/paper). Each component documents its Mono1 branch. - Host-testable. Components are pure functions of props +
LayoutContextthat draw into aui::Canvas&. On the host, aRecordingCanvasrecords every draw call so native tests can assert layout across device geometries without a panel. This is "the UI safety net."
Architecture in one line#
Screen (states/, ui/entry/) ─ props + LayoutContext ─▶ ui::Canvas
│ │
│ component fns (drawHeader, drawMenuList, …) ├─ RasterCanvas ─▶ display:: HAL ─▶ SpiPanelDriver ─▶ shadow FB ─▶ panel
▼ └─ RecordingCanvas (host tests) ─▶ op log
ui::Tween (animation)
The "all rendering through the library" mandate (project memory): no raw
display:: draws from app/UI/screen code. Everything goes through ui::Canvas +
components. Only RasterCanvas, text_renderer, aa_shapes, and the HAL itself
call display::. Exceptions: hw_test and the debug console.
Table of contents#
| Doc | Covers |
|---|---|
| architecture.md | Render pipeline: Canvas → RasterCanvas → display:: → shadow framebuffer; frameBegin/frameCommit bracketing; dirty regions; the cross-core seqlock; the single-pinned-task / mutex rule; AA path. |
| tokens.md | Design-token reference: color tokens + roles, the spacing / radius scales, the font scale/roles, PPI-aware resolution, the Mono1 collapse rules. |
| layout.md | LayoutContext, the orthogonal DeviceProfile, responsive breakpoints, flex/box helpers, how components query geometry. |
| components.md | The component catalog: every src/ui/components/ component (purpose, props, stateless vs retained, Mono1 branch, tokens used) plus widgets and the popup system. |
| input.md | The 2-/3-button / keyboard / touch input model and the house interaction convention; how screens own interaction while components stay stateless. |
| fonts.md | The AA atlas, the size ladder, per-device subset, the UTF-8→Latin-1 fold, the 5 supported languages, and how to regenerate. |
Related docs (cross-reference, not duplicated here)#
docs/design/font-integration.md— firmware typography policy.docs/design/ui-iteration-handoff.md— design iteration notes.docs/design/mockups/—*-coherence.svgreference screens.docs/api-reference.md— admin-portal / OTA HTTP API (not on-device UI)..claude/skills/kleidos-design-system/— the canonical design system (tokens.json, patterns).
Source map#
| Path | Contents |
|---|---|
src/ui/core/ |
canvas.h, layout.h, layout_context.h, device_profile.h, theme.h, tokens.h, animation.h, tab_indicator.h, gradient.h, mask_glyph.h, render_task.h |
src/ui/render/ |
raster_canvas.* (device Canvas over display::), aa_shapes.* (AA primitives) |
src/ui/components/ |
The stateless component catalog (+ qr/) |
src/ui/popup/ |
popup_system (toast/banner/dialog/spinner/transition), popup_queue |
src/ui/widgets/ |
Higher-level retained widgets (action_bar, brand_mark, device_panel, on_device_menu) |
src/ui/brands/ |
Domain→logo brand atlas + registry |
src/ui/input/ |
ButtonInput model + GPIO / virtual / keyboard sources, HoldButton |
src/ui/entry/ |
PIN / passphrase entry screens (pin_arc, pin_entry_ui, passphrase_entry_ui) |
src/hal/display/ |
spi_panel_driver (shadow FB), fonts/ (AA atlas), text_renderer, e-paper driver |
test/support/recording_canvas.h |
Host RecordingCanvas fake |