

<Tabs items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview">
    <Preview name="SingleMinimalSignInExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    "use client";

    import { z } from "zod";
    import { FormBuilder } from "@tilt-legal/cubitt-components/composites";

    const schema = z.object({
      email: z.string().email("Invalid email"),
      password: z.string().min(8, "At least 8 characters"),
      tags: z.array(z.string()).default([]),
      phone: z.string().optional(),
    });

    const formDefs = [
      {
        kind: "field",
        name: "email",
        label: "Email",
        component: "email",
        size: "full",
        inputProps: { autoComplete: "email" },
      },
      {
        kind: "field",
        name: "password",
        label: "Password",
        component: "text",
        size: "full",
        inputProps: { autoComplete: "current-password" },
      },
      {
        kind: "field",
        name: "tags",
        label: "Tags",
        component: "tags",
        size: "full",
      },
      {
        kind: "field",
        name: "phone",
        label: "Phone",
        component: "phone",
        size: "full",
      },
    ] as const satisfies FormDefs;

    export default function SignInForm() {
      return (
        <FormBuilder.Single
          schema={schema}
          formDefs={formDefs}
          defaultValues={{ email: "", password: "", tags: [], phone: "" }}
          submitLabel="Sign in"
          onSubmit={async (values) => console.log(values)}
        />
      );
    }
    ```
  </Tab>
</Tabs>

## How It Works [#how-it-works]

1. **Define a Zod schema** – Describes the shape and validation rules for your form data
2. **Create formDefs** – Flat array of field definitions with `component` types matching your inputs
3. **Render FormBuilder.Single** – Pass schema, formDefs, defaultValues, and onSubmit

<Callout type="info">
  See the full [API Reference](/composites/form-builder/single#api-reference)
  for all available props.
</Callout>
