Components reference

All 24 semantic components: props, when to use them, accessibility, rendering rules and platform mappings.

Generated from packages/spec/components/*.json, the same source the schema, validator and renderer use. Every component also accepts id, component, key, accessibility and visible.

ComponentWebiOSAndroid
Cardshadcn Card (CardHeader/CardTitle/CardContent/CardFooter)GroupBox, or a Button/NavigationLink with card styling in listsCard / ElevatedCard / OutlinedCard (onClick variant when actionable)
Disclosureshadcn Collapsible (or Accordion for several)DisclosureGroupExpandable ListItem / AnimatedVisibility with a toggle row
Group<div role=group> with flex/grid and semantic spacing tokensVStack / HStack / Grid (ViewThatFits for inline)Column / Row / FlowRow
Section<section> + heading; shadcn has no Section primitive (plain markup with semantic tokens)Section(header:) inside List/Form, or VStack with .accessibilityAddTraits(.isHeader) on the titleColumn with a Text heading marked Modifier.semantics { heading() }
Viewsshadcn TabsPicker(.segmented) switching content, or TabView for top-levelPrimaryTabRow + content
Chartshadcn Chart (Recharts)Swift Charts (Chart)Third-party (e.g. Vico) or Canvas; no built-in M3 chart
CollectionList markup with Card or row template; ScrollArea for long listsList + ForEachLazyColumn + items
DetailList<dl> with semantic tokensLabeledContent rows in a Form/List sectionListItem(headlineContent, trailingContent) rows
Media<img> / shadcn AspectRatioAsyncImageAsyncImage (Coil) / Image
MetricCard-like block with semantic tokens (no dedicated shadcn primitive)LabeledContent or a VStack; Gauge for bounded valuesColumn with Text styles
Tableshadcn Table (optionally Data Table with TanStack)Table on regular width; List of rows on compact widthLazyColumn of rows with a header row (no built-in M3 table)
Text<p> with type tokensTextText
Statusshadcn Alert / Skeleton / Sonner toastContentUnavailableView / ProgressView / inline LabelSnackbar / Card with status color / CircularProgressIndicator
Choiceshadcn ToggleGroup / RadioGroup / Select / Combobox (Command + Popover) / CheckboxPicker (.segmented / .inline / .menu) or multi-select ListSegmentedButton / RadioButton rows / ExposedDropdownMenuBox / Checkbox rows
DateInputshadcn Calendar + Popover (Date Picker)DatePickerDatePicker / DateRangePicker
Formshadcn Form (react-hook-form + zod)FormColumn of fields + Button (no Form primitive)
RangeInputshadcn SliderSliderSlider
TextInputshadcn Input / Textarea with Label and FormMessageTextField / TextEditor with .keyboardType and .textContentTypeOutlinedTextField with KeyboardOptions
Toggleshadcn Switch / CheckboxToggleSwitch / Checkbox
Actionshadcn Button (default / secondary / ghost / destructive)Button with .borderedProminent / .bordered / .borderless; role: .destructiveButton / FilledTonalButton / OutlinedButton / TextButton
ActionBarFlex row of shadcn Buttons (DialogFooter-style).toolbar or .safeAreaInset(edge: .bottom)BottomAppBar or Row of Buttons
Comparisonshadcn Table or Cards gridGrid / Table on regular width; List of GroupBox on compactLazyRow of Cards or Column of Cards
Confirmshadcn AlertDialog.confirmationDialog / .alert with role: .destructiveAlertDialog
StepsProgress + step content (no shadcn stepper primitive)NavigationStack pushes or a paged view with a ProgressViewCustom stepper Row + content; LinearProgressIndicator

Cardstructure

One self-contained entity (an account, an order, a place), optionally actionable as a whole.

PropTypeNotes
title requiredtext or bindingName of the entity
subtitletext or binding
mediacomponent idOptional Media component id
badgeobject
childrencomponent ids
actionactionActivating the card as a whole (e.g. open details)

Use when

  • Items in a Collection that each represent an entity
  • A single entity summary in a larger surface

Don't use when

  • Plain grouping: use Group
  • Tabular data with many attributes: use Table

Accessibility article (or link/button when it has an action)

  • Title is the accessible name
  • When actionable, the whole card is one target; nested actions are not allowed then

Agents: Activate the card by its title.

Rendering rules

  • If 'action' is set, children must not contain Actions (one target per card)
  • Uses surface.raised and radius.default

A2UI: Card

Disclosurestructure

Progressive disclosure: secondary content hidden behind a toggle.

PropTypeNotes
summary requiredtext or bindingAlways-visible label describing what is hidden
children requiredcomponent ids
openboolean

Use when

  • Details most people don't need (fees breakdown, advanced options, help text)

Don't use when

  • Content everyone needs to complete the task
  • Primary navigation

Accessibility button (aria-expanded) + region

  • Summary is a button with expanded state
  • Hidden content is not in the tab order while closed

Agents: Expand by the summary text; state is exposed as expanded/collapsed.

Rendering rules

  • Never hide required inputs or the primary action inside a closed Disclosure

A2UI: No direct equivalent; exports as Column (content always shown)

Groupstructure

Visually groups closely related items without a heading (proximity).

PropTypeNotes
children requiredcomponent ids
labeltext or bindingAccessible name for the group when it isn't obvious from its content
arrangement"auto" | "inline" | "grid"Hint only. 'inline' for a few short peers (e.g. metrics); renderers stack on narrow screens.

Use when

  • A few items that belong together (a key figure and its caption, several metrics)

Don't use when

  • The group needs a heading: use Section
  • Choosing between items: use Choice or Comparison

Accessibility group

  • Has an accessible name when it contains interactive items

Agents: Treated as one unit when its label is present.

Rendering rules

  • 'inline' collapses to a stack below the compact breakpoint
  • Gap uses space.stack.default or space.inline.default

A2UI: Column or Row

Sectionstructure

A titled region of the surface that groups related content under a heading.

PropTypeNotes
title requiredtext or bindingHeading for the section
descriptiontext or bindingOptional one-line explanation under the heading
children requiredcomponent ids

Use when

  • The surface has two or more distinct topics (e.g. 'Recipient' and 'Amount')
  • Content would otherwise exceed one screen and needs signposting

Don't use when

  • Only one topic: put content directly under the root
  • Visual grouping without a heading: use Group

Accessibility region (with heading)

  • Title is rendered as a real heading; nesting depth sets the heading level
  • Title is the region's accessible name

Agents: Navigate by heading; the title names the region.

Rendering rules

  • Heading level follows nesting depth, never chosen by the model
  • Spacing between sections uses space.stack.section

A2UI: No direct equivalent; exports as Column with a Text(variant: h2) first child

Viewsstructure

Switch between alternative views of the same subject (tabs).

PropTypeNotes
views requiredlist of objects
selectedbindingKey of the selected view in host data

Use when

  • 2–6 peer views of the same data (Overview / Transactions / Settings)

Don't use when

  • Sequential steps: use Steps
  • Filtering one list: use Choice

Accessibility tablist / tab / tabpanel

  • Each tab has a visible label
  • Arrow keys move between tabs

Agents: Select a view by its label.

Rendering rules

  • More than 4 views on compact screens become a menu or scrollable tabs

A2UI: Tabs

Chartcontent

A visual summary of data, always paired with a text summary.

PropTypeNotes
intent required"trend" | "comparison" | "composition" | "distribution"What the chart should communicate; the renderer picks the chart type
data requiredbindingArray of data points in host data
title requiredtext or binding
summary requiredtext or bindingText alternative stating the takeaway (required)
x requiredobject
series requiredlist of objects

Use when

  • A trend, comparison, share or spread matters more than exact values

Don't use when

  • Exact values matter most: use Table or Metric
  • A single number: use Metric

Accessibility img (figure) with the summary as description, plus a data-table alternative

  • 'summary' states the takeaway in words
  • Series are distinguishable without color (labels, markers)
  • The underlying data is available as a table

Agents: Reads the summary, and the data through the table alternative.

Rendering rules

  • trend → line, comparison → bar, composition → stacked bar (pie only for ≤ 4 parts), distribution → histogram
  • Series colors use color.data.categorical.N in order

A2UI: No equivalent in the Basic catalog; exports as Text(summary) + List

Collectioncontent

A list of items from host data, each rendered with the same template.

PropTypeNotes
items required{ path, componentId }
label requiredtext or bindingWhat the list contains, e.g. 'Recent payments'
emptycomponent idStatus component shown when there are no items
selection"none" | "single" | "multiple"
selectedbindingSelected item value(s) in host data when selection is not 'none'

Use when

  • Browsing a set of similar entities
  • Search results

Don't use when

  • Attributes compared across items: use Table or Comparison
  • Choosing an option in a form: use Choice

Accessibility list / listitem (listbox when selectable)

  • Announces the item count
  • An empty state is provided

Agents: Items are enumerated with their titles; each item exposes its own actions.

Rendering rules

  • Long lists are virtualized by the renderer
  • Items keep their order from host data

A2UI: List (templated children)

DetailListcontent

Label/value pairs describing one thing (a summary, a receipt, a review step).

PropTypeNotes
items requiredlist of objects
titletext or binding

Use when

  • Reviewing before submitting
  • Showing the attributes of one entity
  • Receipts

Don't use when

  • Many entities with the same attributes: use Table
  • Comparing entities: use Comparison

Accessibility list of term/definition pairs (dl)

  • Label and value are programmatically associated

Agents: Read each label with its value.

Rendering rules

  • Keeps the item order stable across generations (keys are remembered)

A2UI: Column of Row(Text, Text)

Mediacontent

An image supplied by the host.

PropTypeNotes
src requiredbindingImage reference in host data; generated UI never contains URLs
alttext or bindingRequired unless decorative
decorativeboolean
aspect"square" | "landscape" | "portrait" | "auto"

Use when

  • Photos or illustrations that help identify something (a product, a place, a person)

Don't use when

  • Decoration with no information
  • Icons for actions (renderer supplies those)

Accessibility img

  • Has alt text unless decorative (then hidden from assistive technology)

Agents: Reads the alt text.

Rendering rules

  • Images never convey information that is not also in text

A2UI: Image

Metriccontent

A key figure with a label, and optionally its change.

PropTypeNotes
label requiredtext or binding
value requiredbindingAlways bound to host data
formatformat
changeobject
captiontext or binding

Use when

  • One to four headline numbers the user asked about

Don't use when

  • Many numbers: use Table or DetailList
  • Trends over time: use Chart

Accessibility group (label + value)

  • Change direction is conveyed in text as well as color
  • Screen readers read label, value and change as one sentence

Agents: Read label and value.

Rendering rules

  • Value uses type.numeric.display
  • Change uses color.data.positive / negative according to 'favorable'

A2UI: Column of Text

Tablecontent

Tabular data: many items sharing the same attributes.

PropTypeNotes
rows requiredbindingArray of row objects in host data
caption requiredtext or bindingWhat the table shows (required for accessibility)
columns requiredlist of objects
rowActionactionActivated per row; context bindings resolve against the row
emptycomponent idStatus component shown when there are no rows

Use when

  • Scanning or comparing many rows by several attributes

Don't use when

  • One entity: use DetailList
  • A few entities where the user must choose: use Comparison

Accessibility table with caption and column headers

  • Has a caption
  • Column headers are real header cells
  • Numeric columns are right-aligned by format

Agents: Read by row and column headers; rows with rowAction are activatable.

Rendering rules

  • On compact screens, rows become stacked cards with label/value pairs
  • Alignment follows the column format, never chosen by the model

A2UI: No direct equivalent; exports as List of Row

Textcontent

A run of text.

PropTypeNotes
text requiredtext or binding
variant"body" | "supporting" | "caption"
formatformatOnly when 'text' is bound to a non-string value

Use when

  • Explanations, instructions, messages

Don't use when

  • Headings: use Section title
  • Label/value pairs: use DetailList
  • Key figures: use Metric

Accessibility text

  • Body text is at least 16px (type.body.default)
  • Line length is capped by measure.max

Agents: Read as text.

Rendering rules

  • 'supporting' uses color.text.muted
  • No inline styling; emphasis comes from structure

A2UI: Text

Statusfeedback

Feedback about state: info, success, warning, error, empty or loading.

PropTypeNotes
kind required"info" | "success" | "warning" | "error" | "empty" | "loading"
title requiredtext or binding
messagetext or binding
actioncomponent idOptional Action to recover or continue (e.g. 'Try again')

Use when

  • Results of an action
  • Empty collections
  • Errors with a way to recover
  • Loading states

Don't use when

  • Validation errors on a field: inputs show their own errors
  • Confirmation before acting: use Confirm

Accessibility status or alert (live region)

  • success/info/loading are polite live regions; error is assertive
  • Meaning is in text, not only color or icon

Agents: Reads the title and message; the recovery action is exposed.

Rendering rules

  • error and warning use color.status.* tokens and an icon
  • empty states explain why and what to do next
  • loading shows a skeleton when layout is known, otherwise a progress indicator

A2UI: Text + Icon

Choiceinput

Pick one or several options from a known set. The renderer chooses the control.

PropTypeNotes
label requiredtext or binding
options requiredoptions (list or from data)
value requiredbindingTwo-way binding into host data
mode"single" | "multiple"
helptext or binding
requiredboolean

Use when

  • Any choice from a known set of options

Don't use when

  • On/off setting: use Toggle
  • Picking between rich entities by comparing attributes: use Comparison

Accessibility radiogroup / group of checkboxes / listbox / combobox (depends on rendering)

  • Visible group label
  • Every option has a text label

Agents: Select options by label.

Rendering rules

  • single, 2–4 short options → segmented control or radios
  • single, 5–10 → radios (or select on compact screens)
  • single, > 10 → searchable select
  • multiple, ≤ 10 → checkboxes; > 10 → searchable multi-select
  • Option order comes from host data or remembers the last order used

A2UI: ChoicePicker

DateInputinput

A date, time, date-time or date range.

PropTypeNotes
label requiredtext or binding
value requiredbindingISO 8601 value(s) in host data
kind"date" | "time" | "datetime" | "dateRange"
mintext or binding
maxtext or binding
helptext or binding
requiredboolean

Use when

  • Any date or time entry

Don't use when

  • Relative choices like 'This month / Last month': use Choice

Accessibility group of spinbuttons or a date picker dialog

  • Typing the date is always possible, not only picking from a calendar

Agents: Fill by label with an ISO date.

Rendering rules

  • Memorable dates (birthdays) use separate day/month/year fields; near dates use a calendar

A2UI: DateTimeInput

Forminput

Collects inputs and submits them together.

PropTypeNotes
children requiredcomponent ids
submit required{ label, action }
cancel{ label, action }Optional; defaults to ui.dismiss when omitted and the surface is dismissible

Use when

  • Any set of inputs that are submitted together

Don't use when

  • Settings that apply immediately: use Toggles with actions
  • Several distinct stages: use Steps

Accessibility form

  • Submit is a real submit button
  • On submit errors, focus moves to an error summary that links to each field

Agents: Fill fields by label, then activate the submit button by its label.

Rendering rules

  • One column; labels above fields
  • Submit is the primary action; cancel is secondary
  • Submit context is built from the form's input bindings

A2UI: Column + Button

RangeInputinput

A number within known bounds where the exact value matters less than its position.

PropTypeNotes
label requiredtext or binding
value requiredbindingNumber in host data
min requirednumber
max requirednumber
stepnumber
formatformat

Use when

  • Approximate values within a range (budget cap, volume)

Don't use when

  • Exact values: use TextInput with kind 'number' or 'currency'

Accessibility slider

  • Current value is shown as text
  • Keyboard arrows change the value by step

Agents: Set the value directly by label.

Rendering rules

  • Shows min, max and the current formatted value

A2UI: Slider

TextInputinput

A single text-like value: text, number, email, phone, currency, search or long text.

PropTypeNotes
label requiredtext or binding
value requiredbindingTwo-way binding into host data
kind"text" | "multiline" | "number" | "currency" | "email" | "phone" | "url" | "search"
currencytext or bindingISO 4217 code when kind is 'currency'
helptext or bindingHint shown below the label (not a placeholder)
requiredboolean
validationobject
autocompletestringHTML autocomplete token hint (e.g. 'email', 'postal-code')

Use when

  • Free-form values the user types

Don't use when

  • A value from a known set: use Choice
  • Dates: use DateInput
  • Secrets (passwords, card numbers): not generated; hosts provide their own secure flows

Accessibility textbox / searchbox / spinbutton

  • Visible label, never placeholder-only
  • Help and errors are associated with the field
  • Kind sets the right keyboard and autocomplete

Agents: Fill by label.

Rendering rules

  • Width suggests expected length
  • Errors appear after the user leaves the field or submits, not while typing

A2UI: TextField

Toggleinput

An on/off setting.

PropTypeNotes
label requiredtext or binding
value requiredbindingBoolean in host data
descriptiontext or binding
actionactionSet when the change applies immediately (a setting); omit inside a Form

Use when

  • Settings that take effect immediately
  • A single yes/no inside a form

Don't use when

  • Choosing between named options: use Choice

Accessibility switch (immediate) / checkbox (in a form)

  • Label says what 'on' means

Agents: Toggle by label; state is exposed as on/off.

Rendering rules

  • With 'action' it renders as a switch; inside a Form without action, as a checkbox

A2UI: CheckBox

Actionaction

A button that triggers a host capability.

PropTypeNotes
label requiredtext or bindingVerb-first label saying what happens ('Send £20', not 'OK')
action requiredaction
emphasis"primary" | "secondary" | "tertiary"
tone"default" | "danger"
disabledboolean or binding

Use when

  • Anything the user can do that isn't typing or choosing

Don't use when

  • Navigating between views: use Views
  • Confirming something destructive: wrap in Confirm

Accessibility button

  • Label describes the outcome
  • Target at least size.target.min
  • Disabled actions explain why nearby

Agents: Activate by label.

Rendering rules

  • At most one primary action visible at a time
  • danger tone uses color.action.danger.*

A2UI: Button

ActionBaraction

The set of actions for a surface or section; the renderer places it where that platform expects.

PropTypeNotes
children requiredcomponent idsAction component ids, in order of importance

Use when

  • Two or more actions that apply to the whole surface or section

Don't use when

  • A single action inline with content: use Action directly

Accessibility toolbar / group

  • Order in the accessibility tree is order of importance

Agents: Actions are listed together.

Rendering rules

  • Web: bottom of the section, primary last on desktop and first on mobile stacks
  • iOS/Android: toolbar or bottom bar on compact screens

A2UI: Row of Button

Comparisonflow

Compare a few options across the same attributes, and choose one.

PropTypeNotes
items requiredbindingArray of options in host data (2–4 recommended)
itemTitle requiredJSON PointerRelative path to each item's name
attributes requiredlist of objects
choose{ label, action }Action per item; context bindings resolve against the item
recommendedtext or bindingOptional value of the recommended item's title, with a reason in 'summary'
summarytext or binding

Use when

  • Choosing between 2–4 plans, products, routes or offers

Don't use when

  • More than ~5 items: use Table with sorting
  • No decision needed: use Table

Accessibility table (items as columns on wide screens) or list of cards

  • Attribute names are headers
  • 'better' is conveyed in text, not only color

Agents: Reads attributes per item; choose actions are named with the item title.

Rendering rules

  • Wide: items as columns; compact: one card per item with the same attribute order
  • Best values per attribute are marked when 'better' is set

A2UI: No direct equivalent; exports as List of Card

Confirmflow

Asks the user to confirm a consequential or destructive action, showing what will happen.

PropTypeNotes
title requiredtext or bindingQuestion naming the action ('Send £250 to Alex?')
messagetext or binding
consequencetext or bindingWhat happens and whether it can be undone
summarycomponent idOptional DetailList summarising what is being confirmed
severity required"consequential" | "destructive"
confirm required{ label, action }
cancel{ label, action }Defaults to 'Cancel' → ui.dismiss
typeToConfirmtext or bindingText the user must type before confirming (for irreversible, high-impact actions)

Use when

  • Moving money, deleting data, sending on someone's behalf, anything irreversible

Don't use when

  • Routine reversible actions (prefer undo)
  • Information only: use Status

Accessibility alertdialog

  • Focus starts on the least destructive option
  • Confirm label repeats the action verb
  • Escape cancels

Agents: Reads title and consequence; confirm and cancel are named buttons.

Rendering rules

  • destructive uses color.action.danger.*
  • Capabilities with high risk level must use Confirm (enforced by the verifier)

A2UI: Modal with Text and Buttons

Stepsflow

A task split into ordered steps with visible progress.

PropTypeNotes
steps requiredlist of objects
currentnumber or bindingIndex of the current step (default 0)
finish required{ label, action }

Use when

  • Tasks with dependent stages or too many inputs for one view (checkout, onboarding)

Don't use when

  • Independent views: use Views
  • Under ~6 inputs: a single Form

Accessibility group with step progress (aria-current on the current step)

  • Current step and total are announced
  • Back never loses entered data

Agents: Reads 'step N of M'; next/back are exposed as buttons.

Rendering rules

  • Renderer provides Back (ui.back) and Next (ui.next); the last step shows 'finish'
  • Each step validates before moving on

A2UI: No direct equivalent; exports as Column of the current step

Polyxd is an early preview. Found something unclear? It will get better with your feedback.