shadcn.io is an independent project built on shadcn/ui
Language starts on English and theme on System. Email and security alerts start on, marketing starts off, and two-factor starts off. Each switch sits on a bordered row.
Use it for an account preferences page. One on or off setting can be a lone Switch. In React, Ark UI does not remember the defaults. The form's initial values do.
Installation
Usage
<form className="w-full max-w-2xl" onSubmit={form.handleSubmit(onSubmit)}>
<FieldGroup className="gap-8">
<div className="flex flex-col gap-1">
<h3 className="font-medium text-lg">Preferences</h3>
<p className="text-muted-foreground text-sm">
Manage your application preferences
</p>
</div>
<FieldGroup className="gap-4">
<Controller
control={form.control}
name="language"
render={({ field }) => (
<Field>
<FieldLabel>Language</FieldLabel>
<Select
collection={languages}
name={field.name}
onValueChange={({ value }) => field.onChange(value[0] ?? "")}
value={field.value ? [field.value] : []}
>
<SelectTrigger className="w-full">
<SelectValue />
</SelectTrigger>
<SelectContent>
{languages.items.map((item) => (
<SelectItem item={item} key={item.value}>
{item.label}
</SelectItem>
))}
</SelectContent>
{/* The rest of the file is under Installation. */}FAQ
What is selected when the form opens?
defaultValues sets the language to en, the theme to system, email notifications and security alerts on, and marketing emails and two-factor authentication off.
How do language and theme write back to the form?
Each is a Controller with a Select and a FieldDescription: "Choose your preferred language." and "Select your preferred theme." The options are a createListCollection; value is [field.value] and onValueChange stores value[0].
How is each switch connected?
The three notification rows come from one notifications array mapped to a Controller each; Two-Factor Authentication has its own. Switch takes checked, and onCheckedChange passes checked to field.onChange.
What does the schema actually reject?
Almost nothing: language and theme are z.string() and the four switches z.boolean(), and every control always holds a valid value, so there are no FieldErrors. Narrow the selects with z.enum if the server needs it.
API Reference
Field
Sets orientation="horizontal". The rest is on the Field page.
Select
Sets collection={languages}, name={field.name}, onValueChange, value, item={item} and collection={themes}. The rest is on the Select page.
Switch
Sets checked={field.value}, name={field.name}, onCheckedChange and checked. The rest is on the Switch page.
Button
Sets type="submit". The rest is on the Button page.





