@form-wire/shadcn
shadcn/ui
Pass your local shadcn primitives into Form Wire and keep the form runtime separate.
Provider setup@form-wire/shadcn
import { createShadcnMapper } from "@form-wire/shadcn"
import { FormWireProvider } from "@form-wire/react"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
import { Checkbox } from "@/components/ui/checkbox"
import { Button } from "@/components/ui/button"
export const mapper = createShadcnMapper({
Input,
Textarea,
Checkbox,
Button,
Field,
FieldLabel,
FieldDescription,
FieldError,
})
export function Providers({ children }) {
return (
<FormWireProvider mapper={mapper}>
{children}
</FormWireProvider>
)
}The rest of this page reuses one set of Form Wire examples.
Swapping the mapper changes the UI library. The schemas, actions, field names, conditional sections, and wizard composition stay the same.
01 / Simple contact formsource
One schema creates a complete accessible form with validation, defaults, and an action.
const Contact = createFormWire(
z.object({
name: z.string().min(2),
email: z.email(),
message: z.string().min(10),
}),
{
fields: {
message: { component: "textarea" },
},
},
)
<Contact.Form action={saveContact} />Outputshadcn
02 / Common field coveragesource
Text, number, date, select, checkbox, textarea, submit state, and form messages use the same mapper.
const Quote = createFormWire(
z.object({
company: z.string().min(2),
plan: z.enum(["starter", "team", "enterprise"]),
seats: z.coerce.number().min(1),
launchDate: z.coerce.date(),
needsSecurityReview: z.boolean(),
notes: z.string().optional(),
})
)
<Quote.Form action={requestQuote} />Outputshadcn
03 / Conditional compositionsource
Use generated fields directly when you need custom flow without giving up schema inference.
<Onboarding.Form
action={submitOnboarding}
validationTiming="onChange"
>
<Onboarding.Fields names={["projectName", "projectType"]} />
<Onboarding.When field="projectType" equals="customer">
<Onboarding.Field name="customerEmail" />
</Onboarding.When>
<Onboarding.Fields names={["budget", "approved"]} />
</Onboarding.Form>Outputshadcn
04 / Multi-step wizardsource
Wizard steps share the same action and schema while Form Wire handles per-step rendering.
<WorkspaceWizard.Wizard
action={launchWorkspace}
nextLabel="Next step"
previousLabel="Back"
>
<WorkspaceWizard.Step title="Basics">
<WorkspaceWizard.Fields names={["workspace", "ownerEmail"]} />
</WorkspaceWizard.Step>
<WorkspaceWizard.Step title="Plan">
<WorkspaceWizard.Fields names={["tier", "timeline"]} />
</WorkspaceWizard.Step>
</WorkspaceWizard.Wizard>Outputshadcn