Skip to content

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

Free

Profile Edit Form for React

Profile settings that open prefilled with username, email, a counted bio, and a website, plus Cancel.

The form opens on johndoe, john@example.com, a short bio, and https://johndoe.com. The bio counts toward 160. A filled website must be a valid URL. Cancel does not submit.

Use it to edit a profile that already exists. A blank profile should start empty on each Input. In React, Base UI does not load the saved values.

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>
    <div className="flex flex-col gap-1">
      <h3 className="font-medium text-lg">Profile Settings</h3>
      <p className="text-muted-foreground text-sm">
        Update your profile information
      </p>
    </div>
    <Controller
      control={form.control}
      name="username"
      render={({ field, fieldState }) => (
        <Field invalid={fieldState.invalid}>
          <FieldLabel htmlFor="profile-edit-form-username">
            Username
          </FieldLabel>
          <Input
            {...field}
            id="profile-edit-form-username"
            placeholder="johndoe"
          />
          <FieldDescription>
            This is your public display name.
          </FieldDescription>
          <FieldError>{fieldState.error?.message}</FieldError>
        </Field>
      )}
    />
    <Controller
      control={form.control}
      name="email"
{/* The rest of the file is under Installation. */}

FAQ

What is already filled in?

defaultValues sets the username johndoe, the email john@example.com, the bio "Software developer passionate about building great products." and the website https://johndoe.com. Load your user's saved values there, or pass them to form.reset once they arrive.

What still has to pass on save?

username is .min(3) with "Username must be at least 3 characters.", email is z.email("Please enter a valid email address."), bio is .max(160) with "Bio must not exceed 160 characters.", and website is z.url("Please enter a valid URL.") or an empty string.

How does the bio counter work?

The bio's FieldDescription prints field.value.length followed by /160 characters, so it updates on every keystroke. The 160 limit itself is checked on save.

What do the other descriptions say?

Username: "This is your public display name." Email: "Your email address is not publicly visible." Website: "Your personal website or portfolio."

What does Cancel do?

Nothing yet: it's a type="button" outline button with no handler, so it never submits. Call form.reset() to restore the saved values, or close the page or dialog.

What does Save Changes log?

Save Changes is the type="submit" button. form.handleSubmit(onSubmit) logs { bio, email, username, website } to the console once the schema passes.

API Reference

Field

Sets invalid={fieldState.invalid}, htmlFor="profile-edit-form-username", htmlFor="profile-edit-form-email", htmlFor="profile-edit-form-bio", htmlFor="profile-edit-form-website" and orientation="horizontal". The rest is on the Field page.

Input

Sets field, id="profile-edit-form-username", placeholder="johndoe", id="profile-edit-form-email", placeholder="john@example.com" and type="email". The rest is on the Input page.

Textarea

Sets field, id="profile-edit-form-bio", placeholder="Tell us about yourself" and rows={4}. The rest is on the Textarea page.

Button

Sets type="submit", type="button" and variant="outline". The rest is on the Button page.