shadcn.io is not affiliated with official shadcn/ui
Backup Restore File Upload Block for Vue
A backup restore shown open over a Backups page: the file's own name is read for environment, date and engine, four checks run on it and its size, and Restore stays off until the database name is typed.
Installation
Overview
Make the backup prove it belongs before anything is replaced, with this restore dialog for Vue with Ark UI. It opens from the Backups page of Hearthstore, hosting for small shops: the header holds an outline Restore from a file Button, and the page itself is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Alert Dialog holds a File Upload drop zone and three typed samples (production, staging and a 2.4 GB file). A file's name is read for real: hearthstore-prod-2026-10-02.sql.gz becomes environment, date, engine and compression, and four checks run on it: the name, the target, the age and the picked size against the 2 GB restore limit. A backup from staging stops the restore with "This backup is from staging; you are restoring into production." The action is the catalog Button in its destructive variant, with no Shine Button in the block; it stays quiet until every check passes and the database name is typed exactly. Confirming draws a "Restored" banner on the page and says "Restored in this demo; nothing was changed." For preview the alert is drawn open in place when the page loads; the header button opens the real Alert Dialog with the same fields. For databases, storage and any restore that can overwrite live data.
FAQ
Why is the alert already open, and what do I keep?
So you can see it without a click. On load the alert is a copy drawn in place over the page: a native dialog element with the alertdialog role that isn't modal, so nothing is trapped or focused. The Restore from a file button opens the real Alert Dialog, modal, with its focus trap, Escape and focus on Cancel, and the copy stays closed until a reload. Both show the same RestoreFields and share the block's state. In your app keep the Alert Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
How is the file name read?
With one pattern: app, then environment (prod, staging or dev), then an ISO date, then the engine (sql, dump or sqlite), then an optional compression (gz, zst or zip). A name that does not match stops the restore and shows the pattern. The app must be Hearthstore's, the environment must be production because that is the target, and a date after today is refused. A date older than the 30 days Hearthstore keeps is a note, not a stop.
Is the size check real?
Yes. It uses the real byte size of the file you pick, compared with the 2 GB limit, and says how far over a larger file is. The file is never opened: nothing here reads its contents, so a real restore must still validate the file on the server. The three samples are typed and carry their own sizes.
Why type the database name?
Because a restore replaces what is there and cannot be undone. Restore is quiet (marked aria-disabled, so it stays focusable) until the checks pass and hearthstore_prod matches exactly; pressed too early it names what is missing and moves focus there. The line under the field says Matches or Does not match as you type.
What stays local, and how do I wire it?
Everything. Restoring changes nothing: it closes the alert, draws the banner behind it and says so in a polite message. To wire it, upload the file to your server, validate and restore it there inside a transaction or on a copy, show real progress, and keep the dialog busy until your server answers.
Where does focus go, and how does it close?
The real alert opens with focus on Cancel, never on the destructive action, so a stray Enter backs out. Escape and Cancel close it and return focus to the Restore from a file button; clicking outside does not close it, since an alert has to be answered. After a confirmed restore focus returns to the same button about 300 ms later.