Components
The full widget component library — layout, text, form inputs, data display, media, and interactive components — with the JSX-like syntax for composing them.
View as MarkdownWidgets are composed from a fixed library of components. You combine them in JSX-like markup, set their properties as attributes, and pass data from the widget's schema. This page is the reference for every component, grouped by category.
Properties are passed as attributes. Strings use quotes (color="primary"); numbers, objects, and data references use braces (gap={4}, value={title}).
Layout
Card is the outer container of every widget; Col and Row lay children out vertically or horizontally.
| Component | Description | Common props |
|---|---|---|
Card | The widget's outer container. Use asForm to make it a submittable form. | size, background, theme, asForm |
Col | Stacks children in a column. | gap, padding, width, align |
Row | Lays children out in a row. | gap, align, padding |
Box | A generic flex container. | direction, wrap, padding |
Divider | A horizontal rule between sections. | size, color, spacing |
Spacer | Flexible empty space that pushes siblings apart. | minSize |
<Card size="md">
<Row gap={2} align="center">
<Title value="Order #1024" size="md" weight="semibold" />
<Spacer />
<Badge label="Shipped" color="success" pill />
</Row>
</Card>Text
| Component | Description | Common props |
|---|---|---|
Title | A heading. | value, size, weight |
Text | Body or secondary text (supports multiple lines). | value, size, color |
Label | A field label tied to an input. | value, fieldName |
Form inputs
Capture structured data inside the chat. Wrap them in a Card with asForm and submit with a Button submit.
| Component | Description | Common props |
|---|---|---|
Input | A single-line text field. | name, inputType, placeholder, required |
Textarea | A multi-line text field. | name, rows, placeholder, required |
Select | A dropdown of options. | name, options, placeholder, block |
Checkbox | A single boolean checkbox. | name, label |
<Col gap={2}>
<Label value="Company size" fieldName="companySize" />
<Select name="companySize" placeholder="Select size"
options={companySizes} block required />
</Col>Data display
| Component | Description | Common props |
|---|---|---|
Table | A data table container. | — |
TableRow | A table row; mark headers with header. | header |
TableCell | A table cell. | align, colSpan, rowSpan, width |
Chart | A bar / line / area chart rendered from data. | data, series, xAxis, yAxis, showLegend |
Badge | A small status pill or tag. | label, color, variant, pill |
ListView | A scrollable list or carousel of items. | orientation, gap, limit |
ListViewItem | A single item within a ListView. | gap |
Media
| Component | Description | Common props |
|---|---|---|
Image | An image, with fit and corner radius. Supports light/dark sources. | src, height, fit, radius |
Icon | An icon from the built-in set (kebab-case names). | name, size, color |
Interactive
A Button runs a function via onClickAction; pass extra data along with additionalInputs.
| Component | Description | Common props |
|---|---|---|
Button | A clickable button that runs a function or submits a form. | label, variant, color, block, submit, onClickAction |
<Button label="Add to cart" iconStart="shopping-cart"
variant="solid" color="primary" block
onClickAction={{ functionName: "addToCart",
additionalInputs: { productId: product.id } }} />Theming
Components use theme tokens (text colors like primary, secondary, tertiary; status colors like success, warning) and automatically adapt to a light or dark chat surface. You generally don't set raw colors — use the named tokens so widgets stay on-brand across themes.
Composing a full widget
Put it together — a product card built from layout, media, text, data display, and interactive components, repeated over a data array:
<Card size="md">
<Col gap={3}>
<Row gap={2} align="center">
<Icon name="shopping-bag" size="sm" color="secondary" />
<Text value={heading} size="sm" color="secondary" />
</Row>
<ListView orientation="horizontal" gap={2}>
{products.map((product) => (
<ListViewItem key={product.id}>
<Col gap={2} width={240}>
<Image src={product.image} height={190} fit="cover" radius="md" />
<Title value={product.name} size="xs" weight="semibold" />
<Text value={product.category} size="sm" color="secondary" />
<Text value={product.price} size="md" weight="medium" />
<Button label="Add to cart" variant="solid" color="primary" block
onClickAction={{ functionName: "addToCart",
additionalInputs: { productId: product.id } }} />
</Col>
</ListViewItem>
))}
</ListView>
</Col>
</Card>