Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Profile Picture Dialog Block for Vue

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.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Let someone change their picture without a crop step, with this profile picture dialog for Vue with Ark 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 the button wrapped in DialogTrigger with asChild, 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.