Skip to content

A2UI Component Reference

Flow-Like A2UI surfaces are normalized component trees. Each component has a stable ID, a lower-camel-case type, typed properties, optional styles, and references to its children. This is the same contract used by the visual builders, FlowPilot, Pages, and Widgets.

A Page being edited with the current visual A2UI builder

A generated or imported surface uses one root ID and a flat component array:

{
"rootComponentId": "root",
"canvasSettings": {
"padding": "24px"
},
"components": [
{
"id": "root",
"style": {
"className": "min-h-full bg-background text-foreground"
},
"component": {
"type": "column",
"gap": { "literalString": "16px" },
"children": {
"explicitList": ["title", "open-dashboard"]
}
}
},
{
"id": "title",
"component": {
"type": "text",
"content": { "literalString": "Operations dashboard" },
"variant": { "literalString": "heading" },
"size": { "literalString": "2xl" },
"weight": { "literalString": "bold" }
}
},
{
"id": "open-dashboard",
"component": {
"type": "button",
"label": { "literalString": "Open dashboard" },
"variant": { "literalString": "default" },
"actions": [
{
"name": "navigate_page",
"context": { "route": "/dashboard" }
}
]
}
}
],
"dataModel": []
}

The visual builders maintain this structure for you. Use the JSON contract directly when generating a complete surface with FlowPilot or another coding agent.

Most visible component properties use BoundValue, even when their value is currently static.

| Value | JSON shape | | --- | --- | | String | { "literalString": "Hello" } | | Number | { "literalNumber": 42 } | | Boolean | { "literalBool": true } | | Select options | { "literalOptions": [{ "value": "open", "label": "Open" }] } | | Arbitrary JSON | { "literalJson": "{\"key\":\"value\"}" } | | Data binding | { "path": "$.data.customer.name", "defaultValue": "Customer" } |

Do not substitute raw strings or numbers where a component property expects a BoundValue.

Use an explicit list for a known component tree:

{
"children": {
"explicitList": ["heading", "description", "actions"]
}
}

Template children are available for data-driven repetition:

{
"children": {
"template": {
"dataPath": "$.data.items",
"itemIdPath": "$.id",
"templateComponentId": "item-template"
}
}
}

For a reusable card, row, or repeated interaction pattern, prefer a widgetInstance. A Widget owns its own component tree, exposed properties, and named actions.

Actions are an array inside the interactive component:

{
"type": "button",
"label": { "literalString": "Approve" },
"actions": [
{
"name": "workflow_event",
"context": {
"nodeId": "board-event-node-id"
}
}
]
}

Use one board Event for each distinct purpose. Page actions use the fixed workflow_event name and identify the selected Event with context.nodeId. The Event handler reads live input state with nodes such as Get Element Value or Get File Input Files; typed values should not be copied into the action context.

The current action contracts are:

| Action | Context | | --- | --- | | workflow_event | nodeId; the builder also includes the owning appId and boardId | | widget_event | actionId; resolved through the Widget instance's action binding | | navigate_page | route plus optional queryParams | | external_link | url |

For Widgets, declare the action ID in the Widget definition and bind that ID when the Widget is instantiated. There are no onClick, onChange, updateData, openModal, or closeModal action objects in the current component contract. A host may receive an otherwise unknown action name as a generic userAction, but that fallback does not execute a workflow by itself.

The current runtime contains 71 component types.

| Type | Purpose | Common properties | | --- | --- | --- | | row | Horizontal flex layout | gap, align, justify, wrap, reverse, children | | column | Vertical flex layout | gap, align, justify, wrap, reverse, children | | stack | Layer children on the z-axis | align, width, height, children | | grid | CSS grid layout | columns, rows, gap, columnGap, rowGap, autoFlow, children | | scrollArea | Scrollable content region | direction, children | | aspectRatio | Preserve a content ratio | ratio, children | | overlay | Anchor components over a base component | baseComponentId, overlays | | absolute | Free-positioned canvas | width, height, children | | box | Generic semantic container | as, children | | center | Center one or more children | inline, children | | spacer | Fixed or flexible space | size, flex | | widgetInstance | Instance of a reusable Widget definition | widgetId, instanceId, inlineWidgetDef, exposedPropValues |

| Type | Purpose | Common properties | | --- | --- | --- | | text | Plain typography | content, variant, size, weight, color, align, truncate, maxLines | | image | Image with loading and fallback behavior | src, alt, fit, fallback, loading, aspectRatio | | icon | Lucide icon | name, size, color, strokeWidth | | video | Video player | src, poster, autoplay, loop, muted, controls | | lottie | Lottie animation | src, autoplay, loop, speed, width, height | | markdown | Rendered Markdown content | content, allowHtml | | divider | Horizontal or vertical separator | orientation, thickness, color | | badge | Compact status or category label | content, variant, color | | avatar | Avatar image with fallback | src, fallback, size | | userProfile | User lookup and profile presentation | value, variant, avatarSize, visibility flags | | progress | Progress indicator | value, max, showLabel, variant, color | | spinner | Indeterminate loading state | size, color | | skeleton | Loading placeholder | width, height, rounded | | table | Data table | columns, data, sorting, search, pagination, and selection flags | | tableRow | Explicit table row | cells, selected, disabled | | tableCell | Explicit table cell | content, isHeader, spans, align | | filePreview | Preview a PDF, image, media, code, or text file | src, filename, mimeType, fileType, showControls | | diffView | Compare text, code, Markdown, JSON, or documents | original, modified, mode, kind, language | | boundingBoxOverlay | Display boxes over an image | image source, boxes, labels, and display options |

| Type | Purpose | Common properties | | --- | --- | --- | | button | Primary user action | label, variant, size, disabled, loading, icon, actions | | feedback | Positive/negative, rating, and comment feedback | mode, labels, ratings, comment settings, context flags | | appLink | Link to an app surface | target, label, appId, eventId, variant, disabled | | textField | Single- or multi-line text input | value, placeholder, label, inputType, multiline, required | | select | Single or multiple selection | value, options, placeholder, multiple, searchable | | slider | Numeric range input | value, min, max, step, showValue, label | | checkbox | Boolean or indeterminate input | checked, label, disabled, indeterminate | | switch | Boolean switch | checked, label, disabled | | radioGroup | Single selection from visible options | value, options, orientation, label | | dateTimeInput | Date, time, or combined input | value, mode, min, max, label | | fileInput | File upload | value, accept, multiple, maxSize, maxFiles, error | | imageInput | Image upload with preview | file-input properties plus aspectRatio and showPreview | | voiceInput | Record audio or speech-to-text input | value, variant, size, mode, invoke, resultMode | | link | Internal route or external link | href, label, route, queryParams, target, variant | | imageLabeler | Draw and edit labeled image regions | image, labels, boxes, and editing options | | imageHotspot | Interactive image hotspots | image, hotspots, selection, and action options |

| Type | Purpose | Common properties | | --- | --- | --- | | card | Framed content group | title, description, footer, variant, padding, children | | modal | Modal dialog | open, title, description, close behavior, size, children | | tabs | Tabbed content | value, tabs, orientation, variant, tab styles | | accordion | Collapsible sections | items, selection and collapse behavior | | drawer | Edge-mounted panel | open, side, title, close behavior, children | | tooltip | Hover or focus explanation | content, side, delay, and trigger component | | popover | Anchored interactive panel | open state, placement, trigger, and content component |

| Type | Purpose | | --- | --- | | plotlyChart | Plotly series, axes, layout, and advanced raw configuration | | nivoChart | Nivo chart types including bar, line, pie, radar, heatmap, Sankey, and more | | geoMap | Geographic map with markers and view settings | | graph | Node and edge network graph with legend, search, and inspectors | | ontologyGraph | Live explorer for one of the project's ontologies | | calendar | Month, week, day, or agenda planning view | | gantt | Interactive task timeline with dependencies | | iframe | Sandboxed external URL or srcdoc embed |

When workflow data drives a chart or table, use Push Data to Chart, Push CSV to Table, or Update Table. Literal data properties are best kept for static design-time content.

| Type | Purpose | | --- | --- | | canvas2d | Root 2D canvas | | sprite | Positioned 2D image sprite | | shape | Rectangle, circle, polygon, line, or other 2D shape | | scene3d | Root 3D scene | | model3d | GLB or GLTF model | | dialogue | Visual-novel-style dialogue | | characterPortrait | Character image and expression | | choiceMenu | Player decision menu | | inventoryGrid | Inventory slots and items | | healthBar | Health or resource meter | | miniMap | Compact map with markers |

style belongs beside component in each component record:

{
"id": "summary-card",
"style": {
"className": "rounded-xl border border-border bg-card p-6 text-card-foreground",
"shadow": {
"x": "0",
"y": "8px",
"blur": "24px",
"color": "rgb(0 0 0 / 0.12)"
}
},
"component": {
"type": "card",
"title": { "literalString": "Summary" }
}
}

Prefer semantic theme classes such as bg-background, bg-card, text-foreground, text-muted-foreground, and border-border. They adapt to light and dark mode without duplicating color rules.

Structured style fields cover background, border, shadow, spacing, sizing, position, transform, overflow, typography, visibility, and responsive overrides.

Layout first

Start with column, row, or grid. Add scrollArea, overlay, or absolute only when the content model requires them.

Bind live values

Use BoundValue paths for shared data, and element setter nodes when a workflow owns the displayed value.

Reuse interactions

Extract repeated interactive cards or rows into Widgets and declare their actions at the Widget level.

Respect both themes

Prefer semantic theme tokens and verify the surface in both light and dark mode.