

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

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

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

    const memberSchema = z.object({
      firstName: z.string().min(1, "Required"),
      lastName: z.string().min(1, "Required"),
      email: z.string().email(),
      role: z.enum(["admin", "member"]).default("member"),
      active: z.boolean().default(true),
    });

    const formDefs = [
      {
        kind: "field",
        name: "firstName",
        label: "First name",
        component: "text",
        size: "half",
      },
      {
        kind: "field",
        name: "lastName",
        label: "Last name",
        component: "text",
        size: "half",
      },
      {
        kind: "field",
        name: "email",
        label: "Email",
        component: "email",
        size: "full",
      },
      {
        kind: "field",
        name: "role",
        label: "Role",
        component: "select",
        options: [
          { value: "admin", label: "Admin" },
          { value: "member", label: "Member" },
        ],
        size: "full",
      },
      {
        kind: "field",
        name: "active",
        label: "Active",
        component: "switch",
        size: "full",
      },
    ] as const satisfies FormDefs;

    export default function BulkImport() {
      return (
        <FormBuilder.Bulk
          schema={memberSchema}
          formDefs={formDefs}
          template={{ filename: "members.csv" }}
          onSubmit={async ({ rows }) => {
            console.log("Importing", rows.length, "rows");
          }}
        />
      );
    }
    ```
  </Tab>
</Tabs>

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

1. **Same schema and formDefs** – Reuse the same definitions from `FormBuilder.Single`
2. **CSV ingestion** – Drop a file or paste tabular data
3. **Auto-mapping** – Headers match field `name` and `label` properties
4. **Validation** – Every row is validated against the Zod schema
5. **Submit rows** – `onSubmit` receives `{ rows }` with validated data

<Callout type="info">
  See the full [API Reference](/composites/form-builder/bulk#api-reference) for
  all available props including `parseOptions`, `mapping`, and `toolbar`.
</Callout>
