The full time-series chart the Admin pillars drill into: multiple labelled series over a shared time axis, with gridlines, y/x axis labels, an optional filled area (band) or stacked mode, and a hover crosshair that reads the exact value at a point. The at-a-glance counterparts stay specialised — `<Sparkline>` for an inline trend, `<Gauge>` for a single ratio, `<DonutChart>` for a categorical split — this is what they expand into. Pure SVG computed in Rust so it renders identically under SSR and after hydration.
Readiness
complete
Preview
live
Props
7
Examples
2
Code
implementation mapped
When to use
An operator dashboard progression view (intake/terminal net-flow, runs over time, vitals).
Comparing two or more series on a shared time axis (e.g. shown vs clicked).
A stacked composition over time (intake split by source) — set `stacked`.
A metric that is partly instrumented — flag the series `gapped` to draw it honestly.
When not to use
A tiny inline trend beside a number — use `<Sparkline>`.
A single ratio/percentage — use `<Gauge>`.
A parts-of-a-whole split at one instant — use `<DonutChart>`.
Accessibility
Role: group
No keyboard shortcuts
Screen reader: The chart carries a visible legend (series are labelled, not colour-only) plus an offscreen text summary of each series' latest value, so a screen-reader user gets the data without the SVG geometry. The hover readout is `aria-live="off"` (pointer-only, not announced).
Notes: Series tone reinforces — it is never the only signal (legend label + last-value text carry meaning). Honours `prefers-reduced-motion` at the CSS-rail level: the live-append slide tween collapses to an instant redraw.
Props
Name
Type
Default
Description
series
array
—
The series to plot. Each: `{ label, tone, gapped?, points: [{t, v}] }` (points may also be bare numbers, in which case `t` is the index). Reactive. Required.
width
integer
640
SVG viewBox width in px (scales to container, keeps ratio).
height
integer
240
SVG viewBox height in px.
y_format
enum: count | ms | percent | tokens
count
How y-axis labels + the hover readout format values.
stacked
boolean
false
Stack series cumulatively (implies filled areas).
band
boolean
false
Fill the area under each line (ignored when stacked, which always fills).
aria_label
string
—
Chart-level description; an offscreen latest-value summary is always added.
Examples
Net-flow: intake vs terminal
Pipeline net-flow — intake (caution) vs terminal (good) over a window.
A circular identity chip. When `src` is set it shows the image; otherwise it derives up-to-two-letter initials from `name` on a token-tinted background. Three sizes keep identity consistent across dense rows, default lists, and profile headers.
Readiness
complete
Preview
live
Props
3
Examples
3
Code
implementation mapped
When to use
A user or agent identity in a list row or header
Comment / activity authorship
Anywhere a person/agent needs a compact recognisable mark
When not to use
A stack of several identities — use AvatarGroup
A general framed image — use Image
A status indicator — use Badge / status-dot
Accessibility
Role: img
No keyboard shortcuts
Screen reader: The image variant uses `name` as alt; the initials variant exposes `name` via role=img + aria-label so the identity is announced rather than read as loose letters.
Notes: Initials are a visual shorthand only — the accessible name is always the full `name`, never the two-letter abbreviation.
Props
Name
Type
Default
Description
name
string
?
Display name — drives initials and the accessible name.
src
string
—
Optional image URL. Empty → initials.
size
enum: small | medium | large
medium
Examples
Initials
An initials avatar (no image).
GH
YAML
type: avatar
props:
name: Grace Hopper
size: medium
Sizes
The three sizes side by side.
ABCDEF
YAML
type: stack
props:
gap: sm
direction: row
align: center
children:
- type: avatar
props:
name: A B
size: small
- type: avatar
props:
name: C D
size: medium
- type: avatar
props:
name: E F
size: large
Show several identities in a compact overlapping stack — collaborators on a board, agents on a run. `overflow` renders a trailing "+N" chip for identities not shown so the count stays honest without widening the row.
Readiness
complete
Preview
live
Props
2
Examples
3
Code
implementation mapped
When to use
Collaborators / members on a card or board header
Agents participating in a run
Any compact 'these N people' affordance
When not to use
A single identity — use Avatar
A full member list with names — use a list / Table
Selectable participants — compose with interactive rows
Accessibility
Role: group
No keyboard shortcuts
Screen reader: The container is role=group; each child Avatar carries its own accessible name, and the overflow chip exposes "+N more" via aria-label so the hidden count is announced, not just shown.
Notes: The overlap is purely visual; assistive tech still reads each avatar in DOM order followed by the overflow count.
Props
Name
Type
Default
Description
size
enum: small | medium | large
medium
overflow
integer
0
Count rendered as a trailing +N chip (0 = none).
Examples
Collaborators
Three collaborators with two more hidden.
ALGHAT+2
YAML
type: avatar-group
props:
overflow: 2
slots:
default:
- type: avatar
props:
name: Ada L
- type: avatar
props:
name: Grace H
- type: avatar
props:
name: Alan T
No overflow
A small stack, no overflow.
QARB
YAML
type: avatar-group
slots:
default:
- type: avatar
props:
name: Q A
- type: avatar
props:
name: R B
Large + overflow
Large stack with a big overflow count.
OT+12
YAML
type: avatar-group
props:
size: large
overflow: 12
slots:
default:
- type: avatar
props:
name: One
size: large
- type: avatar
props:
name: Two
size: large
A read-only rectangular label displaying a count or status. Use Badge when the value is non-interactive — clicking it does nothing. For interactive filter chips, use FilterChip; for free-form labels, use Tag (when it lands). The tone (variant) is structural: muted for inherited / inactive values; primary for emphasis; success / warning / danger / info for ladder-consistent semantic states.
Readiness
complete
Preview
live
Props
1
Examples
3
Code
implementation mapped
When to use
Status indicator on a list row (e.g. 'Active', 'Failed', 'Pending')
Numeric counter ('12 unread', '3 errors')
Inherited / inferred value markers (`muted` variant — '[parent]')
Inline labels next to text headings
When not to use
Interactive toggles — use FilterChip
Read-only free-form text label — use Tag (when it lands)
Element identity (icon + colour + name) — use ElementBadge
Numeric counter on rail items — use CounterPill (sibling, panel-bound)
Accessibility
Role: status
No keyboard shortcuts
Screen reader: Reads the badge's text content. Variant colour is decorative only — semantic state should be conveyed in the text (e.g. 'Status: Active' not just 'Active' next to a green badge).
Notes: Don't rely on colour alone to convey status. Pair badges with text or icons so colourblind users can still parse them.
Compare a small set of categorical values. Each bar's length is its value relative to the dataset maximum, and the numeric value is printed alongside so the chart is readable without colour or precise length perception. For trends over time use Sparkline; for parts-of-a-whole use DonutChart.
Readiness
complete
Preview
live
Props
1
Examples
3
Code
implementation mapped
When to use
Top-N comparisons (counts per category, per element)
Small operational breakdowns on a dashboard
Any 'compare these few values' summary
When not to use
Time series — use Sparkline
Parts of a whole / percentages — use DonutChart
Large datasets needing axes / zoom — out of scope
Accessibility
Role: img
No keyboard shortcuts
Screen reader: The chart container is role=img with an aria-label. Each row prints its label and exact numeric value as text, so the data is fully available without interpreting bar length or colour.
Notes: Value is conveyed as text in addition to bar width — never by bar length alone.
A read-only code sample surface with monospace type, horizontal overflow, and an optional language label. Use it for API examples, shell commands, JSON payloads and generated snippets so every code sample on the platform reads the same way.
Readiness
complete
Preview
live
Props
2
Examples
3
Code
implementation mapped
When to use
API examples, shell commands, JSON payloads, generated snippets
Read-only code samples inside a docs / markdown surface
Short configuration examples
When not to use
Editable code fields — use code-input
One-line inline values — use inline code, or kbd for a shortcut
Large file viewers needing search / minimap — out of scope
Accessibility
Role: region
No keyboard shortcuts
Screen reader: Wrapped in role=region with an aria-label naming the language so screen-reader users can navigate to and skip the sample.
Notes: The language label is decorative chrome; the code itself is the content and is exposed verbatim in the <pre><code>.
Props
Name
Type
Default
Description
language
string
text
Language label shown in the header (also drives the aria-label).
code
string
—
The code text. Falls back to the default slot's text.
Examples
Shell
A shell command sample.
bash
cargo run -p triform-server --features ssr-frontend
One horizontal label→value row for detail panels and sidebars. Label left, value right, with an optional `badge` ("[parent]", "[here]") and an optional `muted` style for inherited/default values. It is the row atom — stack several inside a list or `<DefinitionList>` for a detail block. Use `<KeyValue>` instead when the shape is `name = value` config with masking/actions.
Readiness
complete
Preview
live
Props
4
Examples
2
Code
implementation mapped
When to use
A property/detail panel line — Name → my-element, Type → python.
Sidebar metadata rows where label/value alignment should be consistent.
Rows that need a small status badge ([parent], [here], [overridden]).
When not to use
Env/secret config with masking + edit/delete actions — use `<KeyValue>`.
A clickable row that expands detail — use `<ExpandableRow>`.
Free-form two-column layout — use a layout primitive, not a semantic row.
Accessibility
Role: presentation
No keyboard shortcuts
Screen reader: Presentational by default — label and value read in order. When a row conveys a semantic pair that matters to AT, prefer wrapping a set of them in `<DefinitionList>` (proper `<dl><dt><dd>`) rather than relying on visual adjacency.
Notes: `muted` is visual only — don't let it be the sole signal that a value is inherited; pair with a `badge` ("[inherited]") so the meaning survives for low-vision users.
Props
Name
Type
Default
Description
label
string
—
Row label (left). Required.
value
string
—
Row value (right). Required.
badge
string
—
Optional small status badge ([parent], [here], [overridden]).
muted
boolean
false
Muted/inherited styling. Visual only — pair with a badge so the inherited meaning is not colour-alone.
Examples
Detail rows
Element detail rows — the canonical sidebar shape.
Name my-elementType pythonStatus active
YAML
type: stack
props:
direction: column
gap: sm
children:
- type: text
slots:
default: Name my-element
- type: text
slots:
default: Type python
- type: text
slots:
default: Status active
The semantic multi-row wrapper for label→value pairs. `<KeyValue>` and `<DataRow>` are the single-row atoms; DefinitionList wraps a set of them in proper `<dl><dt><dd>` markup with consistent rhythm and column alignment so a detail block is one accessible unit, not visually-adjacent rows. Use it when a group of read-only attributes should scan like data and announce as term/definition pairs.
Readiness
complete
Preview
live
Props
2
Examples
2
Code
implementation mapped
When to use
A detail block of label→value pairs that should be ONE semantic unit (element properties, request metadata).
Where `<dl>` semantics matter for assistive tech (grouped term/definition associations).
Replacing a visually-aligned stack of rows that AT currently reads as unrelated lines.
When not to use
A single pair — use `<KeyValue>` or `<DataRow>` directly.
Editable config — use `<Field>`/`<Input>`; this is a display wrapper.
Accessibility
Role: list
No keyboard shortcuts
Screen reader: Target semantics: `<dl>` with each pair as `<dt>` (term) + `<dd>` (definition) so AT announces grouped term/definition associations rather than loose lines. This is the primary reason the component exists over a plain row stack.
Notes: Render as `<dl><dt><dd>…` for proper semantic association.
Props
Name
Type
Default
Description
pairs
array
—
The term→definition pairs rendered as `<dt>`/`<dd>`. Each entry is a label + value (+ optional badge), mirroring `<DataRow>`.
aligned
boolean
true
Whether `<dt>` columns align to a shared width (true, default — scannable) or `<dd>` flows directly after each `<dt>`.
Examples
Properties definition list
Element-properties definition block.
Name
my-element
Type
python
Created
2026-05-16
Owner
iggyactive
YAML
type: definition-list
props:
pairs:
- label: Name
value: my-element
- label: Type
value: python
- label: Created
value: 2026-05-16
- label: Owner
value: iggy
badge: active
Request metadata
Request-metadata block with a status badge on one pair.
Render a unified diff: a monospace block of lines, each marked added (+), removed (-), or context (space) with both a gutter glyph and a token-tinted background. Use it for review snippets, generated-change previews, and "what changed" summaries.
Readiness
complete
Preview
live
Props
1
Examples
3
Code
implementation mapped
When to use
Review / change-preview snippets
Showing a generated edit before applying it
Config or code 'before vs after' summaries
When not to use
Plain (non-diff) code — use code-block
Full side-by-side file review with navigation — out of scope
Prose change tracking — not a diff surface
Accessibility
Role: region
No keyboard shortcuts
Screen reader: Wrapped in role=region + aria-label "Diff". Each line begins with a literal +/-/space gutter glyph in the text, so add/remove status is conveyed in content — not by background colour alone.
Notes: The tinted backgrounds are reinforcement only; the gutter glyph is the primary, colour-independent signal.
Props
Name
Type
Default
Description
lines
array
—
Diff lines in order. Each: { kind: add|del|context, text }.
A donut/pie for categorical breakdowns — "where are runs happening" (mail/phone/boards/agents), "where are errors concentrated". Self- contained SVG arc math (no chart library, no canvas, SSR-safe). The hollow centre (`inner_ratio`, default 0.6 ring) carries a total-count label; slices ≤2% of the total fold into one "Other" wedge so the ring stays legible (`collapse_small: false` to opt out).
Readiness
complete
Preview
live
Props
5
Examples
2
Code
implementation mapped
When to use
A categorical share — runs by surface, errors by service, cost by element type.
A breakdown where the total (centre label) matters alongside the split.
Dashboard composition tiles needing SSR with no chart JS.
When not to use
A single ratio/percentage — use `<Gauge>`.
A trend over time — use `<Sparkline>`.
Many categories with precise values — a labelled bar/table reads better than a forest of wedges.
Accessibility
Role: img
No keyboard shortcuts
Screen reader: The SVG is decorative; `aria_label` should summarise the split and a non-visual label/value list should sit nearby so SR users get the per-slice numbers. Slice colour alone is meaningless to them.
Notes: The ≤2% "Other" fold is a legibility default — when exact small slices matter, pass `collapse_small: false` and surface the values in an adjacent list.
Props
Name
Type
Default
Description
slices
array
—
The categorical entries. Each is a label + value + CSS colour. Reactive. Required.
inner_ratio
number
0.6
Inner radius as a fraction of outer (0.0 = full pie, ~0.6 = ring).
collapse_small
boolean
true
Fold slices ≤2% of total into one 'Other' wedge for legibility.
center_label
string
—
Optional hollow-centre label (usually the total count).
aria_label
string
—
SR summary of the breakdown.
Examples
Runs by surface
Runs-by-surface breakdown with a total in the centre.
A compact identity badge for element types and element instances. Badge sizes that show a label reserve the label line even when custom data is incomplete, so icon grids do not change rhythm as metadata loads. The reusable showcase preview mirrors the portal class contract, so changes made here are visible immediately on `/components` and in portal badge surfaces.
Readiness
complete
Preview
live
Props
13
Examples
2
Code
implementation mapped
When to use
Element type selectors where a compact icon-led option is enough
Breadcrumbs, trees, and inline mentions that need element identity
Instance badges with custom icon, color, image, or glow overrides
When not to use
Library browse results that need intention context — use library-element-card
Full element-type catalog entries — use element-card
Generic status labels unrelated to elements — use badge
Accessibility
Role: button
Enter — Activates the badge when clickable
Space — Activates the badge when clickable
Screen reader: The button exposes an aria-label derived from the display name. Decorative icons and images are hidden from assistive tech.
Notes: XS badges hide the name visually. Larger badge sizes reserve a stable name line so a grid does not compress when a custom label is absent.
Props
Name
Type
Default
Description
element_type*
string
—
Element type identifier.
display_name
string
—
Optional preview label for component-showcase rendering.
symbol
string
—
Optional symbol fallback for component-showcase rendering.
icon_name
string
—
Optional Material Symbols icon for component-showcase rendering.
icon_color
string
—
Optional identity color for component-showcase rendering.
size
enum: xs | sm | md | lg | xl
md
Badge size. XS is icon-only; larger sizes show a stable label slot.
show_name
boolean
—
Overrides size-based name visibility.
custom_name
string
—
Optional label override.
selected
boolean
false
Selected visual state.
highlighted
boolean
false
Keyboard-highlight visual state.
disabled
boolean
false
Disabled interaction state.
glow
boolean
false
Live/active glow treatment.
title
string
—
Tooltip and optional accessibility label detail.
Examples
Badge row
Compact element badge row for selectors and toolbars.
YAML
type: stack
props:
gap: sm
direction: row
align: center
children:
- type: element-badge
props:
element_type: circle
display_name: Circle
symbol: Ci
icon_name: radio_button_unchecked
icon_color: '#8B5CF6'
size: md
- type: element-badge
props:
element_type: app
display_name: App
symbol: Ap
icon_name: deployed_code
icon_color: '#8B5CF6'
size: md
- type: element-badge
props:
element_type: validation
display_name: Validation
symbol: Va
icon_name: fact_check
icon_color: '#FF7A1A'
size: md
Badge states
Live and selected badge states.
YAML
type: stack
props:
gap: sm
direction: row
align: center
children:
- type: element-badge
props:
element_type: queue
display_name: Queue
symbol: Qu
icon_name: dns
icon_color: '#FF7A1A'
size: lg
glow: true
- type: element-badge
props:
element_type: contacts
display_name: Contacts
symbol: Cn
icon_name: person
icon_color: '#2F80FF'
size: lg
selected: true
- type: element-badge
props:
element_type: board
display_name: Board
symbol: Bd
icon_name: view_kanban
icon_color: '#6B7280'
size: lg
disabled: true
A reusable full element identity card for browse, showcase, chooser, and live-runtime surfaces. The intention row always reserves two lines, even when empty, so card grids keep a stable rhythm while data is incomplete. Type cards emphasize elemental metadata; instance and live cards can add compact metrics without changing card geometry.
Readiness
complete
Preview
live
Props
15
Examples
4
Code
implementation mapped
When to use
Element catalog and component showcase entries
Chooser surfaces where users compare multiple element types
Element cards that need name, symbol/icon, intention, and metadata tags
Instance and live-runtime summaries with a few high-value statistics
When not to use
Dense library browse grids — use library-element-card
Inline text references — use element-badge-inline
Pure layout grouping — use card
Accessibility
Role: article
No keyboard shortcuts
Screen reader: The card exposes the element name and kind as its accessible label. Icons and accent strips are decorative because the name and text carry identity.
Notes: If the card is interactive, render it as a button/link through the component API rather than adding click handlers to a passive wrapper.
Props
Name
Type
Default
Description
kind*
string
—
Kebab-case element type.
symbol*
string
—
Short periodic-table symbol.
name*
string
—
Human-readable display name.
intention
string
—
One- or two-line element intention. Empty still reserves space.
category*
string
—
Element category id.
icon_name
string
—
Material Symbols icon name.
icon_color*
string
—
Category or element identity color.
form
string
—
Element form label.
variant
enum: type | instance | live
type
Card mode: elemental definition, instantiated element, or live runtime.
The structural neighbourhood of an element in two stacked blocks. First, the composition categories a compound element is built from — each a labelled, icon-led bucket of member element badges. Then the topology relations (Contains, Uses, Attaches) plus the reverse-topology "Referenced by" — each a labelled row of member badges. Member badges link to the element's page, with an href_base prop that lets /components repoint links to its own routes. Driven through the shared ViewEngine `element-composition` arm so /docs and /components stay pixel-identical. A leaf atom with no composition or topology renders nothing.
Readiness
complete
Preview
live
Props
3
Examples
2
Code
implementation mapped
When to use
Compound element pages showing what the element is built from
Any element with topology — what it contains, uses, attaches, or is used by
Linking an element to its structural neighbours with navigable badges
When not to use
A leaf atom with no composition or topology — the component renders nothing
A flat list of unrelated elements — use an element badge row directly
Live instance graphs — this is a type-level structural view
Accessibility
Role: group
No keyboard shortcuts
Screen reader: Each composition category and each relation is a section with its heading as the accessible name, and the member badges form labelled lists. Category and relation icons / glyphs are hidden from assistive technology; the member badges keep their own button semantics inside navigable links.
Notes: Empty categories and relations are dropped so assistive tech never meets an empty heading.
Props
Name
Type
Default
Description
categories
array
—
Composition category buckets (empty for non-compound atoms). Each is a labelled, icon-led group of member element badges.
relations
array
—
Topology relation rows — Contains, Uses, Attaches, Referenced by. Each is a labelled row of member element badges.
href_base
string
/docs/elements/
Link base for member badges. /components repoints this to /components/elements/ so the same component serves both surfaces.
Examples
Composition and relations
A compound element's composition categories and topology.
A pointy-top hex tile matching the canvas element footprint. It carries generated element identity metadata plus a reusable state vocabulary for active, pulse, attention, error, and inactive states. Animated states are subtle and respect reduced-motion preferences.
Readiness
complete
Preview
live
Props
11
Examples
2
Code
implementation mapped
When to use
Canvas-adjacent element previews
Element topology and periodic-table layouts
Compact state visualization where shape identity matters
When not to use
Text-heavy browse results — use element-card or library-element-card
Dense lists — use element-miniature
Inline text mentions — use element-badge-inline
Accessibility
Role: img
No keyboard shortcuts
Screen reader: The rendered element exposes the display name and state in its accessible label. SVG icon and decoration are hidden from assistive technology.
Notes: State is not conveyed by color alone: each state value is also present in data-state and the accessible label.
The cross-cutting view of how element categories wire together. Given nodes (every element ref with its category) and edges (category→category relationship weights), it renders two legible halves: a grid of category cluster cards each holding its element badges, and a list of from→to relationship strands each carrying an edge-count chip. This is deliberately NOT a force-directed graph — a layout of ~78 nodes is unreadable in generated/SSR markup — but the same information expressed as category clusters plus relationship counts. Driven through the shared ViewEngine `element-relationship-map` arm.
Readiness
complete
Preview
live
Props
3
Examples
1
Code
implementation mapped
When to use
An overview of how element categories relate across the whole platform
A landing visual that orients a reader to the element category map
Anywhere a category-level relationship summary beats a node-edge tangle
When not to use
A single element's neighbourhood — use element-composition
A precise force-directed graph — intentionally rejected as unreadable here
Per-instance live relationships — this is a type/category-level view
Accessibility
Role: group
No keyboard shortcuts
Screen reader: The cluster grid is a list of category sections, each headed by the category name and element count. The strands are a list whose items spell out "{from} to {to}: {weight} {kind} relationship(s)" so the count and direction are announced without relying on the arrow or chip glyph, both hidden from assistive technology.
Notes: Categories appearing only as a strand endpoint still get a (member-less) cluster card so every strand resolves; relationship counts are conveyed in the accessible name, not by the chip alone.
Props
Name
Type
Default
Description
nodes
array
—
Every element node, each tagged with its category. Nodes are grouped into category cluster cards.
edges
array
—
Category→category relationship strands rendered as from→to rows with an edge-count chip.
href_base
string
/docs/elements/
Link base for member badges.
Examples
Category constellation
A small category constellation with three clusters and strands.
A list/table row that reveals an inline detail panel on click and collapses on click again — the core drill pattern for the dashboard error panel (click an error, see affected runs) and cockpit per-element detail. The `detail` body is lazy (only built when expanded) so heavy drill queries don't run until the user opens the row. Expansion state is local to the row.
Readiness
complete
Preview
live
Props
3
Examples
2
Code
implementation mapped
When to use
Drill-in rows where detail is expensive and should load only on open (error → affected runs).
Per-item inline detail in a list/table without navigating away.
Rows whose expansion is independent of siblings (multiple can be open).
When not to use
Accordion behaviour (only one row open at a time) — wrap in a coordinator or use `<Disclosure>`.
A static label→value row — use `<DataRow>`.
Navigation to a full detail view — use a link/drill, not inline reveal.
Accessibility
Role: button
Enter — Toggle expansion (summary is the activation target).
Space — Toggle expansion.
Tab — Focuses the summary row, then expanded detail content.
Screen reader: The summary is `role=button` with `aria-expanded` reflecting state, so SR users know the row is togglable and its current state. Because detail is lazily built, ensure the expanded content is announced (focus management / live region) when it appears.
Notes: Local state by design. For one-open-at-a-time semantics the caller coordinates externally — don't bolt accordion logic onto the row.
Present a file reference compactly: a generic document glyph, the file name, and an optional human-readable meta line ("PDF · 1.2 MB"). It is intentionally content-agnostic — it does not download or render the file (that's the consumer's job) — so every attachment / upload row looks and reads the same.
Readiness
complete
Preview
live
Props
2
Examples
3
Code
implementation mapped
When to use
An attachment row on a message or record
An uploaded-file confirmation chip
A reference to a file the user can act on elsewhere
When not to use
Rendering image content — use Image
Playing audio/video — use MediaPlayer
A full file browser / tree — use Tree
Accessibility
Role: group
No keyboard shortcuts
Screen reader: The chip is role=group with an aria-label of the file name; the glyph is aria-hidden decoration and the name + meta are real text.
Notes: The icon is decorative — the file name is the accessible content, so a missing/instructive name is never masked by the glyph.
Props
Name
Type
Default
Description
name
string
file
File name (with extension).
meta
string
—
Optional size / kind line (e.g. 'PDF · 1.2 MB').
Examples
Document
A document with size.
q3-report.pdfPDF · 1.2 MB
YAML
type: file-preview
props:
name: q3-report.pdf
meta: PDF · 1.2 MB
A circular progress ring for a single ratio/percentage tile — success-rate, resource utilisation, eval pass-rate. Pure SVG (ghost backing ring + stroked arc), SSR-safe, no chart library. `value/max` sets the fill (default `max: 1.0` so `value` can be a direct fraction); `tone` selects the stroke palette. Use `<DonutChart>` instead when you have a categorical breakdown rather than one ratio.
Readiness
complete
Preview
live
Props
6
Examples
2
Code
implementation mapped
When to use
A single headline ratio tile — "61% worked", storage used/limit, eval pass-rate.
Dashboard KPI rings where the centre carries the number + a label line.
A SSR-rendered progress dial (no runtime chart JS).
When not to use
A categorical breakdown (mail/phone/agents share) — use `<DonutChart>`.
A trend over time — use `<Sparkline>`.
A linear progress bar — use a progress primitive, not a circular gauge.
Accessibility
Role: img
No keyboard shortcuts
Screen reader: The SVG is decorative; `aria_label` MUST carry the value in words (e.g. "CPU usage 73%"). The arc geometry alone gives a screen-reader user nothing.
Notes: Tone is reinforcement, not the sole signal — the numeric label / aria_label carries meaning so colour-blind and SR users are covered.
Props
Name
Type
Default
Description
value
number
—
Current value (clamped to [0, max]). Reactive. Required.
max
number
1.0
Upper bound. Default 1.0 so `value` can be a direct fraction.
tone
enum: primary | success | warning | error | muted
primary
Stroke palette. Reinforces — not the sole signal.
size
integer
72
Diameter in px.
label
string
—
Optional centre label; omitted → renders the percentage.
aria_label
string
—
SR text carrying the value in words (e.g. "CPU usage 73%").
Examples
Success-rate gauge
Success-rate KPI ring with centre percentage.
◯ 61%Run success rate
YAML
type: stack
props:
direction: column
gap: sm
children:
- type: text
slots:
default: ◯ 61%
- type: text
slots:
default: Run success rate
Storage utilisation (warning)
Warning-tone utilisation gauge near its limit.
◯ 88%Storage used (88 / 100 GB)
YAML
type: stack
props:
direction: column
gap: sm
children:
- type: text
slots:
default: ◯ 88%
- type: text
slots:
default: Storage used (88 / 100 GB)
A single inline glyph resolved from a stable key via the shared icon set. Decorative by default; pass `title` to give it an accessible label.
Readiness
complete
Preview
live
Props
4
Examples
3
Code
implementation mapped
When to use
A small decorative or labelled glyph inside a row of text or a button
Status / category affordances rendered from a known icon key
Any engine spec that needs a vector glyph without raw <svg>
When not to use
A clickable icon-only control — use a button with an icon variant
A large illustrative graphic — that is not an icon
An arbitrary uploaded image — use the image primitive
Accessibility
Role: img
No keyboard shortcuts
Screen reader: With no `title`, the glyph is decorative and hidden from assistive tech. With `title`, it exposes an accessible name. Never rely on an icon alone to convey state to screen-reader users — pair with text.
Notes: `title` is the only accessibility input; absent it, the icon must be purely decorative (its meaning carried by adjacent text).
Props
Name
Type
Default
Description
name
string
settings
Stable icon key resolved against the shared icon set (e.g. settings, terminal, check).
size
string
20
Square edge length in px, as a string (e.g. "16", "20", "24").
class
string
—
Extra CSS class(es) appended to the glyph.
title
string
—
Accessible label. When set, the glyph is exposed to assistive tech; when empty, it is decorative.
A presentation-only chip that renders an identity — a Contact, an Organization, or a pursuit's primary contact — with one shared vocabulary: avatar initials, name, role, and organization. The caller supplies the fields; the chip never fetches, so it is side-effect-free and safe to drop into any surface. The `density` prop selects one of four shapes: `compact` (inline person line), `row` (avatar beside a two-line name/role + organization block), `header` (large avatar disc with name, role, organization, phone, and email for a modal header), and `line` (plain-text one-line fallback for dense lists).
Readiness
complete
Preview
live
Props
6
Examples
2
Code
implementation mapped
When to use
The contact line inside a kanban card body or a pursuit row.
A leads / address-book list row (`density: row`).
The header of an entity-detail modal (`density: header`).
A one-line identity in a dense table or activity row (`density: compact` or `line`).
When not to use
An interactive identity that opens a profile on click — wrap the chip in a button or link; the chip itself is not interactive.
A standalone profile picture with no name — use `<Avatar>`.
Element identity (icon + colour + type name) — use `<ElementBadge>`.
A free-form label or tag — use `<Tag>`.
Accessibility
Role: group
No keyboard shortcuts
Screen reader: The chip is plain text — name, role, and organization are read in document order. In `density: header` the name renders as an `<h2>`, which is the heading an enclosing entity-detail modal points its `aria-labelledby` at. Keep the supplied `name` meaningful; a chip built from only an email or phone reads that value verbatim.
Notes: The chip emits no explicit ARIA role today — it is presentational. The avatar initials disc and the Material Symbols glyphs (person / domain / phone / mail) are decorative and should carry `aria-hidden` so they are not read as stray characters; pair the chip with meaningful text rather than relying on the glyph alone.
Props
Name
Type
Default
Description
density
enum: compact | row | header | line
compact
name
string
—
Primary identity label. Falls back to email, then phone, when absent.
role
string
—
Optional role or title shown after the name (e.g. "VP Engineering").
organization
string
—
Optional organization, shown on the secondary line in row and header densities.
phone
string
—
Optional phone number — shown only in header density; also feeds initials and name fallback.
email
string
—
Optional email — shown only in header density; also feeds initials and name fallback.
Examples
Compact identity
Compact density — the inline person line used in activity rows and kanban card bodies.
Sarah Chen·VP Engineering
YAML
type: stack
props:
direction: row
gap: sm
align: center
children:
- type: icon
props:
name: person
- type: text
slots:
default: Sarah Chen
- type: text
slots:
default: ·
- type: text
slots:
default: VP Engineering
Row identity
Row density — avatar initials beside a two-line name/role and organization block.
SC
Sarah Chen · VP EngineeringNorthwind Traders
YAML
type: stack
props:
direction: row
gap: sm
align: center
children:
- type: badge
props:
variant: primary
slots:
default: SC
- type: stack
props:
direction: column
gap: sm
children:
- type: text
slots:
default: Sarah Chen · VP Engineering
- type: text
slots:
default: Northwind Traders
Display an image inside a frame whose aspect ratio is pinned so the page does not reflow while the image loads. `fit` chooses cover (crop to fill — thumbnails) or contain (letterbox — logos). When `src` is empty a token-styled placeholder is shown instead.
Readiness
complete
Preview
live
Props
4
Examples
3
Code
implementation mapped
When to use
Thumbnails and avatars-as-images in a grid or list
Hero / preview imagery where layout stability matters
Any image that should not cause layout shift while loading
When not to use
Decorative background textures — use CSS
Identity chips with initials fallback — use Avatar
Inline SVG icons — use Icon
Accessibility
Role: img
No keyboard shortcuts
Screen reader: Pass real `alt` for meaningful images; pass an empty string for decorative ones. The placeholder state exposes the same alt via role=img + aria-label so the slot is still announced meaningfully.
Notes: Never omit `alt`. Empty alt is a deliberate "decorative" signal, not a missing-text bug.
Props
Name
Type
Default
Description
src
string
—
Image URL. Empty renders the placeholder frame.
alt
string
—
Alt text. Empty string = decorative.
ratio
string
16 / 9
CSS aspect-ratio value (e.g. '16 / 9', '1').
fit
enum: cover | contain
cover
Examples
Placeholder
An empty 16:9 frame showing the placeholder state.
A thin vertical list container that owns the empty-state branch so callers stop reinventing `if items.is_empty() { empty } else { list }`. When `empty`, it renders `empty_message`; otherwise it renders its children. It is the container, not the rows — compose `<KeyValue>`, `<DataRow>`, or custom rows inside it.
Readiness
complete
Preview
live
Props
3
Examples
2
Code
implementation mapped
When to use
Any vertical list that should show a calm message when there are zero items.
Wrapping a set of KeyValue/DataRow rows with consistent list styling.
List surfaces where the empty case is common (env vars, connections, members).
When not to use
A rich empty state with icon + action — wrap `<EmptyState>` / `<PanelEmptyState>` directly.
A data table with columns/sorting — use a table component.
A single row — just render the row; the list wrapper adds nothing.
Accessibility
Role: list
No keyboard shortcuts
Screen reader: `role=list`; children should be list items. The empty branch replaces the list with a short message — make `empty_message` a meaningful sentence ("No connections yet"), not a bare "Empty", so SR users get the same information sighted users do.
Notes: For a pre-data empty state that needs an icon + call-to-action, the caller should render `<PanelEmptyState>` in the empty branch rather than relying on the plain `empty_message` string.
Props
Name
Type
Default
Description
empty
boolean
false
Whether the list is empty (renders `empty_message` instead of children).
empty_message
string
No items
Message shown when `empty`. Make it a meaningful sentence, not a bare "Empty".
children
array
—
List rows (KeyValue / DataRow / custom). Rendered when not empty.
Display a JSON value for inspection: pretty-printed (2-space indent), monospace, scrollable, in a labelled region. It replaces ad-hoc `<pre>{stringify}</pre>` debug dumps with one consistent surface. Collapsible nodes / syntax colouring are deliberately out of scope — bundling a JSON tokeniser into the showcase bundle is the wrong trade, and the value is fully readable without it.
Readiness
complete
Preview
live
Props
1
Examples
3
Code
implementation mapped
When to use
Inspecting an API response / payload
Showing element config or run output for debugging
Any 'here is the raw JSON' read-only surface
When not to use
Editable JSON — use code-input
An interactive collapsible object explorer — out of scope
Non-JSON code — use code-block
Accessibility
Role: region
No keyboard shortcuts
Screen reader: Wrapped in role=region + aria-label "JSON" so it can be reached and skipped; the content is a real <pre><code> exposing the value verbatim.
Notes: Indentation conveys structure visually; the verbatim text in the <pre> is the source of truth for assistive tech.
Props
Name
Type
Default
Description
json
any
—
The value to display. Objects are pretty-printed; a string is shown as-is.
A compact visual treatment for a single key or a key combination. Use it so shortcut notation reads identically everywhere — a documentation page, a command-palette hint, a menu accelerator. The content is the key label(s); the component supplies the consistent chrome.
Readiness
complete
Preview
live
Props
1
Examples
3
Code
implementation mapped
When to use
Keyboard shortcuts in documentation
Command-palette accelerator hints
Menu / toolbar rows that show an accelerator
When not to use
Inline code or tokens that are not keyboard input — use code-block
Long prose instructions
Button labels — use Button or IconButton
Accessibility
Role: presentation
No keyboard shortcuts
Screen reader: Renders a semantic <kbd> element so assistive tech announces the content as keyboard input rather than plain text.
Notes: Keep the label to the actual key name(s). For a combination, render separate kbd chips joined by a visible "+" so each key is clear.
Props
Name
Type
Default
Description
class
string
—
Extra classes appended after the base kbd class.
Examples
Single combo
A command-palette open shortcut.
⌘+K
YAML
type: stack
props:
gap: xs
direction: row
align: center
children:
- type: kbd
slots:
default: ⌘
- type: text
slots:
default: +
- type: kbd
slots:
default: K
Inline hint
An inline 'press Esc to close' hint.
PressEscto close
YAML
type: stack
props:
gap: xs
direction: row
align: center
children:
- type: text
slots:
default: Press
- type: kbd
slots:
default: Esc
- type: text
slots:
default: to close
Keys
A small set of single keys.
↑↓Enter
YAML
type: stack
props:
gap: sm
direction: row
align: center
children:
- type: kbd
slots:
default: ↑
- type: kbd
slots:
default: ↓
- type: kbd
slots:
default: Enter
The `name = value` row for environment variables, configs, and secrets. Shows an `=` separator, an optional `source` badge ("[parent]", "[circle]"), masks the value as `••••••••` when `masked` (secrets), applies inherited styling when `inherited`, and exposes an `actions` slot for edit/delete. Use `<DataRow>` for plain label→value detail lines; reach for KeyValue when the row is config that can be inherited, masked, or acted on.
Readiness
complete
Preview
live
Props
5
Examples
2
Code
implementation mapped
When to use
Environment-variable / config rows with an inheritance source.
Secret values that must mask by default (`masked: true`).
Config rows that need inline edit/delete actions.
When not to use
Plain detail label→value lines — use `<DataRow>`.
A multi-row semantic block — wrap rows in `<DefinitionList>` for `<dl>` semantics.
Editable form fields — use `<Field>` / `<Input>`; KeyValue is a display row with optional actions, not a form control.
Accessibility
Role: presentation
Tab — Moves into the actions slot (edit/delete) when present.
Screen reader: name / value / source read in order. Masked values announce as the mask glyphs — ensure a reveal control exists in the actions slot if SR users legitimately need the secret; never make the value SR-unreachable when it is required for the task.
Notes: `masked` is a display default, not security — the real value is still in the DOM unless the consumer withholds it. Treat masking as shoulder-surfing defence only.
Props
Name
Type
Default
Description
name
string
—
Variable/key name (left of `=`). Required.
value
string
—
Value (right of `=`). Required; rendered masked when `masked`.
A compact reusable glass element card for the Library panel and dense pickers. It presents the element icon, name, type label, and intention while preserving the same height when intention is missing. This keeps browse/search lists aligned while authors progressively fill metadata.
Readiness
complete
Preview
live
Props
11
Examples
3
Code
implementation mapped
When to use
Library browse and semantic search results
Dense element pickers where cards still need enough context to compare
Cards for element instances that may have custom avatars
When not to use
Full element-type catalog pages — use element-card
Tiny inline references — use element-badge-inline
Generic dashboard cards unrelated to elements — use card
Accessibility
Role: group
No keyboard shortcuts
Screen reader: The parent button or link supplies the actionable label. The card's icon is decorative; the visible name and intention remain real text.
Notes: Keep the card inside a single interactive parent. Do not put buttons inside the card body.
Props
Name
Type
Default
Description
name*
string
—
Human-readable element instance name.
intention
string
—
Element intention. Empty still reserves the same vertical space.
meta_label
string
—
Short element type or category label shown on the trailing edge.
icon_name
string
—
Material Symbols icon fallback.
icon_svg_html
string
—
Raw SVG markup from generated element metadata.
color
string
—
Element/category identity color.
state_color
string
—
Status dot color.
avatar_url
string
—
Optional avatar image URL. Falls back to icon if it fails.
folder
boolean
false
Shows a quiet chevron for drillable compound/folder items.
active
boolean
false
Focused/selected visual state.
loading
boolean
false
Reduced-opacity busy state.
Examples
Library card
Library item with intention copy.
deployed_codeMonth EndReconcile invoices and close the reporting period.App
YAML
type: library-element-card
props:
name: Month End
intention: Reconcile invoices and close the reporting period.
meta_label: App
icon_name: deployed_code
color: '#8B5CF6'
state_color: '#F5D96E'
Missing intention
Library item with no intention still holds the same rhythm.
Library item showing a different element identity in the same reusable shape.
chat_bubbleDaniel CFO CommentaryDraft the month-end commentary and route it for approval.Modifier
YAML
type: library-element-card
props:
name: Daniel CFO Commentary
intention: Draft the month-end commentary and route it for approval.
meta_label: Modifier
icon_name: chat_bubble
color: '#F97316'
state_color: '#F5D96E'
Apply the platform's typographic rhythm (headings, lists, code, links via tokens) to long-form content so generated docs feel like part of the app shell. It accepts EITHER caller-sanitised pre-rendered HTML (the caller owns parsing + sanitisation) OR a plain-text fallback. It deliberately does not embed a markdown parser — keeping the contract truthful: styling is real; the parse step is the caller's. Heading decoration is configurable so the Triform identity accent can stay coherent while the visual language keeps evolving.
Readiness
complete
Preview
live
Props
4
Examples
4
Code
implementation mapped
When to use
Rendering already-parsed, sanitised documentation HTML
Element READMEs whose HTML is produced server-side
Any long-form prose that should match the app's type scale
When not to use
Short labels or inline helper text
Editable rich text — needs an editor, not a viewer
Untrusted HTML — sanitise before passing `html`
Accessibility
Role: article
No keyboard shortcuts
Screen reader: Rendered inside a prose container. When `html` is supplied the caller's semantic structure (headings, lists, links) is preserved verbatim; the plain-text fallback is a single readable block.
Notes: Heading order and semantics are the responsibility of the caller-supplied HTML — this surface only styles it, it does not rewrite structure.
Props
Name
Type
Default
Description
html
string
—
Caller-sanitised pre-rendered HTML. Takes precedence over `text`.
text
string
—
Plain-text fallback when no rendered HTML is supplied.
density
enum: document | panel | chat
document
Typographic density. `document` uses full prose rhythm; `panel` and `chat` compact the scale.
heading_accent
enum: subtle | brand | none
subtle
Heading rule treatment for section headings. `subtle` keeps the rule quiet; `brand` opts into the CTA accent.
Examples
Rendered HTML
Pre-rendered HTML styled by the prose surface.
Overview
This element summarizes text using a small model.
Fast
Cheap
YAML
type: markdown-view
props:
html: <h2>Overview</h2><p>This element summarizes text using a small model.</p><ul><li>Fast</li><li>Cheap</li></ul>
density: document
heading_accent: subtle
Plain text
Plain-text fallback.
No rendered HTML supplied — this is the plain-text fallback block.
YAML
type: markdown-view
props:
text: No rendered HTML supplied — this is the plain-text fallback block.
Done. I updated the schema and kept the generated output in sync.
No restart required
Ready for review
YAML
type: markdown-view
props:
html: <p><strong>Done.</strong> I updated the schema and kept the generated output in sync.</p><ul><li>No restart required</li><li>Ready for review</li></ul>
density: chat
heading_accent: none
Play an audio or video source inside a token-styled frame using the browser's native controls. Native controls are a deliberate choice — they are keyboard-complete, screen-reader-friendly, and support captions for free; a hand-rolled control bar would regress all of that for no benefit at this layer.
Readiness
complete
Preview
live
Props
4
Examples
3
Code
implementation mapped
When to use
Playing a recording, screencast, or audio note
Embedding a short video preview
Any inline media that needs standard playback controls
When not to use
Static images — use Image
A file the user only references (not plays) — use FilePreview
Bespoke synchronized media UX — out of scope
Accessibility
Role: group
Space — Toggle play / pause (native control behaviour)
ArrowLeft — Seek backward (native control behaviour)
ArrowRight — Seek forward (native control behaviour)
Screen reader: The element renders native `controls`, so all playback affordances come with the browser's built-in accessible names, focus order, and keyboard model. The frame is role=group with an aria-label.
Notes: Keyboard behaviour is the browser's, not re-implemented — which is exactly why native controls are used. Provide captions on the source for video where applicable.
Props
Name
Type
Default
Description
src
string
—
Media source URL.
kind
enum: video | audio
video
poster
string
—
Optional poster image (video only).
label
string
Media player
Accessible label for the player frame.
Examples
Video
A video player frame.
YAML
type: media-player
props:
kind: video
label: Screencast
src: ''
The "what can this element DO" surface. One chip per operation an element exposes, each carrying an intent-coloured status dot (read=grey, create=green, change=amber, delete=red, run=blue), the operation name in mono, and a small method tag. Driven through the shared ViewEngine `ops-intent-strip` arm so the /docs element page and the /components atlas render it identically. Intent is never colour-only: every chip spells out its intent in the accessible name.
Readiness
complete
Preview
live
Props
1
Examples
2
Code
implementation mapped
When to use
Element documentation pages summarising the element's operations
Compact operation overviews where a verb + method is enough
Anywhere the read/create/change/delete/run intent should scan at a glance
When not to use
Full operation reference with parameters — use a definition list or table
A single operation call-to-action — use a button
Operation execution UI — this is a read-only summary, not a runner
Accessibility
Role: list
No keyboard shortcuts
Screen reader: The strip is a list and each chip a list item with an accessible name of "{name} ({intent}): {description}", so intent and purpose are announced without relying on the dot colour. The status dot and method glyphs are hidden from assistive technology.
Notes: Intent is conveyed redundantly — by dot colour, by the data-intent attribute, and in the accessible name — so it is never colour-only.
Props
Name
Type
Default
Description
ops*
array
—
The operations to render, one chip each. Order is preserved (the generator pre-sorts universal, category, then element). An empty list renders nothing.
Examples
Operation intents
Full intent vocabulary across the five verbs.
readGET
createPOST
updatePATCH
deleteDELETE
invokePOST
YAML
type: ops-intent-strip
props:
ops:
- name: read
intent: read
method: GET
description: Fetch the current value.
- name: create
intent: create
method: POST
description: Create a new instance.
- name: update
intent: change
method: PATCH
description: Change an existing instance.
- name: delete
intent: delete
method: DELETE
description: Remove the instance.
- name: invoke
intent: run
method: POST
description: Run the element with input.
Action operations
A typical action element's operation summary.
invokePOST
readGET
YAML
type: ops-intent-strip
props:
ops:
- name: invoke
intent: run
method: POST
description: Run the function and return its result.
- name: read
intent: read
method: GET
description: Read the function definition.
An element's declared ports rendered as two legible columns — Inputs on the left, Outputs on the right — separated by a small central element glyph. Each port is a pill with a direction caret, the port name in mono, the port type as a small tag, and a required marker. Deliberately a flex 2-column layout, not an SVG wiring diagram: SVG edge-routing is fragile to emit from generated code and unreadable in SSR, while the two columns carry the same information robustly. Driven through the shared ViewEngine `port-diagram` arm for /docs ↔ /components parity.
Readiness
complete
Preview
live
Props
1
Examples
2
Code
implementation mapped
When to use
Element documentation showing what an element consumes and produces
Compact port overviews where direction + type + required is enough
Any element with a meaningful input/output port contract
When not to use
Full port schemas with nested fields — use a schema view or table
Live wiring between concrete instances — this is a static type-level view
Elements with no ports — the component renders nothing
Accessibility
Role: list
No keyboard shortcuts
Screen reader: Each column is a labelled list headed by "Inputs" or "Outputs" (shown only for the non-empty side). Each port's accessible name spells out "{direction} {name} ({port_type}), required: {description}" so direction and requiredness are announced without relying on the caret or the asterisk glyph, both of which are hidden from assistive technology.
Notes: Direction is conveyed redundantly by column, by the data-direction attribute, and in the accessible name — never by the caret glyph alone.
Props
Name
Type
Default
Description
ports*
array
—
The ports to render, split into the Inputs / Outputs columns by direction. An empty list renders nothing.
Examples
Request and response ports
A request/response element with required and optional ports.
Inputs
▸coderequest*
▸inputjson
◆
Outputs
resultresponse▸
errorerror▸
YAML
type: port-diagram
props:
ports:
- name: code
direction: input
port_type: request
required: true
description: Source code to execute.
- name: input
direction: input
port_type: json
required: false
description: Optional structured input payload.
- name: result
direction: output
port_type: response
required: false
description: Execution result and stdout.
- name: error
direction: output
port_type: error
required: false
description: Error detail when the run fails.
Inputs only
An input-only trigger element (outputs column stays header-less).
A QR code rendered as inline SVG computed in Rust — SSR-safe, no runtime QR library. Encodes `data` at `size` px with token-driven `colors`, a `style` (rounded/square modules), and an optional centre Triform logo. On an encoding failure it renders a calm `role=alert` error block, not a broken image.
Readiness
complete
Preview
live
Props
5
Examples
2
Code
implementation mapped
When to use
Pairing / sign-in / wallet-auth flows that hand off to a phone (scan to continue).
Any URL or token a user should scan rather than type.
SSR pages needing a QR without shipping a client QR library.
When not to use
Encoding large payloads — QR density makes big data unscannable; link to it instead.
A decorative graphic — QR is functional; don't use it as ornament.
Dynamic data that changes faster than a user can scan.
Accessibility
Role: img
No keyboard shortcuts
Screen reader: `aria_label` MUST describe what the QR encodes and the non-scan path ("QR code for sign-in URL — or open triform.dev/auth on this device"). A QR is unusable by a screen-reader user on the same device; always provide the underlying link/code in text too.
Notes: Never make a QR the ONLY path through a flow — pair with the raw URL/code so non-scanning and SR users can proceed.
Props
Name
Type
Default
Description
data
string
—
The string to encode (URL, token). Required. Keep it short to stay scannable.
size
integer
256
Width = height in px.
style
enum: rounded | square
rounded
Module shape.
with_logo
boolean
true
Show the Triform logo in the centre (uses error-correction headroom).
aria_label
string
—
SR text describing what the QR encodes + the non-scan path.
Examples
Sign-in QR
Sign-in QR paired with the raw URL (never QR-only).
▣ [QR]Scan to sign in, or open triform.dev/auth?s=abc123
YAML
type: stack
props:
direction: column
gap: sm
children:
- type: text
slots:
default: ▣ [QR]
- type: text
slots:
default: Scan to sign in, or open triform.dev/auth?s=abc123
QR error fallback
Encoding-failure fallback — calm error block, not a broken image.
QR Error: payload too large
YAML
type: stack
props:
direction: row
gap: sm
children:
- type: icon
props:
name: error_outline
- type: text
slots:
default: 'QR Error: payload too large'
A tiny inline trend line for dashboard headline tiles and category cards — ~30 points in ~160×32, no axes, no labels, no legend. It answers "is this going up or down right now?" at a glance; detail belongs in the drill view. Pure SVG `<polyline>` computed in Rust (SSR-safe, zero runtime JS). `trend` (Up/Down/Neutral) sets the stroke colour; empty/constant data draws a flat midline so the tile never visually collapses.
Readiness
complete
Preview
live
Props
5
Examples
2
Code
implementation mapped
When to use
An at-a-glance trend beside a KPI number (emails sent last 24h, error rate).
Category cards where direction matters more than exact values.
Any SSR tile that needs a trend without a chart library.
When not to use
A readable chart with axes/values — use a full chart component in the drill view.
A single ratio — use `<Gauge>`.
A categorical split — use `<DonutChart>`.
Accessibility
Role: img
No keyboard shortcuts
Screen reader: The SVG is decorative; pair with an `aria_label` describing the trend in words ("Emails sent, last 24 hours, trending up"). The line shape alone is meaningless to a screen-reader user.
Notes: `trend` colour reinforces direction for sighted users; the aria_label is what carries it for everyone else. Leave `trend: neutral` to auto-infer from first-vs-last.
Props
Name
Type
Default
Description
values
array
—
Data points, left-to-right chronologically. ≤60 render cleanly; more are valid but visually dense. Reactive. Required.
trend
enum: neutral | up | down
neutral
Stroke-colour direction hint. `neutral` (default) auto-infers from first-vs-last value.
width
integer
160
Render box width in px.
height
integer
32
Render box height in px.
aria_label
string
—
SR description of the trend ("CPU last 24h, trending up").
Examples
KPI with up-trend
Up-trend sparkline beside a KPI number — the canonical tile shape.
A tokenised tabular surface for dense comparison or reference data where columns and rows carry meaning. It keeps native <table> / <th scope> semantics so assistive tech and the platform stay in agreement. Interactive product tables (sort, select, paginate) layer those behaviours on top — this primitive is the read-only base.
Readiness
complete
Preview
live
Props
3
Examples
3
Code
implementation mapped
When to use
Reference matrices and generated property tables
Dense operational data with clear columns
Read-only markdown tables that need horizontal overflow
When not to use
Small key/value summaries — use DefinitionList or DataRow
Card collections where cross-column comparison isn't needed
Virtualised datasets — out of scope here
Accessibility
Role: table
No keyboard shortcuts
Screen reader: Native <table> with <thead>, <th scope=col> and an optional <caption> — assistive tech announces it as a real data table with column headers. No bespoke grid keyboard model is layered on (a static table doesn't need one and faking it would mislead).
Notes: `aria-sort` is intentionally absent because this primitive does not sort — adding it without real sorting would be a false signal.
A small read-only rectangular label for an arbitrary label with no semantic meaning — a language ("rust"), a version ("v1.2"), a topic keyword. Tag deliberately has no tone ladder: that is Badge's job (status). Clicking a Tag does nothing; for an interactive filter use FilterChip.
Readiness
complete
Preview
live
Props
1
Examples
3
Code
implementation mapped
When to use
Free-form keyword / topic labels on a card or row
Version or language markers
Any non-semantic, non-interactive label
When not to use
Semantic status (Active/Failed/…) — use Badge
An interactive filter toggle — use FilterChip
A numeric counter on a rail item — use CounterPill
Accessibility
Role: presentation
No keyboard shortcuts
Screen reader: Reads its text content. Tag is decorative chrome around a label; keep the label itself meaningful (don't rely on adjacency).
Notes: Tag carries no colour-coded meaning, so there is no colour-only information to mitigate — it is intentionally tone-neutral.
Props
Name
Type
Default
Description
class
string
—
Extra classes appended after the base tag class.
Examples
Keywords
Keyword tags on a project card.
rustleptoswasm
YAML
type: stack
props:
gap: xs
direction: row
align: center
children:
- type: tag
slots:
default: rust
- type: tag
slots:
default: leptos
- type: tag
slots:
default: wasm
Version
A single version marker.
v1.2.0
YAML
type: tag
slots:
default: v1.2.0
Topics
A row of topic tags.
dataioagents
YAML
type: stack
props:
gap: xs
direction: row
align: center
children:
- type: tag
slots:
default: data
- type: tag
slots:
default: io
- type: tag
slots:
default: agents
Shows a sequence of versions, commits, activities, or audit events in a narrow panel without turning each event into a tall card. Rows keep the version/date, message, and action in predictable columns so long histories stay scannable.
Readiness
complete
Preview
live
Props
2
Examples
1
Code
implementation mapped
When to use
Version history inside the props panel.
Short audit trails where each row has one primary action.
Activity streams that need dense scanning more than editorial layout.
When not to use
Narrative feeds with rich media or long comments.
Tables with many sortable columns.
Accessibility
Role: list
Tab — Moves through row actions in document order.
Enter — Activates the focused row action.
Screen reader: N/A
Notes: Rows render as an ordered list. Keep row actions short and focused so keyboard users can move through the history without card-level noise.
Props
Name
Type
Default
Description
items
array
—
The timestamped events, newest-first. Each row keeps version/title, timestamp, body, and one primary action in predictable columns. Required.
density
enum: compact | comfortable
compact
Row spacing. `compact` (default) for narrow props panels; `comfortable` when the timeline has room.
Render a nested hierarchy as an indented, semantically-structured list. This is the read-only *display* shape — a file tree snapshot, element nesting, an org chart. An interactive expand/collapse tree is intentionally out of scope (compose with Disclosure); claiming interactivity without implementing roving focus would be a false accessibility promise.
Readiness
complete
Preview
live
Props
1
Examples
3
Code
implementation mapped
When to use
A static file / directory tree snapshot
Element or component nesting visualisation
Any read-only parent → child hierarchy
When not to use
An interactive expand/collapse navigator — compose with Disclosure
A flat list — use a list / Table
Breadcrumb-style single-path navigation — use Breadcrumb
Accessibility
Role: tree
No keyboard shortcuts
Screen reader: Emits role=tree on the root, role=treeitem per node, and role=group on each nested level so assistive tech announces depth and parent / child relationships. It is non-interactive by contract, so there is no focus management to get wrong.
Notes: Indentation is paired with the group/treeitem roles, so depth is conveyed structurally — not by visual indentation alone.
Documents the reusable visual contract for automation workflow building. Every element's input/output ports come from generated element YAML; the portal renders the primary input at the north vertex, primary output at the south vertex, fans multiple ports across the adjacent vertices, filters compatible targets with the generated port compatibility matrix, and exposes a Playwright-readable topology mirror for end-to-end workflow construction.
Readiness
complete
Preview
live
Props
1
Examples
2
Code
implementation mapped
When to use
Explaining or testing automation workflow port placement.
Designing a canvas interaction that must reuse generated port metadata.
Writing Playwright tests that drive workflow wiring through the visual canvas.
When not to use
Element-library search cards; use library-element-card.
Generic graph diagrams without generated Triform element ports.
Persisted workflow data models; use the automation build-flow op and _flow response.
Accessibility
Role: img
No keyboard shortcuts
Screen reader: The live canvas exposes ports through the workflow-port selector and a workflow-topology-json mirror. The visible wire/port marks are decorative; the generated metadata attributes carry the port name, direction, type, schema hash, and compatibility state for tests and assistive surfaces.
Notes: Boundary flow-in and flow-out nodes are derived visuals only. They are never serialized as edge endpoints.
Props
Name
Type
Default
Description
mode
enum: rest | expanded | focused | connected
rest
Documentation-only state marker for the specimen.
Examples
North input / south output
Rest-state contract: a step's main input is north and its main output is south.
Workflow port contract
Generated per element type; reused by canvas, library, tests
flow inflow out
text
primary input -> N
primary output -> S
extra inputs -> NE, NW
extra outputs -> SE, SW
YAML
type: card
props:
title: Workflow port contract
subtitle: Generated per element type; reused by canvas, library, tests
style: flat
padding: relaxed
slots:
default:
- type: stack
props:
direction: row
gap: md
align: center
children:
- type: badge
props:
variant: muted
slots:
default: flow in
- type: element-hexagon
props:
kind: automation
symbol: Au
name: Trigger
category: apps
icon_name: play_arrow
icon_color: '#7C3AED'
form: compound
state: active
- type: element-hexagon
props:
kind: python
symbol: Py
name: Transform
category: actions
icon_name: code
icon_color: '#2563EB'
form: atom
state: pulse
- type: badge
props:
variant: muted
slots:
default: flow out
- type: well
props:
padding: cozy
slots:
default:
- type: code-block
props:
language: text
code: |
primary input -> N
primary output -> S
extra inputs -> NE, NW
extra outputs -> SE, SW
Test surface
Playwright-facing assertions for a visually built workflow.
Automation builder selectors
Canvas2D stays canonical; DOM mirrors expose coordinates and graph state
A small read-only card summarising one agent-terminal session: which agent (claude-code / open-code / codex / generic), its title, status, session id, and last-active time. Per-agent accent colour and command label are derived from `element_type`; an explicit `accent` / `icon_name` overrides.
Readiness
incomplete
Preview
live
Props
7
Examples
3
Code
implementation unmapped
When to use
A grid or rail of recent agent-terminal sessions
A compact session affordance the user can click to open the full terminal
A dashboard summary of active agent runs
When not to use
The live, interactive terminal itself — that is the terminal panel
A generic status chip with no terminal/session context — use a badge
Accessibility
Role:
No keyboard shortcuts
Screen reader: Renders a static <article> with the title, agent label, and last-active line in document order. It is presentational; when used as a click target, wrap it in a real button/link so it is keyboard-operable.
Notes: The card itself carries no interactive semantics — the parent is responsible for making it actionable and labelled if it opens a session.
The base inline text node the ViewEngine renders. `kind` selects a semantic tone class (heading, muted, error) and otherwise renders plain body text. Content comes from either the `value` prop (reactive) or the default slot.
Readiness
incomplete
Preview
live
Props
2
Examples
3
Code
implementation unmapped
When to use
Any inline label, caption, or run of text inside an engine-rendered spec
A muted secondary line (`kind: muted`)
An inline error message (`kind: error`)
A lightweight heading inside a composed component (`kind: heading`)
When not to use
Rich/long-form prose with markdown — use markdown-view
A standalone page heading with semantic level — use page-header
Interactive text that triggers an action — use link-button
Accessibility
Role:
No keyboard shortcuts
Screen reader: Renders a plain inline <span>; the text content is read in document order. `kind` is purely presentational (a tone class) and adds no ARIA semantics, so use a heading or page-header component when structural heading semantics are required.
Notes: `kind: error` is a visual tone only — pair it with the field's aria-describedby wiring when announcing a validation error.
Props
Name
Type
Default
Description
kind
enum: body | heading | muted | error
body
value
string
—
Reactive inline text. Rendered before the default slot. Use this for a single bound string; use the default slot for composed children.
Examples
Muted caption
A muted secondary caption line.
Run success rate
YAML
type: text
props:
kind: muted
value: Run success rate
Error text
An inline error message.
Circle name is already taken
YAML
type: text
props:
kind: error
value: Circle name is already taken
Heading + body
Heading and body composed in a column.
Storage88 / 100 GB used
YAML
type: stack
props:
direction: column
gap: sm
children:
- type: text
props:
kind: heading
value: Storage
- type: text
props:
kind: muted
value: 88 / 100 GB used