# Connect Interactive UI — LLM Reference > **Purpose:** Feed this document to an LLM so it can generate valid Interactive UI JSON for Connect flows. ## Task You generate JSON component trees for **Connect Interactive Flows**. The JSON is rendered as a Fluent UI Blazor interface. Produce **only** valid JSON matching the schema and rules below. --- ## JSON Schema ```json { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Connect Interactive UI Component Tree", "description": "A polymorphic component tree rendered by Connect. Every node has a 'component' discriminator.", "definitions": { "orientation": { "type": "string", "enum": ["Horizontal", "Vertical"] }, "horizontalAlignment": { "type": "string", "enum": ["Left", "Start", "Center", "Right", "End", "Stretch", "SpaceBetween"] }, "verticalAlignment": { "type": "string", "enum": ["Top", "Center", "Bottom", "Stretch", "SpaceBetween"] }, "color": { "type": "string", "enum": ["Neutral", "Accent", "Warning", "Info", "Error", "Success", "Fill", "FillInverse", "Lightweight", "Disabled", "Custom"], "description": "When 'Custom', set 'customColor' to a CSS color value." }, "typography": { "type": "string", "enum": ["Body", "Subject", "Header", "PaneHeader", "HeroTitle", "PageTitle", "H1", "H2", "H3", "H4", "H5", "H6"] }, "fontWeight": { "type": "string", "enum": ["Normal", "Bold", "Bolder"] }, "align": { "type": "string", "enum": ["Start", "Center", "End", "Stretch", "Baseline"] }, "sortDirection": { "type": "string", "enum": ["Auto", "Ascending", "Descending"] }, "selectMode": { "type": "string", "enum": ["Single", "Multiple"] }, "dataGridRowSize": { "type": "string", "enum": ["Smaller", "Small", "Medium", "Large"] }, "iconVariant": { "type": "string", "enum": ["Regular", "Filled"] }, "iconSize": { "type": "string", "enum": ["Size10", "Size12", "Size16", "Size20", "Size24", "Size28", "Size32", "Size48"] }, "flowStartMode": { "type": "string", "enum": ["Background", "Foreground", "InteractiveInNewTab", "InteractiveInCurrentTab"], "description": "Background: fire-and-forget. Foreground: wait for result. InteractiveInNewTab/InteractiveInCurrentTab: open the run page." }, "buttonDataBinding": { "type": "object", "required": ["componentId"], "properties": { "componentId": { "type": "string", "description": "ID of the source component." }, "sourcePath": { "type": "string", "description": "Optional JSON Path to extract a value from the source data." }, "targetPath": { "type": "string", "description": "Optional JSON Path where the value is placed in the combined data. If omitted, keyed by componentId." } }, "additionalProperties": false }, "dataGridColumn": { "type": "object", "required": ["key", "title"], "properties": { "key": { "type": "string", "description": "Property key (or JSON Path) to read from each row." }, "title": { "type": "string", "description": "Column header text." }, "align": { "$ref": "#/definitions/align", "default": "Start" }, "initialSortDirection": { "$ref": "#/definitions/sortDirection", "default": "Auto" }, "isDefaultSortColumn": { "type": "boolean", "default": false }, "sortable": { "type": "boolean", "default": true }, "filterable": { "type": "boolean", "default": false }, "width": { "type": ["string", "null"], "description": "Fixed CSS width, e.g. '80px'." }, "minWidth": { "type": ["string", "null"], "default": "100px" } }, "additionalProperties": false }, "dataGridSelection": { "type": "object", "properties": { "mode": { "$ref": "#/definitions/selectMode", "default": "Multiple" }, "selectable": { "type": ["string", "null"], "description": "JSON Path evaluated per row; must return boolean." }, "minSelectable": { "type": "integer", "minimum": 0, "default": 1 }, "maxSelectable": { "type": ["integer", "null"], "minimum": 1 } }, "additionalProperties": false }, "dataGridPagination": { "type": "object", "properties": { "itemsPerPage": { "type": "integer", "minimum": 1, "default": 10 } }, "additionalProperties": false }, "component": { "type": "object", "required": ["component"], "discriminator": { "propertyName": "component" }, "oneOf": [ { "$ref": "#/definitions/stack" }, { "$ref": "#/definitions/label" }, { "$ref": "#/definitions/card" }, { "$ref": "#/definitions/divider" }, { "$ref": "#/definitions/icon" }, { "$ref": "#/definitions/dataGrid" }, { "$ref": "#/definitions/jsonSchemaForm" }, { "$ref": "#/definitions/linkButton" }, { "$ref": "#/definitions/flowStartButton" }, { "$ref": "#/definitions/submitDataButton" } ] }, "stack": { "type": "object", "required": ["component"], "properties": { "component": { "const": "stack" }, "style": { "type": ["string", "null"] }, "id": { "type": ["string", "null"] }, "children": { "type": "array", "items": { "$ref": "#/definitions/component" }, "default": [] }, "orientation": { "$ref": "#/definitions/orientation", "default": "Vertical" }, "verticalAlignment": { "$ref": "#/definitions/verticalAlignment", "default": "Top" }, "horizontalAlignment": { "$ref": "#/definitions/horizontalAlignment", "default": "Left" }, "horizontalGap": { "type": ["integer", "null"], "default": 10, "description": "Gap in pixels." }, "verticalGap": { "type": ["integer", "null"], "default": 10, "description": "Gap in pixels." }, "wrap": { "type": "boolean", "default": false }, "reverse": { "type": ["boolean", "null"] } }, "additionalProperties": false }, "label": { "type": "object", "required": ["component"], "properties": { "component": { "const": "label" }, "style": { "type": ["string", "null"] }, "id": { "type": ["string", "null"] }, "text": { "type": ["string", "null"], "description": "Text content to display." }, "typography": { "$ref": "#/definitions/typography", "default": "Body" }, "weight": { "$ref": "#/definitions/fontWeight", "default": "Normal" }, "color": { "$ref": "#/definitions/color" }, "customColor": { "type": ["string", "null"], "description": "CSS color value. Only used when color is 'Custom'." }, "alignment": { "$ref": "#/definitions/horizontalAlignment" }, "marginBlock": { "type": ["string", "null"], "description": "CSS margin-block value." }, "disabled": { "type": "boolean", "default": false } }, "additionalProperties": false }, "card": { "type": "object", "required": ["component"], "properties": { "component": { "const": "card" }, "style": { "type": ["string", "null"] }, "id": { "type": ["string", "null"] }, "children": { "type": "array", "items": { "$ref": "#/definitions/component" }, "default": [] }, "areaRestricted": { "type": "boolean", "default": true, "description": "Clip content to card boundaries." }, "minimalStyle": { "type": "boolean", "default": false } }, "additionalProperties": false }, "divider": { "type": "object", "required": ["component"], "properties": { "component": { "const": "divider" }, "style": { "type": ["string", "null"] }, "id": { "type": ["string", "null"] }, "orientation": { "$ref": "#/definitions/orientation", "default": "Horizontal" } }, "additionalProperties": false }, "icon": { "type": "object", "required": ["component"], "properties": { "component": { "const": "icon" }, "style": { "type": ["string", "null"] }, "id": { "type": ["string", "null"] }, "name": { "type": "string", "default": "Warning", "description": "Fluent UI icon name, e.g. 'CheckmarkCircle', 'Warning', 'Info', 'DismissCircle', 'Heart', 'ArrowClockwise'." }, "title": { "type": ["string", "null"], "description": "Tooltip / accessible title." }, "variant": { "$ref": "#/definitions/iconVariant", "default": "Regular" }, "size": { "$ref": "#/definitions/iconSize", "default": "Size20" }, "color": { "$ref": "#/definitions/color" }, "customColor": { "type": ["string", "null"] }, "width": { "type": ["string", "null"], "description": "CSS width override." } }, "additionalProperties": false }, "dataGrid": { "type": "object", "required": ["component"], "properties": { "component": { "const": "dataGrid" }, "style": { "type": ["string", "null"] }, "id": { "type": ["string", "null"], "description": "Required when selection data must be read by a button." }, "columns": { "type": "array", "items": { "$ref": "#/definitions/dataGridColumn" }, "default": [] }, "items": { "type": "array", "items": { "type": "object" }, "default": [], "description": "Array of JSON objects; each object is a row." }, "selection": { "$ref": "#/definitions/dataGridSelection" }, "itemKey": { "type": ["string", "null"], "description": "Row property key used to identify selected items." }, "showHover": { "type": "boolean", "default": false }, "resizeableColumns":{ "type": "boolean", "default": true }, "autoFitColumns": { "type": "boolean", "default": true }, "rowSize": { "$ref": "#/definitions/dataGridRowSize", "default": "Small" }, "pagination": { "oneOf": [{ "$ref": "#/definitions/dataGridPagination" }, { "type": "null" }], "description": "Omit or null to disable pagination." } }, "additionalProperties": false }, "jsonSchemaForm": { "type": "object", "required": ["component", "schema"], "properties": { "component": { "const": "jsonSchemaForm" }, "style": { "type": ["string", "null"] }, "id": { "type": ["string", "null"], "description": "Required when a button needs to read the form data." }, "schema": { "type": "object", "description": "A standard JSON Schema (draft 2020-12 compatible) that drives form generation." }, "data": { "description": "Optional initial form data matching the schema." }, "gap": { "type": "string", "default": "0.5rem", "description": "CSS gap between form fields." } }, "additionalProperties": false }, "linkButton": { "type": "object", "required": ["component"], "properties": { "component": { "const": "linkButton" }, "style": { "type": ["string", "null"] }, "id": { "type": ["string", "null"] }, "text": { "type": ["string", "null"], "default": "Open Link" }, "linkTemplate": { "type": "string", "default": "", "description": "URL with optional {placeholder} tokens resolved from combined data." }, "queryPath": { "type": ["string", "null"], "description": "JSON Path to an object whose properties become query string params." }, "openInNewTab": { "type": "boolean", "default": true }, "data": { "type": "object", "default": {}, "description": "Static data merged into the combined data." }, "bindings": { "type": "array", "items": { "$ref": "#/definitions/buttonDataBinding" }, "default": [] }, "validatesComponents": { "type": "array", "items": { "type": "string" }, "default": [], "description": "IDs of components to validate before navigating." } }, "additionalProperties": false }, "flowStartButton": { "type": "object", "required": ["component"], "properties": { "component": { "const": "flowStartButton" }, "style": { "type": ["string", "null"] }, "id": { "type": ["string", "null"] }, "text": { "type": ["string", "null"], "default": "Start Flow" }, "flowPath": { "type": ["string", "null"], "description": "Explicit flow path. When null, resolved from combined data." }, "allowedFlowPaths": { "type": "array", "items": { "type": "string" }, "default": [], "description": "Allowed paths when flowPath is null (dynamic mode)." }, "startMode": { "$ref": "#/definitions/flowStartMode", "default": "Foreground" }, "allowMultipleStarts": { "type": "boolean", "default": false }, "data": { "type": "object", "default": {}, "description": "Static data merged into flow input." }, "bindings": { "type": "array", "items": { "$ref": "#/definitions/buttonDataBinding" }, "default": [] }, "validatesComponents": { "type": "array", "items": { "type": "string" }, "default": [], "description": "IDs of components to validate before starting." } }, "additionalProperties": false }, "submitDataButton": { "type": "object", "required": ["component"], "properties": { "component": { "const": "submitDataButton" }, "style": { "type": ["string", "null"] }, "id": { "type": ["string", "null"] }, "text": { "type": ["string", "null"], "default": "Submit", "description": "Button label text." }, "data": { "type": "object", "default": {}, "description": "Static data merged into the submission payload." }, "bindings": { "type": "array", "items": { "$ref": "#/definitions/buttonDataBinding" }, "default": [], "description": "Data bindings to collect input from other components." }, "validatesComponents": { "type": "array", "items": { "type": "string" }, "default": [], "description": "IDs of components to validate before submitting." } }, "additionalProperties": false, "description": "Submits collected user input to a flow checkpoint to resume a waiting interactive flow. Only functional during an active ShowInteractiveUi interaction. The button is disabled after the first successful submission." } }, "$ref": "#/definitions/component" } ``` --- ## Rules 1. **Output only JSON.** No markdown fences, no commentary, no explanation — just the raw JSON object. 2. The root must be a single component object (typically a `stack`). 3. Every object must include `"component": ""`. 4. Only use property names shown in the schema. All names are **camelCase**. 5. Enum values are **PascalCase** and must be one of the listed values exactly. 6. Omit properties when the default is acceptable — keep JSON minimal. 7. `id` is only needed on components whose data is consumed by a button (`bindings[].componentId`). Do not add ids to purely display components. 8. `style` accepts any valid inline CSS. Use it for layout fine-tuning (widths, margins, flex). 9. For icon names, use Fluent UI icon names like: `CheckmarkCircle`, `DismissCircle`, `Warning`, `Info`, `Heart`, `Star`, `People`, `Document`, `Settings`, `ArrowClockwise`, `Search`, `Add`, `Delete`, `Edit`, `Save`, `Eye`, `EyeOff`, `Lock`, `Globe`, `Mail`, `Phone`, `Calendar`, `Clock`, `Folder`, `Database`, `Cloud`, `Lightning`, `Rocket`. 10. **Synchronous UIs** (those configured with an output binding to write user input back to the flow) **must contain at least one `submitDataButton`** somewhere in the component tree. The flow engine validates this at execution time and throws an error if no `submitDataButton` is found. **Display-only UIs** (no output binding) do not require a `submitDataButton`; any `submitDataButton` present will be rendered as disabled since there is no data target. --- ## Data Binding Rules Buttons (`linkButton`, `flowStartButton`, `submitDataButton`) can pull data from other components: 1. Give the data-providing component an `id` (e.g. `"id": "myGrid"`). 2. In the button, add a `bindings` entry: `{ "componentId": "myGrid" }`. 3. Optionally use `sourcePath` (JSON Path on the source data) and `targetPath` (JSON Path in the combined data). 4. Add the component id to `validatesComponents` to enforce validation before the action. 5. **DataGrid** output provides: `items`, `selectedItems`, `selectedIndices`, `selectedKeys`. 6. **JsonSchemaForm** output provides the current form data as a JSON object. 7. `linkTemplate` placeholders use `{propertyName}` or `{$.json.path}` syntax — values are URL-encoded automatically. --- ## Quick Reference Table | Component | Discriminator | Container? | Provides Data? | Key Properties | |---|---|---|---|---| | Stack | `stack` | Yes | No (aggregates children) | `children`, `orientation`, `wrap`, `horizontalGap`, `verticalGap` | | Label | `label` | No | No | `text`, `typography`, `weight`, `color` | | Card | `card` | Yes | No (aggregates children) | `children`, `areaRestricted`, `minimalStyle` | | Divider | `divider` | No | No | `orientation` | | Icon | `icon` | No | No | `name`, `variant`, `size`, `color` | | DataGrid | `dataGrid` | No | Yes (selection data) | `columns`, `items`, `selection`, `pagination`, `itemKey` | | JsonSchemaForm | `jsonSchemaForm` | No | Yes (form data) | `schema`, `data`, `gap` | | LinkButton | `linkButton` | No | No | `text`, `linkTemplate`, `openInNewTab`, `bindings` | | FlowStartButton | `flowStartButton` | No | No | `text`, `flowPath`, `startMode`, `bindings` | | SubmitDataButton | `submitDataButton` | No | No | `text`, `data`, `bindings`, `validatesComponents` |