Skip to content

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.

PropTypeDefaultDescription
idstringrequiredUnique form identifier
versionstringForm version string
titlestringForm title (shown in header)
onSubmit(answers, inputLog, remarks?) => voidSubmission handler
onSave(answers, inputLog, remarks?) => voidManual save handler
initialAnswersRecord<string, unknown>Pre-populate answers
initialInputLogInputLogEntry[]Resume from existing input log
navigation'none' | 'sidebar' | 'stepper' | 'tabs''none'Multi-section navigation mode
theme'default' | 'printed''default'Visual theme
compactbooleanfalseReduced spacing
width'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Form width (480/640/800/1000/1200px)
submitLabelstring"Submit"Submit button text
nextLabelstring"Continue"Next button text
backLabelstring"Back"Back button text
ctaLabelstringCTA button text (e.g., "Save For Later")
hideActionsbooleanfalseHide navigation buttons
autoSavebooleanfalseEnable auto-save
autoSaveDelaynumber1500Auto-save debounce (ms)
saveIndicator'checkmark' | 'toast' | 'none''toast'Auto-save feedback style
onAutoSave(answers, inputLog, remarks?) => void | Promise<void>Auto-save handler
enableRoutingbooleanfalseURL-based section routing
basePathstringBase path for URL routing
blockNavigationbooleanfalsePrevent navigation until current section is valid
readOnlybooleanfalseRead-only mode
previewbooleanfalsePreview mode
debugbooleanfalseShow debug panel
classstringCSS class on form root

Connected mode props

PropTypeDefaultDescription
apiKeystringPublishable key (fpk_*) — enables connected mode
serverUrlstringwindow.location.originServer URL
identityTokenstringJWT for identity verification
onSubmitSuccess(result) => voidCalled after successful server submit
onFormStateReady(formState) => voidCalled when form state is initialized
onManifestReady(manifest) => voidCalled when manifest is built

Advanced props

PropTypeDefaultDescription
seriesstringSeries slug for prefill grouping
prefill'all' | 'partial'Prefill from prior submissions in series
detectStaleSessionbooleanfalseEnable stale tab detection
staleThresholdnumber60000Time in ms before session is stale
showSaveStatusbooleanfalseShow "Last saved X ago" status
environmentEnvironmentInfoEnvironment info for non-prod badge
slotsRecord<string, (ctx) => JSX.Element>Named slot content
componentsRecord<string, (props) => JSX.Element>Custom component overrides

<Section>

Groups questions into navigable steps.

PropTypeDefaultDescription
titlestringrequiredDisplay title (shown in navigation)
idstringderived from titleUnique section ID
slugstringsame as idURL-friendly slug for deep linking
iconJSX.ElementIcon in navigation/header
showIfConditionConditional 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)

PropTypeDefaultDescription
idstringrequiredUnique field identifier
typeFieldTyperequiredField type
labelstringDisplay label (supports markdown + {{tokens}})
descriptionstringHelp text below field (supports markdown + {{tokens}})
requiredbooleanfalseField is required
showIfConditionConditional visibility
requiredIfConditionConditionally required
disabledIfConditionConditionally disabled
excludeFromCompletionbooleanfalseSkip in completion percentage
commentablebooleanfalseAllow user remarks on this field
prefillbooleanfalsePrefillable from prior submissions
validationMessagestringCustom validation error message
componentComponentOverride the default field renderer
visualLabelJSX.ElementJSX override for visible label
visualDescriptionJSX.ElementJSX override for visible description

Field types

text / email / tel / phone / textarea

PropTypeDescription
placeholderstringPlaceholder text
minLengthnumberMinimum character length
maxLengthnumberMaximum character length
patternstringRegex validation pattern
patternHintstringHint when pattern fails
formatTextFieldFormatPreset input mask
maskstringCustom IMask pattern
maskedbooleanObscure value on blur
maskedVisibleCharsnumberChars visible when masked
rowsnumberTextarea rows
matchstringID of field whose value must match

Format presets: ssn, ein, phone, zip, zip4, routingNumber, itin, canadianPostal, mmyy, mmddyyyy, isoDate, time24, measurement.

number

PropTypeDescription
min / maxnumberValue range
stepnumberStep increment
prefix / suffixstringDisplay text (e.g., "$", "sq ft")
thousandsSeparatorstringDefault ','
decimalSeparatorstringDefault '.'
scalenumberDecimal places (default 0)
padFractionalZerosbooleanPad trailing zeros
formulastringComputed formula (makes field read-only)
placeholderstringPlaceholder text

currency

PropTypeDescription
currencystringCurrency code (default 'USD')
symbolstringCustom symbol
localestringLocale (default 'en-US')
min / maxnumberValue range
symbolPosition'prefix' | 'suffix'Symbol placement
scalenumberDecimal places (default 2)
showCentsbooleanPad fractional zeros (default true)
formulastringComputed formula
placeholderstringPlaceholder text

date / datetime

PropTypeDescription
min / maxstringBounds (ISO string)
formatstringDisplay format
timezonestringTimezone (datetime only)

time

PropTypeDescription
min / maxstringBounds (HH:MM)

year

PropTypeDescription
min / maxnumberYear range
placeholderstringPlaceholder

month

No additional props.

select / radio

PropTypeDescription
options{ value, label, exclusive? }[]required — choices
multiplebooleanMultiple selections (select only)
searchablebooleanAutocomplete (select only)

multicheck

PropTypeDescription
options{ value, label, exclusive? }[]required — choices
minSelect / maxSelectnumberSelection 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

PropTypeDescription
yesLabelstringCustom yes label (default "Yes")
noLabelstringCustom no label (default "No")

rating

PropTypeDescription
maxnumberMaximum rating (default 5)
variant'stars' | 'numbers'Display variant

file

PropTypeDescription
acceptstringMIME types (e.g., "image/*,.pdf")
maxSizenumberMax file size in bytes
multiplebooleanAllow multiple files

signature

No additional props. Renders a signature pad.

tags

PropTypeDescription
options{ value, label }[]Predefined tag options
maxTagsnumberMaximum tags
allowCustombooleanAllow free-text tags (default true)
placeholderstringPlaceholder

matrix

PropTypeDescription
rows{ id, label }[]required — row definitions
columns{ value, label }[]required — column options

Stores { [rowId]: selectedColumnValue }.

ranking

PropTypeDescription
options{ value, label }[]required — items to rank

Value is an ordered array.

url

PropTypeDescription
placeholderstringPlaceholder

country

PropTypeDescription
placeholderstringPlaceholder

Searchable country selector.

geo

PropTypeDescription
defaultZoomnumberInitial map zoom level

Stores { lat: number, lng: number }.

hidden

PropTypeDescription
valueunknownrequired — static value to store

Not rendered. Use for tracking data.

custom

PropTypeDescription
componentComponentrequired — custom field component

<Repeat>

Repeatable group of fields. Users add/remove items.

PropTypeDefaultDescription
idstringrequiredUnique repeat group ID
labelstringGroup label
minItems / maxItemsnumberItem count bounds
showIfConditionConditional visibility
variant'card' | 'table''card'Display variant
itemLabelstringPer-item label (supports {{fieldId}}, {{index}}, {{index1}})
addButtonLabelstring | { zero, oneOrMore }Custom add button text
collapsiblebooleanfalseEdit/Done toggle
startCollapsedbooleanfalseNew items start collapsed
autoAddFirstbooleanfalseAuto-add first item when empty
excludeFromCompletionbooleanfalseSkip in completion %

Nested repeats are supported.


<Review>

Summary/review section. Always appears last in navigation.

PropTypeDefaultDescription
titlestring"Review"Section title
idstring"review"Section ID
iconJSX.ElementNavigation icon
showIfConditionConditional 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>.

PropTypeDescription
idstringrequired — field ID to display
labelstringOverride label
hideLabelbooleanHide the label
showIfConditionConditional visibility

Layout components

<Row>

Horizontal layout for side-by-side fields.

PropTypeDefaultDescription
colsnumberchildren countEqual columns
gap'sm' | 'md' | 'lg''md'Gap between columns
align'start' | 'center' | 'end' | 'stretch''stretch'Vertical alignment
compactbooleanfalseNatural column widths
showIfConditionConditional visibility

<Stack>

Vertical layout with controlled spacing.

PropTypeDefaultDescription
gap'sm' | 'md' | 'lg''md'Gap between items
showIfConditionConditional visibility

<Card>

Visual container with optional title.

PropTypeDefaultDescription
titlestringCard title
showIfConditionConditional visibility

Info/warning/error/success message box.

PropTypeDefaultDescription
variant'info' | 'warning' | 'error' | 'success'requiredVisual style
titlestringBanner title
showIfConditionConditional visibility

Children must be a string (supports markdown + {{tokens}}).

<Content>

Conditional content block. Static children or dynamic render function.

PropTypeDescription
showIfConditionConditional visibility
render(ctx: FormStateContext) => JSX.ElementDynamic render

<Divider>

Horizontal separator. Supports showIf.


Place these at the top level inside <Form>, outside sections.

ComponentDescriptionKey Props
<Header> / <Footer>Top/bottom containersshowIf
<SidebarNav> / <StepperNav>Section navigationshowLabels
<FormContent>Active section content area
<FormTitle>Form titletext (override)
<ProgressBar>Completion indicatorlabel, scope, sectionId
<AutoSaveStatus>"Saving..."/"Saved" indicator
<NavActions>Back/next/submit barsubmitLabel, saveLabel, backLabel, nextLabel
<SaveButton>Save buttonlabel, showIf
<SubmitButton>Submit buttonlabel, showIf
<BackButton>Back buttonlabel, showIf
<NextButton>Next buttonlabel, submitLabel, showIf
<Slot>Host content injectionname, 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

OperatorDescription
eqEquals
neNot equals
gt / gteGreater than (or equal)
lt / lteLess than (or equal)
inValue in array
ninValue not in array
$orAny condition matches
$notCondition 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

FunctionDescription
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.

TokenDescription
{{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'   // SolidJS

See the theming guide for CSS variables, layers, and custom themes.