shadcn.io is not affiliated with official shadcn/ui
Profile Picture Dialog Block for React
A profile page with its picture dialog shown open: a large preview over an Upload tab that checks one PNG, JPG or WebP up to 2 MB and shows it without cropping, and a Drawings tab of eight greyscale patterns, with Remove picture and Save picture.
Installation
Overview
Let someone change their picture without a crop step, with this profile picture dialog for React with Base UI. It opens from the profile page of Staffnook, a staff directory: the page's header holds an outline Change photo Button, and the profile, a cover band, the round picture, the name and three stat boxes, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Dialog shows a large round preview, your initials until a picture is chosen, over two Tabs. Upload is a File Upload that takes one PNG, JPG or WebP of 2 MB or less, dropped or chosen with Browse; a file that is the wrong type or too big gets an Alert naming it. Drawings is a grid of eight greyscale patterns, rings, stripes, dots, waves, checks, rays, arcs and a grid, to use as a face. Remove picture goes back to initials, and Save picture, the only Shine Button, puts the choice on the drawn profile. For preview the dialog is drawn open in place when the page loads; the header button opens the real dialog, with the same choice. For directories, communities, accounts and any app with an avatar.
FAQ
Why is the dialog already open, and what do I keep?
So you can see it without a click. On load the dialog is a copy drawn in place over the profile: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Change photo button opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same PictureFields component and share the block's state, so a file chosen in the copy is there in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
Where does the chosen file go?
Nowhere. The file stays in your browser tab: the preview shows it through an object URL that the page makes and lets go of when you choose another file or close the page, so nothing is read by a server and nothing is uploaded. The type and the size are checked from the file's own properties, and a refusal says which rule failed and names the file. In your app upload the file to your storage on Save, check its type and size again on the server, and scan it before showing it to others.
Why is there no crop?
Because the picture is shown round by a circle that cuts the square or the oblong to its middle, the way most directories do, and this block is about choosing, uploading and removing. A cropping step belongs to its own dialog (see the related image crop block), and a camera needs a permission and a stream, which this demo never asks for.
Is it accessible from the keyboard?
Yes. The real dialog is named by its title and described by its sentence, focus starts on the first tab, and Escape, Cancel and the close button return focus to the Change photo button. The tabs move with the arrow keys; the drop area is a labelled region with a real Browse button that opens the file picker; the drawings are native radio buttons you can arrow through, each named by its pattern; and what changes is spoken once in a polite status line (inside the dialog while it is open). The trigger is passed to DialogTrigger through render, and the dialog is controlled with open and onOpenChange.
What stays local, and how do I wire it for real?
Everything. Saving changes this block's state and the drawn profile, and the drawings are paths in the file. In your app store which drawing or which uploaded file is the person's picture, serve it from your own storage, and keep a fallback to initials for anyone who has none.
How does it look on a phone?
The copy shown on load docks to the foot of the page as a bottom sheet with its buttons pinned and the content scrolling above them: the preview and Remove picture, then the tabs. The drawings stay in a grid of four across, and the real dialog keeps the Dialog's own phone layout, a sheet stuck to the bottom of the screen.
Related
- Pro
Avatar Upload Onboarding
Profile and accountA picture step split in two: the member's initials turn into a round cropper for a file chosen on the device, and the crop shows live at 96, 40 and 24 pixels.
- Pro
A profile page with its cover-crop dialog shown open: a drawn landscape in an image cropper with shape, zoom, turn and reset controls, and the same crop shown live as an avatar, a card thumbnail and a banner strip.
- Pro
Edit Profile Dialog
Account and securityA community profile page with its edit dialog shown open: a display name, a username checked against the names already taken, a main craft you type or pick, a bio with a 160 character count, and a strip of chips that says what changed.
- Pro
Add Profile Dialog
Account and securityA newsletter's writers page with its byline composer shown open: a name, what they write, a 120 character bio, a mark from six drawn glyphs or initials and a switch, beside a card that shows the byline as it will print.
- Pro
Media Upload Dialog
Media and widgetsA video library with its upload dialog shown open: a drop zone for images, video and audio that names the files it turns away and why, tiles for the ones that pass with a check each, bulk removal, a total and an Add button that puts the clips in the library.
- Pro
API Key Dialog
Account and securityA keys page with its create-key dialog shown open: a name, scopes and an expiry in the first step, then the secret shown once, masked behind an eye button, with a Copy button and a box that has to be ticked before Done.