Media gallery
A library of generated images and videos: filter by kind, a square grid grouped by day, a full-screen viewer and multi-select.
On this page
Filter images and videos, open the viewer, and select several with Shift for a range.
Installation
Usage
import { MediaGallery } from "@/components/ui/chatcn/media-gallery"
<MediaGallery
items={library} // { id, kind: "image" | "video", src, posterSrc?, alt, prompt?, createdAt?, duration? }
loading={isLoading}
onDownload={(items) => zipAndDownload(items)}
onDelete={(items) => remove(items.map((item) => item.id))}
/>Tiles show the poster for videos, so the grid never loads video files. Day headings appear when items have createdAt; pass now to pin them in tests and screenshots. The viewer is built on the shared Dialog and plays videos with the same player as video generation.
Examples
Loading and empty
Placeholder tiles while the library loads, and the empty state per filter.
Props
| Prop | Type | Notes |
|---|---|---|
items | MediaItem[] | Sorted newest first |
loading | boolean | Placeholder tiles, no counts |
filter, defaultFilter, onFilterChange | "all" | "image" | "video" | |
selected, defaultSelected, onSelectedChange | string[] | Item ids |
onDownload, onDelete | (items: MediaItem[]) => void | Each shows its button |
groupByDay | boolean | On when items have createdAt |
now | Date | Reference for Today and Yesterday |
Keyboard
| Key | Action |
|---|---|
← → ↑ ↓ | Move through the grid. Columns follow the layout |
Home, End | First or last item |
Enter | Open the viewer |
Space | Select or deselect. Shift+Space selects a range |
⌘A / Ctrl+A | Select everything in view |
Esc | Clear the selection |
← → in the viewer | Previous or next item |
Accessibility
- One tile is in the tab order at a time; arrows move focus. Each tile's name says whether it opens or selects and whether it is selected.
- Clicking a tile opens it, and once anything is selected a click selects instead. Shift and Command or Control clicks select without opening.
- The filter is a toggle group with counts, and the selection count is announced politely.
- The selection circle is a pointer shortcut; keyboard users press Space on the tile.
Motion
- Tiles do not scale or lift on hover; a light tint appears over 150 ms on fine pointers only.
- Selection rings and the toolbar swap instantly: they are frequent and often keyboard driven.
- The viewer opens with the shared dialog motion, and paging swaps instantly.