shadcn.io is not affiliated with official shadcn/ui
Gallery Grid File Upload Block for React Aria
A wedding album editor: a grid of drawn photos with captions under each and a Cover badge on one, and a detail rail for the chosen photo with a 120-character caption, Make cover and Remove with Undo.
Installation
Overview
Caption and curate an album in one place, with this gallery upload for React with React Aria. It is the album editor of Albumine, a tool for wedding photographers. A hairline frame with a plus mark on each corner holds a grid of drawn photos on shared hairlines, each with its caption under it (or "No caption") and a Cover badge on the one that opens the album. Choosing a photo fills the detail rail beside the grid: the photo drawn in its own ratio (portrait, square, landscape or wide), its name and size, a Textarea in a Field for the caption with a count out of 120, Make cover and Remove. One photo is the cover at a time; Make cover moves it. A removed photo stays in its slot as a dashed "Removed" cell with Undo, so the grid never shifts. Add photos, the only colored control, and a file dropped on the grid use File Upload; the album holds twelve slots. The bands are ruled by Guides, with a CSS entrance only. For album tools, portfolios and any editor where each picture carries a caption.
FAQ
Why is the detail a rail and not a dialog?
So the grid and the caption are on screen together: you type a caption and watch it appear under the tile at once. Below the medium breakpoint the rail stacks under the grid, still at the same width as the page. If your albums run to hundreds of photos, a bottom Drawer for the detail on phones is a small change: render the same Details content inside it.
How does the cover work?
cover holds one id. Make cover sets it, and the badge moves to that tile. Removing the cover hands the badge to the first photo that remains; Undo brings the photo back but not the badge, so the album never has two. Make cover on the cover says so in the status line and changes nothing.
What are the rules for a caption?
It holds up to 120 characters; the field stops there and the count under it reads "42 of 120". The caption is saved to the block's state as you type and the status line confirms it when you leave the field. Tiles show it in two lines at most, and "No caption" in muted text when there is none.
Where do the four ratios come from?
Each photo is typed with a ratio, and the detail frame draws the picture at that shape inside a fixed-height box, so the rail never changes height. Picked files get a ratio in turn, since their dimensions are never read. In your app, set the ratio from the image's natural size.
What stays local, and how do I wire it up?
All of it. The block never opens a picked file: it draws a scene chosen from the name and lists its name and size. Captions, the cover and removals live in state and a reload restores the eight typed photos. To wire it, send files to your server, store the caption and a cover flag with each, and delete on the server when Remove is confirmed.
Is it accessible?
Every tile is a button named for its file ("ceremony-arch.jpg, the cover"), the chosen one carries aria-current, and the caption field has a visible label and its count as a description. Removing moves focus to the slot's Undo button; Undo moves it back to the tile. One polite status line speaks each change.