Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

Settings Form for React

App settings with language and theme selects, notification switches, and two-factor, opened on saved defaults.

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, Base UI does not remember the defaults. The form's initial values do.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

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 htmlFor="settings-form-language">
              Language
            </FieldLabel>
            <Select
              items={languages}
              name={field.name}
              onValueChange={(next) => field.onChange(next ?? "")}
              value={field.value || null}
            >
              <SelectTrigger className="w-full" id="settings-form-language">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {languages.map((item) => (
                  <SelectItem key={item.value} value={item.value}>
                    {item.label}
                  </SelectItem>
{/* 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." Select takes items, value={field.value || null}, and onValueChange stores the next value.

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={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.

How are the sections split?

A Preferences heading with a muted line, the two selects in a FieldGroup, then two FieldSets with the FieldLegends Notifications and Security. Each switch row is a horizontal Field with rounded-lg border p-4, its label and description in FieldContent.

What does Save Settings log?

Save Settings is a type="submit" button. form.handleSubmit(onSubmit) logs all six values to the console. Save them to your API or local storage from there.

API Reference

Field

Sets htmlFor="settings-form-language", htmlFor="settings-form-theme", orientation="horizontal", htmlFor, settings-form- and notification. The rest is on the Field page.

Select

Sets items={languages}, name={field.name}, onValueChange, next, id="settings-form-language" and value={item.value}. The rest is on the Select page.

Switch

Sets checked={field.value}, id, settings-form-, notification, name and name={field.name}. The rest is on the Switch page.

Button

Sets type="submit". The rest is on the Button page.