Playground

Paste A2UI, see it render

Messages (JSON or JSONL), a flat component list or a nested node, rendered live in any theme. Share it as a link; read the prompt a model gets.

Read as: JSONL messages · 4 messages · 1 surface

Loading the renderer…
No issues

System prompt

~6,191 tokens · 24,762 characters

What catalogPrompt({ extensions, lite, terse }) generates for the current catalog: the rules and every component a model may use.

text
Catalog https://ui.exponential.at/catalogs/core/v1.
Rules:
- Reply with A2UI v0.9 messages: createSurface{surfaceId, catalogId}, then updateComponents{surfaceId, components:[…]}; one component has id "root".
- A component = {id, component, …props, children?: [ids] | {componentId, path, key?}, slots?: {name: id}, on?: {event: action}, style?, visible?}. Children are ids, never inline; {componentId, path} repeats per item, key = the item field naming it.
- Include every required prop. A ~ prop may be a binding {path: "/json/pointer"} or a call {call, args}; bound values stay live. visible: false (or a binding) hides any component.
- Lay out with Stack, Grid, Card, Sidebar and List (anything longer than a screen); Box + style only for the rest. Wrap fields in Form.
- Responsive: a ^ prop also takes {base, sm?, md?, lg?, xl?} (from that breakpoint up). Style conditions, one level, narrow first: "@media (min-width: $breakpoint.md)": {…} (also max-width, min-height, max-height in px or $breakpoint.sm|md|lg|xl; orientation: portrait|landscape; hover: hover|none; prefers-reduced-motion: reduce), then ":hover", ":focus-visible", ":pressed". display: "none" hides.
- Prefer catalog components over Markdown, labels and tones over colours. Built-in copy (Cancel, Search…) is localized: leave it unset.
Components (props marked * are required, ~ accept a binding, ^ are responsive; =x is the default, else an enum defaults to its first value and a boolean to false):
Common props (no description below): name (form key), label, placeholder, disabled, checks (validation; every failure shows), validateOn, style (extra Box style), icon, size, tone, open (bind it), side, emptyText, dismissible, busy, loading, lines (truncate), width (px), height (px), value (bind it for two-way state), title, subtitle, description, meta, count, min, max, step, src, alt, multiple, pressable (fires press), durationMs (known length), firstDayOfWeek (0 = Sunday; else the locale's), direction, orientation, gap, aspectRatio (width/height), text.
Box: A styled container laid out by the whitelisted style object; the primitive every macro expands into.
  children; on: press
  style: style
  pressable: boolean
Stack: A flex container that lays its children out in one direction with a gap.
  children
  direction^: horizontal|vertical="vertical"
  gap^: none|xs|sm|md|lg|xl="md"
  align^: start|center|end|stretch="stretch" — Cross-axis alignment of the children.
  justify^: start|center|end|between|around|evenly — Main-axis distribution of the children.
  wrap^: boolean — Lets children wrap onto new lines.
  style: style
Grid: An equal-column grid for cards and tiles.
  children
  columns^: number=2 — Equal columns 1–6 (`{base: 1, md: 2, lg: 3}`).
  gap^: none|xs|sm|md|lg|xl="md"
  style: style
Card: A bordered content card with an optional title and description; use it for grouped content, not page headers.
  children
  title: string
  description: string
  padded: boolean=true — Pads the body; off for edge-to-edge rows.
  style: style
Separator: A hairline that divides content.
  orientation: horizontal|vertical
List: A windowed scrolling list; required for anything longer than a screen, children may come from a data template.
  children; slots: section
  direction: vertical|horizontal
  gap: none|xs|sm|md|lg|xl
  divided: boolean — Draws a hairline between items.
  sectionBy: string — Groups consecutive template items by this field; slot `section` = each header (scope {value, count}).
  stickyHeaders: boolean — Pins the current section header.
  style: style
Resizable: Panels split by draggable handles; each child is one panel.
  children; on: change
  direction^: horizontal|vertical
  sizes~: [number] — Percent per panel; bind it.
  panels: [panel] — Per-panel limits, by index.
  handle: boolean — Draws a grip on each handle.
  style: style
ScrollArea: A scrolling region of bounded height or width.
  children
  direction: vertical|horizontal|both
  maxHeight: number — Px it scrolls within; omit to fill the parent.
  style: style
Sidebar: A two-column shell: a navigation column (`sidebar` slot) beside the children, hidden below a breakpoint or when `collapsed`; give narrow screens another way in (a `bar` Segmented, or a Drawer from an AppBar button).
  children; slots: sidebar
  side: left|right
  width: number=240
  collapseBelow: never|sm|md|lg|xl="md" — Hides the column below this breakpoint.
  collapsed~: boolean — Hides the column at any width; bind it to a toggle.
AppBar: A top bar with a title, an optional subtitle and back button, and `leading`/`trailing` slots for controls.
  slots: leading, trailing; on: back
  title*~: string
  subtitle~: string
  back: boolean — Shows a back button that fires `back`.
Section: A band header over hairline-divided rows: a title with an optional caption, count and glyph, foldable, tinted; no title = just the rows.
  children; slots: leading, trailing; on: change
  title~: string
  caption: string — Muted text after the title.
  count: number
  icon: icon
  collapsible: boolean — The header folds the rows (chevron, press).
  open~: boolean=true
  tint: neutral|primary|success|warning|danger|info — The band's colour tone.
  tree: boolean — The rows form a tree: each `Row.depth` indents and draws its guides.
  style: style
Group: A form-field container: a rounded group of rows with an optional title and footnote.
  children
  title: string
  footer: string — A muted note under the group.
Text: A run of text in one of the type styles; prefer dedicated components over inline markdown.
  text*~: string
  variant: body|caption|muted|lead|code|label|title — The type style.
  align: start|center|end — Horizontal alignment inside its box.
  lines: number
  tone: neutral|primary|success|warning|danger|info
  live: off|polite|assertive — Announces text changes to screen readers (`assertive` interrupts).
  style: style
Heading: A section or page heading at one of four levels.
  text*~: string
  level: h1|h2|h3|h4="h2" — h1 is the page title, h4 the smallest.
Markdown: Rendered GitHub-flavoured markdown, for prose.
  text*~: markdown
  lines: number
  style: style
CodeBlock: Source code in a mono block with built-in syntax colouring, optional line numbers and a copy button.
  code*~: string — The source text.
  language: plain|json|js|ts|tsx|rust|swift|kotlin|python|bash|html|css|sql|yaml|markdown — The syntax colouring.
  title: string
  lineNumbers: boolean — Shows a line-number gutter.
  wrap: boolean — Wraps long lines instead of scrolling sideways.
  copyable: boolean=true — Shows the copy-to-clipboard button.
  highlight: [number] — 1-based line numbers to emphasise.
  maxLines: number — Lines shown before the block scrolls.
Kbd: A keyboard shortcut drawn as a key cap.
  keys*: string — The shortcut text (`⌘K`, `Ctrl+Shift+P`).
Label: A caption for a control that has no label of its own, with an optional required mark.
  text*~: string
  for: string — The id of the control it labels.
  required: boolean — Adds the required mark.
Image: A picture from a URL, or a placeholder box when it has none.
  src~: url
  alt*: string
  fit: contain|cover|fill|none|scaleDown="cover" — How the picture fills its box.
  width: number
  height: number
  aspectRatio: number
  fallback: icon — An icon shown when the picture fails or is missing.
  loading: lazy|eager
  focalX: number — Horizontal focal point 0..1 kept when cropped (0.5).
  focalY: number — Vertical focal point 0..1 kept when cropped (0.5).
  style: style
Icon: One icon from the shared Lucide registry, by name.
  name*: icon
  size: sm|default|lg="default"
  tone: neutral|primary|success|warning|danger|info
  label: string
Video: An inline video player with native controls.
  src*~: url
  poster: url — A still shown before playback.
  durationMs: number
  autoplay: boolean — Starts muted playback on appear.
  aspectRatio: number=1.7777778
  style: style
AudioPlayer: An inline audio player with a title and native controls.
  src*~: url
  title: string
  durationMs: number
Avatar: A round user picture that falls back to initials on a stable hue.
  name*~: string
  src~: url
  size: sm|default|lg="default"
  seed: string — Hashes the fallback hue; defaults to the name.
Carousel: A horizontally paging scroller; each child is one page.
  children; on: change
  page~: number=0 — The active page index.
  loop: boolean — Wraps from the last page to the first.
  indicators: boolean=true — Shows the page dots.
Tabs: Tab navigation; the child at index i is the panel of tab i.
  children; on: change
  tabs*: [tab] — The tab headers in order.
  value~: string
  fill: boolean — Stretches the headers across the width.
Segmented: ONE row of segments selecting one or many values: the pill-track segmented control, bare toggles, joined outline buttons or a bottom bar of destinations.
  on: change
  items*: [option] — The segments in order.
  type: single|multiple — One active value or several.
  value~: string
  variant: segmented|toggles|outline|bar — The segmented track, bare `toggles`, joined `outline` buttons, or a full-width `bar` with icons over labels.
  size: sm|default|lg="default"
  fill: boolean — Stretches the segments across the width (a `bar` always does).
Accordion: Collapsible sections; the child at index i is the body of item i.
  children; on: change
  items*: [accordionItem] — The section headers in order.
  type: single|multiple — One section open at a time, or any number.
  value~: string
Collapsible: One disclosure section with a title row that shows or hides its children.
  children; on: change
  title*: string
  open~: boolean
  count: number
Pagination: Previous, next and the current page out of a total.
  on: change
  totalPages*: number — How many pages there are.
  page~: number=1 — The current 1-based page; bind it.
Breadcrumb: The path to the current page; every item but the last is a link that fires `select` with its value.
  on: select
  items*: [option] — The path from the root to the current page.
Stepper: Wizard progress: numbered steps, finished ones ticked.
  steps*: [step] — The steps in order.
  current~: number=0 — The 0-based index of the active step.
  orientation: horizontal|vertical
Dialog: A centred modal over the surface, opened by its trigger slot or by binding `open`.
  children; slots: trigger, footer; on: change
  title: string
  description: string
  open~: boolean
  dismissible: boolean=true
Drawer: A panel sliding in from an edge (a bottom sheet on phones).
  children; slots: trigger, footer; on: change
  title: string
  description: string
  open~: boolean
  side^: top|right|bottom|left="bottom"
  dismissible: boolean=true
  dragToDismiss: boolean=true — Lets a swipe toward its edge close it.
AlertDialog: A modal that asks for a confirmation and ignores clicks outside; fires `confirm` or `cancel`.
  children; slots: trigger; on: confirm, cancel, change
  title*: string
  description: string
  confirmLabel: string="$string.confirm" — The confirming button's text.
  cancelLabel: string="$string.cancel" — The cancelling button's text.
  destructive: boolean — Styles the confirming button as dangerous.
  open~: boolean
Popover: A small panel anchored to its trigger, opened on press.
  children; slots: trigger; on: change
  open~: boolean
  side: top|right|bottom|left="bottom"
  openOn: press|hover — Press, or hover over the trigger (press on touch).
Tooltip: A short hint shown on hover or long-press over its children.
  children
  content*: string — The hint text.
  side: top|right|bottom|left
Menu: A menu of actions, checkboxes, groups and one-level submenus: opened by pressing its child (or a default button) or by right-click / long-press on it.
  one child; on: select
  label: string
  icon: icon
  items*: [menuItem] — The entries in order.
  openOn: press|contextmenu — A press on the child, or the context gesture over it.
Toast: A transient notice in the toast layer; render one per notice with `open` bound.
  on: dismiss, action, change
  title*~: string
  description~: string
  type: info|success|warning|error — The severity, picking icon and tone (`error` interrupts screen readers).
  open~: boolean=true
  duration: number=5000 — Ms until it dismisses itself; 0 = never.
  actionLabel: string — A button label; pressing it fires `action`.
  dismissible: boolean=true
Badge: A small count or status label.
  text*~: string
  variant: default|secondary|outline|ghost|destructive|link — Filled, secondary, outlined or destructive.
  icon: icon
Alert: An inline banner with an icon, a title and a message.
  title*: string
  message: string — The detail under the heading.
  type: info|success|warning|error — The severity, which picks the icon and tone.
Chip: A small labelled token: a pill for a filter, label or state, or a rect naming an entity with a glyph or picture, optionally removable.
  slots: leading; on: press, remove
  label*~: string
  shape: pill|rect — A rounded pill or a squarer entity chip.
  selected: boolean — Draws it as the active choice.
  tone: neutral|primary|success|warning|danger|info
  dot: color — A colour dot before the text (a label chip).
  icon: icon
  image: url — A round picture instead of the icon.
  detail: string — Muted text after the label.
  removable: boolean — Shows a remove control that fires `remove`.
  pressable: boolean
EmptyState: A centred icon, title and explanation for an empty list, with an optional action.
  on: press
  icon*: icon
  title*: string
  description: string
  actionLabel: string — A button label; pressing it fires `press`.
Progress: A horizontal progress bar with an optional label.
  value*~: number
  max: number=100
  label: string
  tone: neutral|primary|success|warning|danger|info="primary"
Meter: A usage track: a bar of coloured segments against a maximum, with a caption and a value.
  segments*: [segment] — The slices in order.
  max: number=100
  label: string
  value: string
Ring: A circular progress ring for a fraction, sized like an icon.
  value*~: number
  size: sm|default|lg="default"
  tone: neutral|primary|success|warning|danger|info="primary"
  label: string
Spinner: An indeterminate activity indicator.
  size: sm|default|lg="default"
  label: string
Skeleton: A shimmering placeholder block while content loads.
  width: string
  height: string
  rounded: boolean — A circle instead of a bar.
Table: A data table of typed columns over rows: sorting, row selection, widths, alignment, windowed; a `slot` column renders a component per cell.
  slots: *; on: sort, select, rowPress
  columns*: [column] — The columns in order.
  rows*~: [object] — One object per row keyed by column key; bind it for live data.
  rowKey: string="id" — The row field that identifies a row.
  sort~: sort — The active sort; bound = you order `rows`, unbound = sorted locally.
  selectable: none|single|multiple — Row selection (many = a checkbox column).
  selected~: [string] — The selected row keys; bind them.
  caption: string — A caption under the table.
  emptyText: string="$string.noResults"
  striped: boolean — Alternates row fills.
  density: default|compact — Row height class.
  stickyHeader: boolean — Keeps the header visible while the rows scroll.
Chart: A bar, stacked-bar, line, area, pie, donut or sparkline chart with axes, legend and tooltip, as wide as its box.
  kind*: bar|stackedBar|line|area|pie|donut|sparkline — The chart form.
  categories~: [string] — The x-axis labels, or the pie slices; omit for a sparkline.
  series*~: [series] — One per line, bar group or pie ring; coloured $color.chart1..8 unless toned.
  title: string
  height: number=200
  xLabel: string — A caption under the x axis.
  yLabel: string — A caption beside the y axis.
  min: number
  max: number
  showAxes: boolean=true — Draws the axes with tick labels.
  showGrid: boolean=true — Draws horizontal grid lines at the ticks.
  showLegend: boolean=true — Draws the legend (2+ series or slices).
  showValues: boolean — Writes each value on its bar, point or slice.
Sparkline: A tiny inline trend line of recent values, no axes or legend.
  values*~: [number] — The points, oldest first.
  tone: neutral|primary|success|warning|danger|info="primary"
  height: number=24
Button: A press target with a label and optional icon (or one custom child).
  one child; on: press
  label~: string
  icon: icon
  variant: default|secondary|outline|ghost|destructive|link — `default` = the primary action, `destructive` = dangerous, `ghost`/`link` = quiet.
  size: sm|default|lg|icon="default"
  disabled~: boolean
  loading: boolean
  submit: boolean — Submits the enclosing Form on press.
Link: Inline link text that opens a URL or fires `press`.
  on: press
  label*~: string
  href: url — The URL to open; omit to handle `press` yourself.
  external: boolean — Marks it as leaving the app.
Toggle: A two-state button that stays pressed.
  on: change
  label*: string
  icon: icon
  pressed~: boolean — The state; bind it.
  variant: default|outline — Plain or outlined.
  size: sm|default|lg="default"
Form: Collects its fields by `name` and fires `submit` with their values once every check passes (a `submit` Button or Enter submits).
  children; on: submit, invalid, change
  name*: string
  disabled~: boolean
  busy~: boolean
  summary: boolean — Also lists every failed check above the fields.
Input: A single-line text field.
  on: change, submit, focus, blur
  label*: string
  name*: string
  type: text|email|password|number|search|url|tel — The keyboard and masking kind.
  placeholder: string
  value~: string
  disabled: boolean
  checks: [check]
  validateOn: change|blur|submit="blur"
Textarea: A multi-line text field.
  on: change, focus, blur
  label*: string
  name*: string
  placeholder: string
  rows: number=3 — Visible lines (the minimum when autosizing).
  autosize: boolean — Grows with the text from `rows` up to `maxRows`.
  maxRows: number — Autosize stops growing here and scrolls.
  value~: string
  disabled: boolean
  checks: [check]
  validateOn: change|blur|submit="blur"
NumberField: A numeric field with steppers, min/max/step clamping and locale formatting.
  on: change, submit, focus, blur
  label*: string
  name*: string
  value~: number
  min: number
  max: number
  step: number=1
  precision: number — Decimal places shown; defaults to the step's.
  unit: string — A suffix after the number (`kg`, `%`).
  placeholder: string
  disabled: boolean
  checks: [check]
  validateOn: change|blur|submit="blur"
Checkbox: A labelled checkbox; bind `checked`.
  on: change
  label*~: string
  name*: string
  checked~: boolean — The state; bind it.
  disabled: boolean
  checks: [check]
Radio: A labelled group of radio options choosing one value; bind `value`.
  on: change
  label: string
  name*: string
  options*: [option] — The choices in order.
  value~: string
  orientation: horizontal|vertical="vertical"
  checks: [check]
Switch: A labelled on/off switch; bind `checked`.
  on: change
  label*~: string
  name*: string
  checked~: boolean — The state; bind it.
  description: string
  disabled: boolean
Slider: A range slider between min and max; bind `value`.
  on: change
  label: string
  min: number=0
  max*: number
  step: number=1
  value~: number
Rating: A row of stars scoring out of `max`; `readOnly` only displays.
  on: change
  value~: number=0
  max: number=5
  readOnly: boolean — Display only; no presses.
  size: sm|default|lg="default"
Select: A dropdown picker of one or many options; `searchable` makes it a filtering combobox, `source` a host list.
  on: change, search
  label: string
  name*: string
  options~: [option] — Inline choices, or a path the host refills on `search`; omit with `source`.
  source: string — A host list id (e.g. `exp:statuses`) that supplies the options.
  placeholder: string
  value~: string
  multiple: boolean
  searchable: boolean — Adds a filter field; typing fires `search`.
  emptyText: string="$string.noResults"
  disabled: boolean
  checks: [check]
  validateOn: change|blur|submit
ChipInput: A multi-value field of removable chips (Enter or comma adds); bind `values`.
  on: change, add, remove
  label: string
  name*: string
  values~: [string] — The entries; bind them.
  suggestions~: [option] — Completions offered while typing.
  placeholder: string
  max: number
  disabled: boolean
  checks: [check]
DatePicker: A calendar date field (ISO yyyy-mm-dd).
  on: change
  label: string
  name*: string
  value~: date
  min: date
  max: date
  placeholder: string
  firstDayOfWeek: number
DateRangePicker: A two-date range field with one calendar (ISO dates).
  on: change
  label: string
  name*: string
  start~: date — The first day as yyyy-mm-dd, or empty.
  end~: date — The last day as yyyy-mm-dd, or empty.
  min: date
  max: date
  placeholder: string
  firstDayOfWeek: number
TimePicker: A time-of-day field (`HH:mm`) picked from a list every `step` minutes, or typed.
  on: change
  label: string
  name*: string
  value~: string
  min: string
  max: string
  step: number=15
  placeholder: string
  disabled: boolean
FileUpload: A drop zone with a browse button; files reach the host via `upload`, which lists them back in `files`.
  on: upload, remove
  label: string
  name*: string
  accept: string — Accepted types, comma-separated (`image/*,.pdf`).
  multiple: boolean
  maxSize: number — Max bytes per file; bigger ones are refused.
  files~: [file] — The attached files, each removable.
  hint: string — Text under the drop zone's title.
  disabled: boolean
Composer: The chat input box: a growing text field with a submit button and optional attachments.
  on: submit, change, stop
  placeholder: string
  value~: string
  submitLabel: string="$string.send" — The submit button's accessibility label.
  attachments: boolean — Shows the attach control.
  busy: boolean
Row: THE list row: a lead glyph or slot, a mono identifier, a title with a subtitle, trailing meta or a readable value, a slot and a chevron; flat or a card, nestable by depth.
  slots: leading, trailing; on: press
  title*~: string
  identifier~: string — A mono identifier before the title (`EXP-12`).
  subtitle~: string
  meta~: string
  value~: string
  placeholder: string
  icon: icon
  chevron: none|right|selector — A trailing disclosure (`right`) or picker (`selector`) glyph.
  selected: boolean — Draws it as the active row.
  density: default|compact — Row height class.
  surface: flat|card — A flat row, or a padded card with its own fill and border.
  pressable: boolean
  depth: number=0 — Nesting depth under a tree Section (0 = root); the guides are computed from the rows around it.
Shapes: option = {label*: string, value*: string, icon: icon, disabled: boolean}; check = {condition*: boolean, message*: string}; tab = {label*: string, value*: string, icon: icon, count: number}; menuItem = {label: string, value: string, kind: item|checkbox|separator|label|submenu, icon: icon, shortcut: string, checked: boolean, destructive: boolean, disabled: boolean, items: [menuItem]}; accordionItem = {title*: string, value*: string, count: number}; segment = {value*: number, tone: neutral|primary|success|warning|danger|info, label: string}; series = {name*: string, values*: [number], tone: neutral|primary|success|warning|danger|info}; step = {label*: string, description: string}; column = {key*: string, label*: string, type: text|number|date|boolean|badge|slot|currency|percent|relativeTime, slot: string, width: number, align: start|center|end, sortable: boolean, currency: string, decimals: number}; sort = {key*: string, direction*: asc|desc}; panel = {min: number, max: number, collapsible: boolean}; file = {name*: string, size: number, type: string, url: url}
Functions (client-side, the A2UI basic ones plus core ones): required, regex, length, numeric, email, formatString, formatNumber, formatCurrency, formatDate, pluralize, openUrl, and, or, not, percent, add, sub, eq, lt, clamp, cond, fallback, concat, coalesce, text, map, len, fill, set, formatPercent, formatRelativeTime.
Style keys (Box): display, flex*, justifyContent, align*, gap, width, height, min/max sizes, aspectRatio, position (relative|absolute|sticky), top/right/bottom/left, inset*, padding*/margin* (+Horizontal/Vertical/InlineStart/End), grid*, overflow(X/Y), direction, backgroundColor, backgroundGradient {angle, stops}, backdropBlur $blur.*, color, border*, opacity, boxShadow, font*, letterSpacing, text*, transition $motion.*, transform (translate/scale/rotate, paint only), animation (pulse|spin|fade-in|slide-in-up/down/left/right|shimmer), visibility, pointerEvents, userSelect, cursor. Values: px, "N%", "auto", or tokens $spacing.md, $color.primary, $radius.lg, $control.row.