Single
Preview

Schema-driven single-record forms with grouped layouts, conditional fields, and wizard steps.

FormBuilder.Single renders one form from a Zod schema and formDefs. It owns the Cubitt field UI, form wiring, conditional visibility, validation display, and optional stepper controls.

Usage

import { z } from "zod";
import {
  FormBuilder,
  type FormDefs,
} from "@tilt-legal/cubitt-components/form-builder";
const schema = z.object({
  email: z.string().email("Invalid email"),
  password: z.string().min(8, "At least 8 characters"),
});

const formDefs = [
  {
    kind: "field",
    name: "email",
    label: "Email",
    component: "email",
    size: "full",
  },
  {
    kind: "field",
    name: "password",
    label: "Password",
    component: "text",
    size: "full",
  },
] as const satisfies FormDefs;
<FormBuilder.Single
  defaultValues={{ email: "", password: "" }}
  formDefs={formDefs}
  onSubmit={async (values) => {
    await signIn(values);
  }}
  schema={schema}
  submitLabel="Sign in"
/>

Examples

Minimal Sign-In

Grouped Layout

Conditional Logic

Multi-Step Wizard

Stepper Navigation

External Submit

API Reference

PropTypeDefaultDescription
schemaz.ZodTypeAny-Zod schema used for validation and type inference
formDefsFormDefs<T>-Step, group, and field definitions
onSubmit(values: T) => FormSubmitResult-Submit handler. Return a ZodError to display server validation
defaultValuesPartial<T>{}Initial TanStack Form values
defaultStepnumber | string-Initial step index or step id
validateOnBackbooleanfalseValidate the current step before moving backward
titlestring-Optional heading rendered above the form
descriptionstring-Optional description rendered under the heading
disabledbooleanfalseDisable fields, stepper actions, and the default submit button
idstring-Form id for external submit buttons
submitLabelstring | null"Submit"Built-in submit button label. Pass null to hide
footerReactNode-Content rendered after fields before submit controls
stepperfalse | StepperRender<T>-Hide, replace, or extend the default stepper controls
groupClassNamestring-Layout class for group wrappers
itemClassNamestring-Layout class for field containers
classNamestring-Layout class for the form element
submitRefRef<() => void>-Imperative submit function
formRefRef<AnyReactFormApi>-Underlying TanStack Form instance

Stepper Hook

FormBuilder.Single.useStepper() returns a handle for external navigation.

PropertyTypeDescription
state.indexnumberCurrent visible step index
state.totalnumberTotal visible steps
state.isFirstbooleanWhether the first visible step is active
state.isLastbooleanWhether the last visible step is active
state.disabledbooleanMirrors the form disabled state
state.stepFormStep | nullActive step definition
actions.next() => Promise<boolean>Validate and advance
actions.previous() => Promise<boolean>Move backward
actions.goTo(target: number | string) => Promise<boolean>Move to a step index or id
actions.submit() => Promise<boolean>Validate current step and submit
actions.reset() => voidReset to the first step
render(slot) => ReactNodePass to the stepper prop

On this page