Skip to main content
View as Markdown

Multi-Step Forms

Long forms are easier to complete when they are broken into manageable pieces. The layout property chooses how a form's fields are presented: all at once, split into steps with previous/next navigation, or one field per screen Typeform-style. Steps support conditional skipping and branching so the path through the form can adapt to the submitter's answers.

forms:
  - id: 1
    name: onboarding
    title: Set up your workspace
    layout: multi-step
    submitTo: { table: workspaces }
    fields:
      - { kind: standalone, name: workspace_name, inputType: short-text, required: true }
      - { kind: standalone, name: team_size, inputType: number }
      - { kind: standalone, name: use_case, inputType: long-text }
    steps:
      - { id: basics, title: The basics, fields: [workspace_name] }
      - { id: team, title: Your team, fields: [team_size] }
      - { id: goals, title: Your goals, fields: [use_case] }

Layout Modes

Mode Description
single-page All fields on one page (default). Steps are ignored.
multi-step Fields grouped into steps[] with previous/next navigation.
one-question One field per screen, advancing automatically. Driven by the same steps[] model.

Step Definitions

When layout is multi-step or one-question, the steps array partitions the form's fields into ordered screens. Each step references field names defined in the parent fields array.

Property Description
id Unique step id within the form (kebab-case recommended, ≤64 chars). Required.
title Step title shown above the fields.
description Step intro paragraph.
fields Field names belonging to this step. Each must match a field's name (standalone/calculation/signature) or column (table-field). At least one.
visibleWhen Whole-step visibility rule. When false, the entire step is skipped. Uses the conditional shape.
goToWhen Branching rules. The first matching rule jumps to its goTo step instead of the linear next step.

By default a multi-step form advances linearly: step 1 → step 2 → step 3. Two mechanisms override that flow.

Skip a step with a step-level visibleWhen — when the condition is false the step is removed from the sequence entirely.

Branch to a different step with goToWhen. Each rule has a when condition and a goTo target step id; the first matching rule wins, otherwise linear flow continues.

steps:
  - id: plan
    title: Choose a plan
    fields: [plan]
    goToWhen:
      # Enterprise plans skip self-serve billing and route to a sales step
      - when: { field: plan, operator: eq, value: enterprise }
        goTo: sales
  - id: billing
    title: Payment
    fields: [card_number]
  - id: sales
    title: Talk to sales
    fields: [company, seats]
    # only relevant for enterprise; hidden otherwise
    visibleWhen: { field: plan, operator: eq, value: enterprise }

One-Question-at-a-Time

The one-question layout presents a single field per screen for a focused, conversational experience. It reuses the same steps[] model — typically one field per step — and the same visibleWhen / goToWhen branching applies.

forms:
  - id: 2
    name: survey
    title: Quick survey
    layout: one-question
    submitTo: { storeSubmission: true }
    display:
      progressBar: true
    fields:
      - {
          kind: standalone,
          name: nps,
          inputType: rating,
          label: How likely are you to recommend us?,
        }
      - {
          kind: standalone,
          name: reason,
          inputType: long-text,
          label: What's the main reason for your score?,
        }
    steps:
      - { id: q1, fields: [nps] }
      - { id: q2, fields: [reason] }

Display Overrides

The display object adjusts how the form looks without affecting submission semantics.

Property Description
columns Number of columns the fields are arranged in (1–4). Applies to single-page and per-step layouts.
progressBar Show a progress bar in multi-step / one-question layouts. No effect on single-page.
submitLabel Submit button label (Submit by default). Supports $t: keys.
theme Per-form overrides: primaryColor, backgroundColor, borderRadius.
forms:
  - id: 3
    name: registration
    title: Event registration
    layout: multi-step
    display:
      columns: 2
      progressBar: true
      submitLabel: Complete registration
      theme:
        primaryColor: '#4f46e5'
        borderRadius: 0.5rem
    submitTo: { table: registrations }
    fields:
      - { kind: table-field, column: first_name, required: true }
      - { kind: table-field, column: last_name, required: true }
      - { kind: table-field, column: email, required: true }
      - { kind: table-field, column: dietary_notes }
    steps:
      - { id: name, title: Your name, fields: [first_name, last_name] }
      - { id: contact, title: Contact & preferences, fields: [email, dietary_notes] }