Appearance
DSL Reference
Complete API reference for FormDSL's JSX components. Both @formdsl/react and @formdsl/solid share an identical API.
tsx
// React
import { Form, Section, Question, Row, Card, Banner, Repeat, Review } from '@formdsl/react'
// SolidJS
import { Form, Section, Question, Row, Card, Banner, Repeat, Review } from '@formdsl/solid'<Form>
Root container. Handles collection, rendering, state, navigation, and submission.
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | required | Unique form identifier |
version | string | — | Form version string |
title | string | — | Form title (shown in header) |
onSubmit | (answers, inputLog, remarks?) => void | — | Submission handler |
onSave | (answers, inputLog, remarks?) => void | — | Manual save handler |
initialAnswers | Record<string, unknown> | — | 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 (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<void> | — | Auto-save handler |
enableRouting | boolean | false | URL-based section routing |
basePath | string | — | Base path for URL routing |
blockNavigation | boolean | false | Prevent navigation until current section 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 |
Connected mode props
| Prop | Type | Default | Description |
|---|---|---|---|
apiKey | string | — | Publishable key (fpk_*) — enables connected mode |
serverUrl | string | window.location.origin | Server URL |
identityToken | string | — | JWT for identity verification |
onSubmitSuccess | (result) => void | — | Called after successful server submit |
onFormStateReady | (formState) => void | — | Called when form state is initialized |
onManifestReady | (manifest) => void | — | Called when manifest is built |
Advanced props
| Prop | Type | Default | Description |
|---|---|---|---|
series | string | — | Series slug for prefill grouping |
prefill | 'all' | 'partial' | — | Prefill from prior submissions in series |
detectStaleSession | boolean | false | Enable stale tab detection |
staleThreshold | number | 60000 | Time in ms before session is stale |
showSaveStatus | boolean | false | Show "Last saved X ago" status |
environment | EnvironmentInfo | — | Environment info for non-prod badge |
slots | Record<string, (ctx) => JSX.Element> | — | Named slot content |
components | Record<string, (props) => JSX.Element> | — | Custom component overrides |
<Section>
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 when hidden) |
variant | 'default' | 'plain' | 'compact' | 'highlighted' | 'default' | Visual style |
fieldLayout | 'stacked' | 'horizontal' | 'stacked' | Label placement |
<Question>
Registers a form field. The type prop determines the field type and available sub-props.
Base props (all field types)
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | required | Unique field identifier |
type | FieldType | required | Field type |
label | string | — | Display label (supports markdown + {{tokens}}) |
description | string | — | Help text below field (supports markdown + {{tokens}}) |
required | boolean | false | Field is required |
showIf | Condition | — | Conditional visibility |
requiredIf | Condition | — | Conditionally required |
disabledIf | Condition | — | Conditionally disabled |
excludeFromCompletion | boolean | false | Skip in completion percentage |
commentable | boolean | false | Allow user remarks on this field |
prefill | boolean | false | Prefillable from prior submissions |
validationMessage | string | — | Custom validation error message |
component | Component | — | Override the default field renderer |
visualLabel | JSX.Element | — | JSX override for visible label |
visualDescription | JSX.Element | — | JSX override for visible description |
Field types
text / email / tel / phone / textarea
| Prop | Type | Description |
|---|---|---|
placeholder | string | Placeholder text |
minLength | number | Minimum character length |
maxLength | number | Maximum character length |
pattern | string | Regex validation pattern |
patternHint | string | Hint when pattern fails |
format | TextFieldFormat | Preset input mask |
mask | string | Custom IMask pattern |
masked | boolean | Obscure value on blur |
maskedVisibleChars | number | Chars visible when masked |
rows | number | Textarea rows |
match | string | ID of field whose value must match |
Format presets: ssn, ein, phone, zip, zip4, routingNumber, itin, canadianPostal, mmyy, mmddyyyy, isoDate, time24, measurement.
number
| Prop | Type | Description |
|---|---|---|
min / max | number | Value range |
step | number | Step increment |
prefix / suffix | string | Display text (e.g., "$", "sq ft") |
thousandsSeparator | string | Default ',' |
decimalSeparator | string | Default '.' |
scale | number | Decimal places (default 0) |
padFractionalZeros | boolean | Pad trailing zeros |
formula | string | Computed formula (makes field read-only) |
placeholder | string | Placeholder text |
currency
| Prop | Type | Description |
|---|---|---|
currency | string | Currency code (default 'USD') |
symbol | string | Custom symbol |
locale | string | Locale (default 'en-US') |
min / max | number | Value range |
symbolPosition | 'prefix' | 'suffix' | Symbol placement |
scale | number | Decimal places (default 2) |
showCents | boolean | Pad fractional zeros (default true) |
formula | string | Computed formula |
placeholder | string | Placeholder text |
date / datetime
| Prop | Type | Description |
|---|---|---|
min / max | string | Bounds (ISO string) |
format | string | Display format |
timezone | string | Timezone (datetime only) |
time
| Prop | Type | Description |
|---|---|---|
min / max | string | Bounds (HH:MM) |
year
| Prop | Type | Description |
|---|---|---|
min / max | number | Year range |
placeholder | string | Placeholder |
month
No additional props.
select / radio
| Prop | Type | Description |
|---|---|---|
options | { value, label, exclusive? }[] | required — choices |
multiple | boolean | Multiple selections (select only) |
searchable | boolean | Autocomplete (select only) |
multicheck
| Prop | Type | Description |
|---|---|---|
options | { value, label, exclusive? }[] | required — choices |
minSelect / maxSelect | number | Selection count bounds |
The exclusive flag on an option clears all other selections when chosen.
boolean / checkbox
No additional props. Renders a toggle/checkbox. Value is true/false.
yesno
| Prop | Type | Description |
|---|---|---|
yesLabel | string | Custom yes label (default "Yes") |
noLabel | string | Custom no label (default "No") |
rating
| Prop | Type | Description |
|---|---|---|
max | number | Maximum rating (default 5) |
variant | 'stars' | 'numbers' | Display variant |
file
| Prop | Type | Description |
|---|---|---|
accept | string | MIME types (e.g., "image/*,.pdf") |
maxSize | number | Max file size in bytes |
multiple | boolean | Allow multiple files |
signature
No additional props. Renders a signature pad.
tags
| Prop | Type | Description |
|---|---|---|
options | { value, label }[] | Predefined tag options |
maxTags | number | Maximum tags |
allowCustom | boolean | Allow free-text tags (default true) |
placeholder | string | Placeholder |
matrix
| Prop | Type | Description |
|---|---|---|
rows | { id, label }[] | required — row definitions |
columns | { value, label }[] | required — column options |
Stores { [rowId]: selectedColumnValue }.
ranking
| Prop | Type | Description |
|---|---|---|
options | { value, label }[] | required — items to rank |
Value is an ordered array.
url
| Prop | Type | Description |
|---|---|---|
placeholder | string | Placeholder |
country
| Prop | Type | Description |
|---|---|---|
placeholder | string | Placeholder |
Searchable country selector.
geo
| Prop | Type | Description |
|---|---|---|
defaultZoom | number | Initial map zoom level |
Stores { lat: number, lng: number }.
hidden
| Prop | Type | Description |
|---|---|---|
value | unknown | required — static value to store |
Not rendered. Use for tracking data.
custom
| Prop | Type | Description |
|---|---|---|
component | Component | required — custom field component |
<Repeat>
Repeatable group of fields. Users add/remove items.
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | required | Unique repeat group ID |
label | string | — | Group label |
minItems / maxItems | number | — | Item count bounds |
showIf | Condition | — | Conditional visibility |
variant | 'card' | 'table' | 'card' | Display variant |
itemLabel | string | — | Per-item label (supports {{fieldId}}, {{index}}, {{index1}}) |
addButtonLabel | string | { zero, oneOrMore } | — | Custom add button text |
collapsible | boolean | false | Edit/Done toggle |
startCollapsed | boolean | false | New items start collapsed |
autoAddFirst | boolean | false | Auto-add first item when empty |
excludeFromCompletion | boolean | false | Skip in completion % |
Nested repeats are supported.
<Review>
Summary/review section. Always appears last in navigation.
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | "Review" | Section title |
id | string | "review" | Section ID |
icon | JSX.Element | — | Navigation icon |
showIf | Condition | — | Conditional visibility |
No children = auto-generated summary of all sections and fields.
With children = custom layout using <Answer> components.
<Answer>
Read-only display of a field value. Used inside <Review>.
| Prop | Type | Description |
|---|---|---|
id | string | required — field ID to display |
label | string | Override label |
hideLabel | boolean | Hide the label |
showIf | Condition | Conditional visibility |
Layout components
<Row>
Horizontal layout for side-by-side fields.
| Prop | Type | Default | Description |
|---|---|---|---|
cols | number | children count | Equal columns |
gap | 'sm' | 'md' | 'lg' | 'md' | Gap between columns |
align | 'start' | 'center' | 'end' | 'stretch' | 'stretch' | Vertical alignment |
compact | boolean | false | Natural column widths |
showIf | Condition | — | Conditional visibility |
<Stack>
Vertical layout with controlled spacing.
| Prop | Type | Default | Description |
|---|---|---|---|
gap | 'sm' | 'md' | 'lg' | 'md' | Gap between items |
showIf | Condition | — | Conditional visibility |
<Card>
Visual container with optional title.
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Card title |
showIf | Condition | — | Conditional visibility |
<Banner>
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 + {{tokens}}).
<Content>
Conditional content block. Static children or dynamic render function.
| Prop | Type | Description |
|---|---|---|
showIf | Condition | Conditional visibility |
render | (ctx: FormStateContext) => JSX.Element | Dynamic render |
<Divider>
Horizontal separator. Supports showIf.
Navigation & UI atoms
Place these at the top level inside <Form>, outside sections.
| Component | Description | Key Props |
|---|---|---|
<Header> / <Footer> | Top/bottom containers | showIf |
<SidebarNav> / <StepperNav> | Section navigation | showLabels |
<FormContent> | Active section content area | — |
<FormTitle> | Form title | text (override) |
<ProgressBar> | Completion indicator | label, scope, sectionId |
<AutoSaveStatus> | "Saving..."/"Saved" indicator | — |
<NavActions> | Back/next/submit bar | submitLabel, saveLabel, backLabel, nextLabel |
<SaveButton> | Save button | label, showIf |
<SubmitButton> | Submit button | label, showIf |
<BackButton> | Back button | label, showIf |
<NextButton> | Next button | label, submitLabel, showIf |
<Slot> | Host content injection | name, showIf |
Custom layout example
tsx
<Form id="wizard" navigation="sidebar" title="Application" autoSave>
<Header>
<FormTitle />
<AutoSaveStatus />
<SaveButton label="Save Draft" />
<SubmitButton />
</Header>
<SidebarNav />
<FormContent />
<Section title="Step 1">
<Question id="name" type="text" required label="Name" />
</Section>
<Section title="Step 2">
<Question id="email" type="email" required label="Email" />
</Section>
<Review />
</Form>Conditions
Control visibility (showIf), requirement (requiredIf), and disabled state (disabledIf). Uses MongoDB-style operators.
Syntax
tsx
// Equality
showIf={{ country: "US" }}
// Multiple values (OR)
showIf={{ country: ["US", "CA", "MX"] }}
// Operators
showIf={{ age: { gte: 18 } }}
showIf={{ income: { gt: 0, lte: 1000000 } }}
// Multiple fields (AND)
showIf={{ country: "US", age: { gte: 18 } }}
// Boolean
showIf={{ hasDependents: true }}
// Logical OR
showIf={{ $or: [{ country: "US" }, { days: { gte: 183 } }] }}
// Logical NOT
showIf={{ $not: { country: "US" } }}
// Array membership (multicheck/tags)
showIf={{ interests: { in: ["sports"] } }}
showIf={{ interests: { nin: ["excluded"] } }}Operators
| Operator | Description |
|---|---|
eq | Equals |
ne | Not equals |
gt / gte | Greater than (or equal) |
lt / lte | Less than (or equal) |
in | Value in array |
nin | Value not in array |
$or | Any condition matches |
$not | Condition does not match |
Dot notation
For nested fields (inside repeats): showIf={{ "spouse.employed": true }}.
Formulas
Computed fields that auto-calculate. Available on number and currency types. Makes the field read-only.
tsx
<Question id="total" type="currency" label="Total"
formula="{{qty}} * {{price}}" />Functions
| Function | Description |
|---|---|
SUM(a, b, c) | Sum of values |
COUNT(a, b, c) | Count of non-empty values |
MIN(a, b) / MAX(a, b) | Min/max |
IF(cond, then, else) | Conditional |
ROUND(val, decimals) | Round |
Token interpolation
{{fieldId}} tokens work in label, description, itemLabel, and Banner content.
| Token | Description |
|---|---|
{{fieldId}} | Current value of a field |
{{index}} | 0-based repeat item index |
{{index1}} | 1-based repeat item index |
Labels and descriptions support inline markdown: **bold**, *italic*, `code`, [link](url).
Embed / mount API
Mount a FormDSL form into any DOM element (works outside React/SolidJS apps):
tsx
// React
import { mount } from '@formdsl/react/embed'
const unmount = mount(document.getElementById('form-root'), {
formComponent: ContactForm,
// ...form props
})
// Later: unmount()Stylesheet
Import once in your app entry:
tsx
import '@formdsl/react/styles' // React
import '@formdsl/solid/styles' // SolidJSSee the theming guide for CSS variables, layers, and custom themes.