Skip to content

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

Free

Edit Profile Dialog for Solid

An Edit Profile dialog with a gradient cover, Margaret Villard's photo, her name, a username with a check, a website, and a bio count.

UI library: Ark UI

Edit Profile opens Edit profile. A gradient cover has buttons to change or remove it, and Margaret Villard's photo overlaps the corner. The fields show Margaret, Villard, margaret-villard-69 with a check, a website prefixed https://, and a biography with characters left.

Use it to edit a profile without a settings page. The check does not look the name up. A longer editor fits a Sheet. In Solid, Ark UI does not save the profile.

Preview

Preview width

Installation

MCP · Pro
Make your AI a shadcn expert
Your agent installs components, builds pages and restyles your app from one prompt, in Claude Code, Cursor or VS Code.
Part of Pro

Anatomy

Dialog anatomy: content, title, description, close, footer

Usage

<Dialog>
      <DialogTrigger asChild={props => <Button {...props()} variant="outline">Edit Profile</Button>} />
      <DialogContent class="gap-0 p-0 sm:max-w-2xl">
        <DialogHeader class="px-6 py-4">
          <DialogTitle>Edit profile</DialogTitle>
        </DialogHeader>
        <div class="relative">
          <div class="h-40 bg-linear-to-r from-primary/30 via-primary/15 to-muted" />
          <div class="absolute end-4 top-4 flex gap-2">
            <Button aria-label="Change cover image" pill size="icon-sm" variant="secondary">
              <ImageIcon aria-hidden="true" />
            </Button>
            <Button aria-label="Remove cover image" pill size="icon-sm" variant="secondary">
              <XIcon aria-hidden="true" />
            </Button>
          </div>
          <div class="absolute start-6 -bottom-12">
            <Avatar class="size-24 ring-4 ring-background">
              <AvatarImage alt="Margaret Villard" src="https://github.com/shadcn.png" />
              <AvatarFallback>MV</AvatarFallback>
            </Avatar>
            <Button aria-label="Change profile photo" class="absolute end-0 bottom-0" pill size="icon-sm">
              <ImageIcon aria-hidden="true" />
            </Button>
          </div>
        </div>
        <FieldGroup class="px-6 pt-16 pb-6">
          <div class="grid grid-cols-2 gap-4">
            <Field>
              <FieldLabel>First name</FieldLabel>
              <Input value="Margaret" name="first-name" type="text" />
{/* The rest of the file is under Installation. */}

FAQ

How do the image buttons upload?

They're icon buttons with an aria-label and no handler. Have each open a hidden file input with accept="image/*", preview the file, and upload it when people save.

Does the check mean the username is available?

It's a static text-success check in an InputGroupAddon. Check availability as people type, with a short debounce, and swap the icon for a spinner or an error while it runs.

How does the character counter work?

The textarea is controlled with maxLength of 200, and a FieldDescription under it shows 200 minus the current length.

How is the https:// prefix built?

An InputGroup with the InputGroupInput and an InputGroupAddon holding InputGroupText. The addon comes after the input in the markup, so clicking it focuses the input, and align="inline-start" shows it first.

How do I warn about unsaved changes?

Compare the values with what you loaded and, when someone closes with changes, ask before discarding. Control the dialog to intercept the close. Pass open and update it in onOpenChange, which receives { open }.

How is the cover styled?

A soft gradient of the theme's primary color, bg-linear-to-r from-primary/30 via-primary/15 to-muted, so it works in light and dark mode. Replace it with the person's image.

API Reference

Dialog

Sets asChild and props. The rest is on the Dialog page.

Button

Sets props, variant="outline", aria-label="Change cover image", pill, size="icon-sm" and variant="secondary". The rest is on the Button page.

Avatar

Sets alt="Margaret Villard" and src="https://github.com/shadcn.png". The rest is on the Avatar page.

Field

No extra props in this demo. The rest is on the Field page.

Input

Sets value="Margaret", name="first-name", type="text", value="Villard" and name="last-name". The rest is on the Input page.

Input Group

Sets name="username", onInput={handleUsernameChange}, type="text", value={username()}, align="inline-end" and value="www.margaret.com". The rest is on the Input Group page.

Textarea

Sets maxLength={maxBioLength}, name="bio", onInput={handleBioChange} and value={bio()}. The rest is on the Textarea page.