A dialog that picks one or more files for a field: featured image, gallery blocks, company logo, profile photo, document attachment. Library, Upload and From URL tabs; new uploads are selected automatically; a selection tray, a pluralised confirm button, an optional alt-text check, and an imperative useMediaPicker() for code paths.
Installation
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { MediaPicker } from "@vamos-ui/react/media";
<MediaPicker accept="image/*" confirmLabel="Set featured image" onSelect={([asset]) => setCover(asset)}>
<Button>Set featured image</Button>
</MediaPicker>Focus starts in the search field. The selection count is announced (“2 files selected”). Ctrl/⌘ + Enter confirms.
Files dropped on the Upload tab go to the library and are selected as they finish.
The embedded library is drawn flat inside the dialog, so the dialog stays the only glass layer.
Examples
Multiple with a limit (listing gallery)
multiple + max: tiles beyond the limit are disabled, the button reads “Insert 3 images”.
Imperative (CRM company logo)
const [asset] = await pick({ accept }) — resolves [] when cancelled. Needs MediaPickerProvider once.
From URL
Shown when the adapter implements sideload; the imported file is added to the library and selected.
Require alt text
Images without alt text get an inline field or Decorative before Insert is enabled; the text is saved to the library.
API
MediaPicker
| Prop | Type | Default |
|---|---|---|
open / defaultOpen / onOpenChangeControlled or uncontrolled; or pass a trigger as children. | boolean | — |
childrenTrigger element (DialogTrigger asChild). | ReactNode | — |
onSelectOn confirm, in selection order. | (assets: MediaAsset[]) => void | — |
multiple / maxSeveral files, with an optional limit. | boolean · number | false |
accept"image/*": library filter and upload restriction; also switches copy to “image(s)”. | string | — |
valuePreselected asset ids (loaded with getMany). | string[] | — |
title / confirmLabelDialog title and confirm text. Default “Select image” / “Insert 2 images” (plural rules per locale). | string | — |
tabsTabs and their order. | ("library" | "upload" | "url")[] | library, upload (+ url with sideload) |
requireAltAsk for alt text before confirming. | boolean | false |
size720px · 1080px with the details panel · full screen. | "md" | "lg" | "full" | "lg" |
adapterDefault: MediaProvider. | MediaAdapter | — |
labels / libraryLabelsBuilt-in strings (dictionary namespace mediaPicker). | Partial<MediaPickerLabels> · Partial<MediaLibraryLabels> | — |
MediaPickerProvider
| Prop | Type | Default |
|---|---|---|
adapterOptional; default MediaProvider. | MediaAdapter | — |
childrenThe app. | ReactNode | — |
useMediaPicker()
| Prop | Type | Default |
|---|---|---|
→Same options as MediaPicker without open/onSelect. | (options?: MediaPickOptions) => Promise<MediaAsset[]> | — |