Dynamic UI SDK
The Dynamic UI SDK is the typed authoring surface for record forms, page UI blocks, and PDF document layouts. Your code returns a tree of supported components, and the platform renderer handles the rest.
Authoring Pattern
Each UI codeblock exports run() and returns SDK.GlobalStore(...).
Prefer destructuring components from SDK and using capitalized JSX values such as Flex, Text, and CollectionTable inside the returned tree.
import { Params, ReturnType } from './data';
import { SDK } from './external';
export function run(params: Params): ReturnType {
const { Badge, CollectionTable, Flex, Text } = SDK;
return SDK.GlobalStore({
data: {
selectedStatus: 'active'
},
ui: (store) => (
<Flex direction="column" gap={4}>
<Text textStyle="h2" content="Operations overview" />
<Badge content={store.read('data.selectedStatus')} />
<CollectionTable collectionName="projects" title="Projects" />
</Flex>
)
});
} Store API
The store object supports four core patterns:
store.bind(path)store.read(path)store.read(expr, { mode: 'CEL' })store.derive(pointer, expression)
Scoped Callbacks
When a component introduces a nested item or row scope, use the typed callback that component provides instead of manually re-resolving paths.
Repeater.items((item) => ...)DataGrid.columns((row) => [...])CollectionTable.details((row) => ...)Kanban.details((row) => ...)
import { Params, ReturnType } from './data';
import { SDK } from './external';
export function run(_params: Params): ReturnType {
const { DataGrid, Flex, FormInput, GridColumn, Repeater, Text } = SDK;
return SDK.GlobalStore({
data: {
items: [{ sku: 'A-1', qty: 1 }],
rows: [{ name: 'Ada', qty: 2 }]
},
ui: (store) => (
<Flex direction="column" gap={4}>
<Repeater
value={store.bind('data.items')}
items={(item) => <FormInput label="SKU" value={item.bind('sku')} />}
/>
<DataGrid
value={store.bind('data.rows')}
columns={(row) => [
<GridColumn header="Name" cell={<FormInput label="Name" value={row.bind('name')} />} />,
<GridColumn header="Qty" cell={<Text content={row.read('qty')} />} />
]}
/>
</Flex>
)
});
} CEL in Dynamic UI
Use CEL for:
- visibility rules,
- dynamic props,
- derived values,
pre_queryexpressions that depend on current scope.
Validation Behavior
Dynamic UI includes meaningful validation, especially in preview and invariant-check flows. Normal runtime rendering is intentionally lighter so page and form execution stays fast.
const { Flex, Text, FormInput } = SDK; followed by capitalized JSX component usage. This keeps examples aligned with the runtime SDK and the
current type-safety tests.Components
Dynamic UI supports a broad but controlled registry of components, including:
- Layout and content:
Flex,Text,Badge,Image,Divider,Chart - Form components:
FormInput,FormButton,Combobox,Checkbox,CheckboxGroup - Structured views:
Tabs,Steps,TreeView,DropdownMenu - Data surfaces:
DataGrid,Repeater,Table,CollectionTable,TaskBlock,Kanban,Timeline - PDF layout:
Document,Page,View
Supported Chart Types
The current chart component supports four chart kinds:
bar: Compare values across categories. Provide cartesian data, an `xKey`, and one or more `series`. Use `stacked` when multiple series should accumulate.line: Show trends over time or ordered sequences. Provide cartesian data with an `xKey` and `series`. Use `curve` when you want linear, natural, or step rendering.area: Show trend plus volume emphasis. Use the same cartesian shape as bar and line charts. This works well when totals or stacked accumulation matter visually.donut: Show part-to-whole composition. Provide `data` as `{ key, value }[]` and use `innerRadius` to tune the center opening.
All chart specs also support shared metadata such as title, description, config, showLegend, showTooltip, showGrid, and valueFormat.
import { Params, ReturnType } from './data';
import { SDK } from './external';
export function run(_params: Params): ReturnType {
const { Chart } = SDK;
return SDK.GlobalStore({
data: {},
ui: () => (
<Chart
spec={{
kind: 'bar',
title: 'Projects by status',
xKey: 'status',
series: ['count'],
data: [
{ status: 'Active', count: 12 },
{ status: 'Blocked', count: 3 },
{ status: 'Done', count: 9 }
],
config: {
count: { label: 'Projects' }
}
}}
/>
)
});
} Full Registry Reference
The list below covers the current authoring surface exposed by Dynamic UI, plus the one system-rendered placeholder you may encounter at runtime.
Layout and Content
| Element | What it does | How to use it |
|---|---|---|
Flex | General-purpose layout container for rows, columns, spacing, and surface styling. | Use it as the default wrapper for most interfaces and pages. Put child nodes inside it and control spacing with `direction`, `gap`, `align`, and `justify`. |
View | Box-like container primarily used in PDF and structured layouts. | Use it when you want a bounded visual section with its own padding, border, or background, especially in document layouts. |
Text | Renders labels, headings, body copy, and inline values. | Use `content` for the displayed value and `textStyle` for semantic styling such as `h1`, `h2`, or `body`. |
Badge | Displays a small status or label chip. | Use it for state indicators, quick counts, or compact labels. Bind `content` from store values when needed. |
Image | Displays an image with basic fitting and sizing controls. | Provide `src` and optional `alt`, `width`, `height`, and `objectFit` when the page or document needs visual media. |
Divider | Adds a visual separator between sections. | Use it to break large forms or dashboard areas into clearer chunks. Adjust `margin`, `thickness`, and `lineStyle` as needed. |
Empty | Shows a structured empty state with title, description, and optional children. | Use it when a page or panel needs a graceful “nothing here yet” state instead of a blank surface. |
Chart | Renders chart specs for dashboard-style data visualization. | Pass a `spec` object with one of the supported chart kinds. This is best for summary pages and reporting surfaces rather than data entry forms. |
Form Components
| Element | What it does | How to use it |
|---|---|---|
FormInput | Renders a collection-aware input bound to a form field. | Bind `value` with `store.bind("form.field")` or `store.derive(...)`. The actual input renderer comes from the bound collection column metadata. |
FormButton | Triggers submit, clear, or store-set actions in a form. | Use `action="submit"` for form submission, `action="clear"` for reset behavior, or `{ set, value }` for simple UI-state actions. |
Combobox | Provides searchable or multi-select option picking. | Pass `options` and bind `value` when the user needs to choose from a known set rather than from collection-backed form metadata. |
Checkbox | Captures a single boolean choice. | Bind `value` for yes/no decisions. The `selection-card` variant works well for visually emphasized choices. |
CheckboxGroup | Captures multiple selections from a fixed list. | Provide `options` and bind `value` to a string array when the user may choose several values at once. |
Structured and Stateful UI
| Element | What it does | How to use it |
|---|---|---|
Tabs | Creates a tab container with switchable content panels. | Use it to split larger forms or dashboards into clearly named sections. Pair it with `TabContent` children. |
TabContent | Defines one tab panel inside `Tabs`. | Set `value` and `label`, then place the tab body inside it. Every child must live under a parent `Tabs` node. |
Steps | Creates a multi-step flow container. | Use it when users should move through a staged workflow or guided sequence. Pair it with `StepContent`. |
StepContent | Defines one step within a `Steps` flow. | Set the `label` and optional `description`, then place the step content inside it. |
TreeView | Displays hierarchical selectable nodes. | Use it for org structures, category hierarchies, or nested navigation where parent-child structure matters. |
DropdownMenu | Shows an action menu from a trigger button. | Use it for contextual actions or quick command menus. Provide `items` and bind the selected action if you need to react in store state. |
Data Surfaces
| Element | What it does | How to use it |
|---|---|---|
Repeater | Repeats a template for each item in an array. | Bind the array with `value={store.bind(...)}` and pass `items={(item) => ...}` so the item store is typed from the same bind path. |
DataGrid | Renders editable, row-based tabular input inside Dynamic UI. | Bind an array value, define columns with row-store callbacks, and use it for nested line items or structured repeated form data. |
GridColumn | Defines one column inside a `DataGrid`. | Use it only as a child of `DataGrid`, setting the `header` and the cell node to render for each row. |
Table | Displays presentational tabular output. | Use it for read-only summary tables or PDF output when you already know the final columns and do not need collection-table behavior. |
CollectionTable | Embeds a collection browsing surface directly inside Dynamic UI. | Use `collectionName` and optional `pre_query`, `features`, and `details` when you want users to browse real collection records from a page. |
TaskBlock | Embeds the task system in a page or Dynamic UI surface. | Use it for department queues, review lists, or work-management widgets inside app pages. |
Kanban | Displays an array of records as cards grouped by a dot-path `laneKey`, with optional per-card `details` like CollectionTable. | Set required `laneKey` and bind `items` to the card array, or rely on scope when it is already the card array. Use `details={(row) => …}` for card content; without `details`, use dot-path `title` / `description`. Column titles match the resolved lane value (same rules as column ids). |
Timeline | Displays dated or sequenced events. | Use it when users need to understand order, history, or milestone progression at a glance. |
PDF Layout Elements
| Element | What it does | How to use it |
|---|---|---|
Document | Root container for a PDF layout. | Use it only in PDF document codeblocks. It should wrap one or more `Page` nodes. |
Page | Defines a single PDF page. | Use it under `Document` and control paper settings such as `size`, `orientation`, and `margin`. |
View | Provides an internal layout section within a PDF page. | Use it under `Page` for grouped document structure, spacing, and boxed sections. |
System-Rendered Element
| Element | What it does | How to use it |
|---|---|---|
Redacted | Represents a server-resolved redaction placeholder. | You do not usually author this directly. The runtime inserts it when a user cannot access the referenced data. |
Form Surfaces vs Page Surfaces
Use form_for when the UI is tied to a collection-backed record form. Use a plain data store
when building a page surface or PDF document that is not itself the primary mutation form.
Recommended Patterns
- Start with a small tree and expand only when the workflow clearly needs it.
- Use collection-backed forms for actual record editing.
- Use page UI blocks for dashboards, contextual browsing, and embedded operational components.
- Test with the real permission model, especially where redaction is involved.