# FormDSL Reference Download as Markdown > **For LLMs generating FormDSL forms.** This document covers the complete JSX DSL surface area for both SolidJS (`@formdsl/solid`) and React (`@formdsl/react`). The APIs are identical across frameworks. ## Quick Start ```tsx // SolidJS import { Form, Section, Question, Row } from '@formdsl/solid' // React import { Form, Section, Question, Row } from '@formdsl/react' export default function MyForm() { return (
console.log(answers)}>
) } ``` Every form follows the pattern: **Form > Section > Question**. Layout components (`Row`, `Card`, `Banner`, etc.) go inside sections. The `id` on each Question must be unique within the form. --- ## Core Components ### `
` Root container. Handles collection, rendering, state, navigation, and submission. | Prop | Type | Default | Description | |------|------|---------|-------------| | `id` | `string` | required | Unique form identifier (used for deploy) | | `version` | `string` | `undefined` | Form version string | | `title` | `string` | | Form title (shown in header if using `FormTitle`) | | `onSubmit` | `(answers, inputLog, remarks?) => void` | | Submission handler | | `onSave` | `(answers, inputLog, remarks?) => void` | | Manual save handler | | `initialAnswers` | `Record` | | Pre-populate answers | | `initialInputLog` | `InputLogEntry[]` | | Resume from existing input log | | `navigation` | `'none' \| 'sidebar' \| 'stepper' \| 'tabs'` | `'none'` | Multi-section navigation mode | | `theme` | `'default' \| 'printed'` | `'default'` | Visual theme | | `compact` | `boolean` | `false` | Reduced spacing | | `width` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Form width preset (480/640/800/1000/1200px) | | `submitLabel` | `string` | `"Submit"` | Submit button text | | `nextLabel` | `string` | `"Continue"` | Next button text | | `backLabel` | `string` | `"Back"` | Back button text | | `ctaLabel` | `string` | | CTA button text (e.g., "Save For Later") | | `hideActions` | `boolean` | `false` | Hide navigation buttons | | `autoSave` | `boolean` | `false` | Enable auto-save | | `autoSaveDelay` | `number` | `1500` | Auto-save debounce (ms) | | `saveIndicator` | `'checkmark' \| 'toast' \| 'none'` | `'toast'` | Auto-save feedback style | | `onAutoSave` | `(answers, inputLog, remarks?) => void \| Promise` | | Auto-save handler | | `enableRouting` | `boolean` | `false` | URL-based section routing | | `basePath` | `string` | | Base path for URL routing | | `blockNavigation` | `boolean` | `false` | Prevent section navigation until current is valid | | `readOnly` | `boolean` | `false` | Read-only mode | | `preview` | `boolean` | `false` | Preview mode | | `debug` | `boolean` | `false` | Show debug panel | | `class` | `string` | | CSS class on form root | | `series` | `string` | | Series slug for prefill grouping | | `prefill` | `'all' \| 'partial'` | | Prefill mode | | `apiKey` | `string` | | Publishable key for connected mode (`fpk_*`) | | `serverUrl` | `string` | `window.location.origin` | Server URL for connected mode | | `identityToken` | `string` | | JWT for identity verification | | `onSubmitSuccess` | `(result) => void` | | Called after successful connected-mode submit | | `onFormStateReady` | `(formState) => void` | | Called when form state is initialized | | `onManifestReady` | `(manifest) => void` | | Called when manifest is built | | `detectStaleSession` | `boolean` | `false` | Enable stale tab detection | | `staleThreshold` | `number` | `60000` | Time in ms before session is considered stale | | `showSaveStatus` | `boolean` | `false` | Show persistent "Last saved X ago" status | | `environment` | `EnvironmentInfo` | | Environment info for non-production badge | | `slots` | `Record JSX.Element>` | | Named slot content | | `components` | `Record JSX.Element>` | | Custom component overrides | **Connected mode**: When `apiKey` is provided, the form automatically creates drafts, auto-saves, and submits to the FormDSL server. No `onSubmit` needed. --- ### `
` Groups questions into navigable steps. | Prop | Type | Default | Description | |------|------|---------|-------------| | `title` | `string` | required | Display title (shown in navigation) | | `id` | `string` | derived from `title` | Unique section ID | | `slug` | `string` | same as `id` | URL-friendly slug for deep linking | | `icon` | `JSX.Element` | | Icon in navigation/header | | `showIf` | `Condition` | | Conditional visibility (section skipped in nav when hidden) | | `variant` | `'default' \| 'plain' \| 'compact' \| 'highlighted'` | `'default'` | Visual style | | `fieldLayout` | `'stacked' \| 'horizontal'` | `'stacked'` | Label placement (`horizontal` = side-by-side) | ```tsx
``` --- ### `` Registers a form field. The `type` prop determines the field type and available props. #### Base Props (all field types) | Prop | Type | Default | Description | |------|------|---------|-------------| | `id` | `string` | required | Unique field identifier | | `type` | `FieldType` | required | Field type (see below) | | `label` | `string` | | Display label (supports markdown + `{{tokens}}`) | | `description` | `string` | | Help text below the field (supports markdown + `{{tokens}}`) | | `visualLabel` | `JSX.Element` | | JSX override for the visible label (string `label` still used for manifest/review/a11y) | | `visualDescription` | `JSX.Element` | | JSX override for the visible description | | `required` | `boolean` | `false` | Field is required | | `showIf` | `Condition` | | Conditional visibility | | `requiredIf` | `Condition` | | Conditionally required (overrides `required`) | | `disabledIf` | `Condition` | | Conditionally disabled | | `excludeFromCompletion` | `boolean` | `false` | Skip in completion percentage | | `commentable` | `boolean` | `false` | Allow user remarks/comments on this field | | `prefill` | `boolean` | `false` | Mark as prefillable from prior submissions | | `validationMessage` | `string` | | Custom validation error message (overrides defaults) | | `component` | `Component` | | Override the default field renderer for any field type | #### Field Types ##### `text` / `email` / `tel` / `phone` / `textarea` | Prop | Type | Default | Description | |------|------|---------|-------------| | `placeholder` | `string` | | Placeholder text | | `minLength` | `number` | | Minimum character length | | `maxLength` | `number` | | Maximum character length | | `pattern` | `string` | | Regex validation pattern | | `patternHint` | `string` | | Hint shown when pattern validation fails | | `format` | `TextFieldFormat` | | Preset input mask (see Masking section) | | `mask` | `string` | | Custom IMask pattern | | `masked` | `boolean` | | Obscure value on blur (auto-true for `ssn`, `itin`) | | `maskedVisibleChars` | `number` | | Chars visible from the end when masked | | `maskPlaceholder` | `string` | `'_'` | Placeholder char in mask | | `rows` | `number` | | Textarea rows | | `match` | `string` | | ID of another field whose value must match (e.g., confirm email) | ```tsx ``` ##### `number` | Prop | Type | Default | Description | |------|------|---------|-------------| | `min` | `number` | | Minimum value | | `max` | `number` | | Maximum value | | `step` | `number` | | Step increment | | `placeholder` | `string` | | Placeholder text | | `prefix` | `string` | | Text before number (e.g., `"$"`) | | `suffix` | `string` | | Text after number (e.g., `"sq ft"`) | | `thousandsSeparator` | `string` | `','` | Thousands separator | | `decimalSeparator` | `string` | `'.'` | Decimal separator | | `scale` | `number` | `0` | Decimal places | | `padFractionalZeros` | `boolean` | `false` | Pad with trailing zeros | | `formula` | `string` | | Computed formula (makes field read-only) | ```tsx ``` ##### `currency` | Prop | Type | Default | Description | |------|------|---------|-------------| | `currency` | `string` | `'USD'` | Currency code | | `symbol` | `string` | auto from code | Custom symbol | | `locale` | `string` | `'en-US'` | Locale | | `min` | `number` | | Minimum value | | `max` | `number` | | Maximum value | | `symbolPosition` | `'prefix' \| 'suffix'` | `'prefix'` | Symbol placement | | `thousandsSeparator` | `string` | `','` | Thousands separator | | `decimalSeparator` | `string` | `'.'` | Decimal separator | | `scale` | `number` | `2` | Decimal places | | `showCents` | `boolean` | `true` | Pad fractional zeros | | `placeholder` | `string` | | Placeholder text | | `formula` | `string` | | Computed formula (makes field read-only) | ```tsx ``` ##### `date` / `datetime` | Prop | Type | Default | Description | |------|------|---------|-------------| | `min` | `string` | | Minimum date (ISO string) | | `max` | `string` | | Maximum date (ISO string) | | `format` | `string` | | Display format | | `timezone` | `string` | | Timezone (`datetime` only) | ```tsx ``` ##### `time` | Prop | Type | Default | Description | |------|------|---------|-------------| | `min` | `string` | | Minimum time (HH:MM) | | `max` | `string` | | Maximum time (HH:MM) | ```tsx ``` ##### `year` | Prop | Type | Default | Description | |------|------|---------|-------------| | `min` | `number` | | Minimum year | | `max` | `number` | | Maximum year | | `placeholder` | `string` | | Placeholder | ##### `month` No additional props. ```tsx ``` ##### `select` / `radio` | Prop | Type | Default | Description | |------|------|---------|-------------| | `options` | `{ value: string, label: string, exclusive?: boolean }[]` | required | Choices | | `multiple` | `boolean` | `false` | Allow multiple selections (`select` only) | | `searchable` | `boolean` | `false` | Autocomplete input (`select` only) | ```tsx ``` ##### `multicheck` | Prop | Type | Default | Description | |------|------|---------|-------------| | `options` | `{ value: string, label: string, exclusive?: boolean }[]` | required | Choices | | `minSelect` | `number` | | Minimum selections | | `maxSelect` | `number` | | Maximum selections | The `exclusive` option clears all other selections when chosen (e.g., "None of the above"). ```tsx ``` ##### `boolean` / `checkbox` No additional props. Renders a toggle/checkbox. Value is `true`/`false`. ```tsx ``` ##### `yesno` | Prop | Type | Default | Description | |------|------|---------|-------------| | `yesLabel` | `string` | `"Yes"` | Custom yes label | | `noLabel` | `string` | `"No"` | Custom no label | ```tsx ``` ##### `rating` | Prop | Type | Default | Description | |------|------|---------|-------------| | `max` | `number` | `5` | Maximum rating | | `variant` | `'stars' \| 'numbers'` | `'stars'` | Display variant | ```tsx ``` ##### `file` | Prop | Type | Default | Description | |------|------|---------|-------------| | `accept` | `string` | | Accepted MIME types (e.g., `"image/*,.pdf"`) | | `maxSize` | `number` | | Max file size in bytes | | `multiple` | `boolean` | `false` | Allow multiple files | ```tsx ``` ##### `signature` No additional props. Renders a signature pad. ```tsx ``` ##### `tags` | Prop | Type | Default | Description | |------|------|---------|-------------| | `options` | `{ value: string, label: string }[]` | | Predefined tag options | | `maxTags` | `number` | | Maximum number of tags | | `allowCustom` | `boolean` | `true` | Allow free-text tags | | `placeholder` | `string` | | Placeholder | ```tsx ``` ##### `matrix` | Prop | Type | Default | Description | |------|------|---------|-------------| | `rows` | `{ id: string, label: string }[]` | required | Row definitions | | `columns` | `{ value: string, label: string }[]` | required | Column options | Table-style radio grid, commonly used for Likert scales. Stores `{ [rowId]: selectedColumnValue }`. ```tsx ``` ##### `url` | Prop | Type | Default | Description | |------|------|---------|-------------| | `placeholder` | `string` | | Placeholder text | ```tsx ``` ##### `geo` | Prop | Type | Default | Description | |------|------|---------|-------------| | `defaultZoom` | `number` | | Initial map zoom level | Stores `{ lat: number, lng: number }`. ##### `address` No additional props. Stores a structured address object. ##### `country` | Prop | Type | Default | Description | |------|------|---------|-------------| | `placeholder` | `string` | | Placeholder | Searchable country selector. Internally maps to `text`. ```tsx ``` ##### `ranking` | Prop | Type | Default | Description | |------|------|---------|-------------| | `options` | `{ value: string, label: string }[]` | required | Items to rank | Drag-and-drop reorderable list. Value is an ordered array. ```tsx ``` ##### `hidden` | Prop | Type | Default | Description | |------|------|---------|-------------| | `value` | `unknown` | required | Static value to store | Not rendered. Use for tracking data. ```tsx ``` ##### `custom` | Prop | Type | Default | Description | |------|------|---------|-------------| | `component` | `Component` | required | Custom field component | For custom field rendering. Not available on hosted pages. --- ### `` Repeatable group of fields. Users can add/remove items. | Prop | Type | Default | Description | |------|------|---------|-------------| | `id` | `string` | required | Unique repeat group ID | | `label` | `string` | | Group label | | `minItems` | `number` | | Minimum number of items | | `maxItems` | `number` | | Maximum number of items | | `showIf` | `Condition` | | Conditional visibility | | `excludeFromCompletion` | `boolean` | `false` | Skip in completion % | | `variant` | `'card' \| 'table'` | `'card'` | Display variant | | `itemLabel` | `string` | | Label template per item (supports `{{fieldId}}`, `{{index}}`, `{{index1}}`) | | `addButtonLabel` | `string \| { zero: string, oneOrMore: string }` | | Custom add button text | | `collapsible` | `boolean` | `false` | Edit/Done toggle (card variant) | | `startCollapsed` | `boolean` | `false` | New items start collapsed | | `forceEdit` | `boolean` | `false` | Always in edit mode | | `autoAddFirst` | `boolean` | `false` | Auto-add first item when empty | Children define the template for one item. ```tsx ``` **Nested repeats** are supported: ```tsx ``` --- ### `` Summary/review section. Always appears last in navigation. | Prop | Type | Default | Description | |------|------|---------|-------------| | `title` | `string` | `"Review"` | Section title | | `id` | `string` | `"review"` | Section ID | | `slug` | `string` | `"review"` | URL slug | | `icon` | `JSX.Element` | | Navigation icon | | `showIf` | `Condition` | | Conditional visibility | **Auto mode** (no children): generates a summary of all sections and fields automatically. **Custom mode** (with children): you control the layout using `` components. ```tsx {/* Auto mode */} {/* Custom mode */} ``` ### `` Read-only display of a field value. Used inside `` for custom layouts. | Prop | Type | Default | Description | |------|------|---------|-------------| | `id` | `string` | required | Field ID to display (must match a Question) | | `label` | `string` | | Override label | | `hideLabel` | `boolean` | `false` | Hide the label | | `showIf` | `Condition` | | Conditional visibility | --- ## Layout Components ### `` Horizontal layout for side-by-side fields. | Prop | Type | Default | Description | |------|------|---------|-------------| | `cols` | `number` | children count | Number of equal columns | | `gap` | `'sm' \| 'md' \| 'lg'` | `'md'` | Gap between columns | | `align` | `'start' \| 'center' \| 'end' \| 'stretch'` | `'stretch'` | Vertical alignment | | `compact` | `boolean` | `false` | Natural column widths, not stretched | | `showIf` | `Condition` | | Conditional visibility | ```tsx ``` ### `` Vertical layout with controlled spacing. | Prop | Type | Default | Description | |------|------|---------|-------------| | `gap` | `'sm' \| 'md' \| 'lg'` | `'md'` | Gap between items | | `showIf` | `Condition` | | Conditional visibility | ### `` Visual container with optional title. | Prop | Type | Default | Description | |------|------|---------|-------------| | `title` | `string` | | Card title | | `showIf` | `Condition` | | Conditional visibility | ```tsx ``` ### `` Conditional content block. Supports static children or dynamic render function. | Prop | Type | Default | Description | |------|------|---------|-------------| | `showIf` | `Condition` | | Conditional visibility | | `render` | `(ctx: FormStateContext) => JSX.Element` | | Dynamic render function | ```tsx {/* Static content, conditionally shown */} {/* Dynamic content using form state */} { const qty = (ctx.getAnswer('qty') as number) || 0 const price = (ctx.getAnswer('price') as number) || 0 return

Subtotal: ${(qty * price).toFixed(2)}

}} /> ``` ### `` Info/warning/error/success message box. | Prop | Type | Default | Description | |------|------|---------|-------------| | `variant` | `'info' \| 'warning' \| 'error' \| 'success'` | required | Visual style | | `title` | `string` | | Banner title | | `showIf` | `Condition` | | Conditional visibility | Children must be a string (supports markdown and `{{tokens}}`). ```tsx Filing jointly may provide more tax benefits for married couples. US residents must report worldwide income. ``` ### `` Visual horizontal separator. | Prop | Type | Default | Description | |------|------|---------|-------------| | `showIf` | `Condition` | | Conditional visibility | --- ## Navigation & UI Atoms These components control the form chrome. Place them at the top level inside ``, outside sections. ### `
` / `