Shadcn with Valibot
This example keeps the design-system boundary in the application. A local kit maps "Form, Please" control props and slots to shadcn-style components. Valibot provides the Standard Schema.
Install the adapter
npx shadcn@latest add r13v/form-please/shadcn-form-kitThe registry item installs form-please and copies the adapter into your
application. Install the schema library used by your form separately. This
example uses valibot.
npm install valibotThe item targets shadcn's Base UI implementation. Review the copied component imports when your project uses another style or customized component props. The adapter remains normal application source, so it can follow local aliases, styles, and signatures.
Try the workshop proposal
Change radio and switch values, move the sliders, search the comboboxes, choose calendar values, and edit the OTP. Submit to run the Valibot schema twice and receive transformed output.
Adapter surface
The local adapter defines native-shaped controls, Base UI option controls,
sliders, date pickers, comboboxes, an OTP control, and structural slots. Each
control uses the public ControlProps contract. The kit uses the public
createFormKit and defineControl functions. Its radio and combobox option
types mark their IDs with OptionValue<string>, so Valibot picklist fields
reject option values outside their inferred unions.
Copy the example
"use client"
import type { , } from "form-please"
import { } from "react"
import * as from "valibot"
import { as } from "../components/ui/form-please/shadcn-form-kit"
const = .({
: .(.(), .(3, "Use at least three characters")),
: .(
.(),
.(20, "Explain the workshop in at least 20 characters"),
),
: .(["design", "engineering", "leadership"]),
: .(.(), .(6), .(80)),
: .(),
: .(),
: .(),
: .(.()),
: .(["studio", "remote", "hybrid"]),
: .(),
: .(.(), .(30), .(180)),
: .([.(), .()]),
: .(.()),
: .(),
: .(.()),
: .(),
: .({
: .(.()),
: .(.()),
}),
: .(
.(),
.(/^\d{6}$/, "Enter the six-digit invite code"),
),
})
type = <typeof >
type = <typeof >
const = {
: [
{ : "design", : "Design" },
{ : "engineering", : "Engineering" },
{ : "leadership", : "Leadership" },
],
: [
{
: "studio",
: "Studio",
: "A facilitated, in-person room.",
},
{
: "remote",
: "Remote",
: "A live online session.",
},
{
: "hybrid",
: "Hybrid",
: "One room with remote participants.",
},
],
: [
{ : "north-studio", : "North studio" },
{ : "library-lab", : "Library lab" },
{ : "remote-room", : "Remote room" },
],
: [
{ : "research", : "Research" },
{ : "prototyping", : "Prototyping" },
{ : "facilitation", : "Facilitation" },
{ : "systems", : "Systems thinking" },
],
} as
const = .(, {
: [
{
: "section",
: "proposal",
: "Workshop proposal",
: "Native controls rendered with local shadcn primitives.",
: 2,
: [
{
: "field",
: "title",
: "text",
: "Title",
: true,
: { : "Designing useful constraints" },
},
{
: "field",
: "track",
: "select",
: "Track",
: .,
},
{
: "field",
: "abstract",
: "textarea",
: "Abstract",
: true,
: { : 4 },
},
{
: "field",
: "capacity",
: "number",
: "Capacity",
: { : 6, : 80, : 1 },
},
{
: "field",
: "proposalDate",
: "date",
: "Proposal date",
},
{
: "field",
: "startsAt",
: "time",
: "Preferred start time",
: { : 900 },
},
{
: "field",
: "accessibilityReview",
: "checkbox",
: "Request an accessibility review",
},
{
: "field",
: "brief",
: "file",
: "Optional brief",
: { : ".pdf,.md,text/markdown,application/pdf" },
},
],
},
{
: "section",
: "experience",
: "Session experience",
: "Base UI option controls and each slider value shape.",
: 2,
: [
{
: "field",
: "format",
: "radio",
: "Format",
: .,
},
{
: "field",
: "recordingAllowed",
: "switch",
: "Allow a recording",
: { : "sm" },
},
{
: "field",
: "duration",
: "slider",
: "Duration",
: "One numeric value, in minutes.",
: {
: 30,
: 180,
: 15,
: { : "unit", : "minute" },
},
},
{
: "field",
: "audienceRange",
: "rangeSlider",
: "Audience experience range",
: "A fixed two-number tuple.",
: { : 0, : 10, : 1, : 2 },
},
{
: "field",
: "agendaCheckpoints",
: "multiSlider",
: "Agenda checkpoints",
: "An arbitrary array of numeric thumbs.",
: { : 0, : 100, : 5 },
},
],
},
{
: "section",
: "schedule",
: "Discovery and schedule",
: "Searchable options, calendar values, and OTP input.",
: 2,
: [
{
: "field",
: "venue",
: "combobox",
: "Venue",
: .,
: {
: "Search venues",
: true,
},
},
{
: "field",
: "topics",
: "multiCombobox",
: "Topics",
: .,
: {
: "Add topics",
},
},
{
: "field",
: "workshopDate",
: "datePicker",
: "Workshop date",
: {
: "Pick a date",
: "dropdown",
: [
{ : "2027-04-09", : "Spring lab" },
{ : "2027-09-17", : "Autumn lab" },
],
},
},
{
: "field",
: "availability",
: "dateRangePicker",
: "Travel availability",
: { : 2 },
},
{
: "field",
: "inviteCode",
: "inputOtp",
: "Invite code",
: true,
: {
: 6,
: [3, 3],
: true,
: "^\\d*$",
: "one-time-code",
},
},
],
},
],
})
const = {
: "Designing useful constraints",
:
"A practical session for turning product constraints into focused experiments.",
: "design",
: 24,
: "2026-08-02",
: "10:00",
: true,
: ,
: "studio",
: false,
: 90,
: [2, 7],
: [20, 50, 80],
: "north-studio",
: ["research", "prototyping"],
: "2027-04-09",
: { : "2027-04-07", : "2027-04-11" },
: "104729",
} satisfies
export function () {
const [, ] = <>()
const = .(, {
,
({ }) {
()
},
})
let = "Submit the proposal to validate it with Valibot."
if ( !== ) {
= `${.} is ready for ${.} participants.`
}
return (
<
="Shadcn with Valibot workshop example"
="grid gap-4"
>
<. ="grid gap-4" ={}>
<.>Submit proposal</.>
</.>
< ="polite" ="text-sm text-muted-foreground">
{}
</>
</>
)
}Read Form kits for the control and slot contracts.
Review the registry manifest
and adapter source
before adapting them to your project. Append a matching Git release tag to the
registry item reference, such as #vX.Y.Z, when an installation must be
reproducible.