Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Multi Step File Upload Block for Radix UI

A project page with a side sheet that adds files in three steps, Files, Options and Review, with switches, a destination folder and a derived summary; shown open in place and opened for real from the header.

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

Keep a long upload in one place instead of three pages, with this side sheet for React with Radix UI. It opens from the project page of Embarkly, project uploads for a studio tool: the header holds an outline Upload to a project Button, and the page itself, a grid of drawn file tiles, sits under a soft scrim inside a hairline frame with a plus mark on each corner. The Sheet shows Steps for Files, Options and Review. Files is a File Upload drop zone over the list, with two files typed to start. Options are Switch rows for Compress images, Strip location data and Make private, and a Native Select for the destination folder. Review is a Data List worked out from the first two. The foot's Next is the only Shine Button and becomes "Upload 3 files" on the last step; Back and Cancel are outline. Finishing adds dashed tiles to the page behind the sheet. For preview the sheet is drawn open in place at the end of the frame when the page loads; the header button opens the real Sheet, with the same steps. For studio tools, asset managers and any app where an upload has settings.

FAQ

Why is the sheet already open, and what do I keep?

So you can see it without a click. On load the sheet is a copy drawn in place at the end of the frame: a native dialog element that isn't modal, so nothing is trapped, hidden or focused. The Upload to a project button opens the real Sheet, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same FlowBody and FlowFoot components and share the block's state. In your app keep the Sheet and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.

How do the steps work?

The strip shows the rungs reached and the three panes share one cell, so the sheet never changes height between steps. Only the current pane can be reached by keyboard or screen reader. Next moves on and says "Step 2 of 3: Options" in the polite status line; Back goes one step, and on the first step it reads Cancel and closes the sheet.

What if there are no files?

Remove both starting files and Next waits: its text stays readable, it is marked as unavailable, and pressing it says "Add at least one file to continue" and puts focus on the drop zone. The list holds up to eight files of 100 MB; a refusal says why.

Do the options do anything?

No. Compress images, Strip location data and Make private are choices kept in the block's state and repeated in the review. Nothing is compressed, stripped, uploaded or saved. In your app pass them to your upload call and apply them on the server.

Which side does the sheet open from?

From the end of the page's reading direction: the right in a left-to-right page and the left in a right-to-left one. The sheet's own sides are physical, so sideOf reads the page's direction when the sheet opens. On a phone the copy docks to the foot of the frame as a bottom sheet, and the real sheet is full width.

Is it accessible from the keyboard?

Yes. The real sheet is named by its title and described by its sentence, focus stays inside until it closes, and Escape, Cancel and the close button return focus to Upload to a project. The trigger is the button wrapped in SheetTrigger with asChild, and the sheet is controlled with open and onOpenChange. The copy shown on load moves no focus; Escape inside it, Cancel and its close button close it and put focus on the button.