A form field that holds one image: pick it from the library or drop a file, preview, replace, remove, crop to a ratio (non-destructive or as a new copy), set a focal point and a per-use alt text. Warns about missing alt text and low resolution. For featured images, social cards, logos, profile photos and block props.
Alt textWhite villa with a pool terrace at dusk
Shown on the blog index and in link previews.
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 { ImageField } from "@vamos-ui/react/media";
<Field label="Featured image">
<ImageField aspect="16/9" recommended={{ width: 1200, height: 630 }} value={cover} onChange={setCover} />
</Field>The empty state is a real button (and a drop target); the filled preview is the Replace button and Remove is separate, both labelled. The chosen alt text is shown under the preview.
The focal marker is a focusable 2-D control: aria-roledescription “focal point”, aria-valuetext “horizontal 62%, vertical 40%”; arrows step 1%, Shift + arrows 10%, Home centres.
Save as copy needs a same-origin or CORS-enabled image; otherwise the dialog explains that the image must be uploaded to the library first.
Examples
Round avatar (HR profile)
shape="round" + size="sm" (96px) + layout="inline"; crop locks to 1:1.
Alt textSelin Kaya, Head of Sales
Focal point
FocalPointPicker on its own: drag, or arrows (Shift for 10%), with live 1:1, 16:9 and 4:5 previews.
Click or drag on the image, or use the arrow keys (Shift for bigger steps), to mark the part that must stay in view when the image is cropped.
focalPoint = {"x":0.62,"y":0.48}Crop modes
metadata keeps the file and stores a rect for the loader; copy uploads a cropped file.
Alt textRenovated kitchen with a marble island
crop: noneAlt textDining room with pendant lights and wooden tables
file: bistro-dining-room.jpgIn a form with validation (CRM)
Field passes label, hint, error and required; name posts the asset id.
API
ImageField
| Prop | Type | Default |
|---|---|---|
value / defaultValue / onChange{ asset, alt?, focal?, crop? } — alt and focal override the asset per use; crop is a name or a rect. | ImageFieldValue | null | — |
aspectPreview ratio and default crop ratio. | ImageAspect ("16/9", "1/1", "1.91/1", number…) | "16/9" ("1/1" round) |
cropPresetsRatio buttons in the crop dialog; name stores asset.crops[name]. | { label; value: number; name? }[] | — |
recommendedShows a hint, and a warning when the image is smaller. | { width; height } | — |
shaperound for avatars. | "rect" | "round" | "rect" |
size96px avatar · card (22rem) · container width. | "sm" | "md" | "full" | "md" |
layoutinline puts actions and alt text beside the preview. | "stacked" | "inline" | "stacked" |
focalFocal point tool. | boolean | true (rect) |
croptrue offers both modes when the adapter can edit (else copy). | boolean | "metadata" | "copy" | true |
requireAltThe picker asks for alt text; the field warns while it is missing. | boolean | false |
acceptPicker filter and drop restriction. | string | "image/*" |
disabled / readOnly / required / invalidAlso read from a surrounding Field. | boolean | — |
nameHidden input with the asset id for native forms. | string | — |
adapterDefault: MediaProvider. | MediaAdapter | — |
labelsBuilt-in strings (dictionary namespace imageField). | Partial<ImageFieldLabels> | — |
FocalPointPicker
| Prop | Type | Default |
|---|---|---|
srcThe image. | string | MediaAsset | — |
value / defaultValue / onValueChange0..1 in image space (not mirrored in RTL). | { x: number; y: number } | — |
onValueCommitOnce per drag or key press (autosave). | (point) => void | — |
previewsLive crop previews. | false | ("1/1" | "16/9" | "4/5" | "4/3" | "1.91/1" | "3/2")[] | ["1/1","16/9","4/5"] |
maxHeightImage stage height. | number | string | "20rem" |
disabled / labelsDictionary namespace focalPoint. | boolean · Partial<FocalPointLabels> | — |
Social image with a low-res warning
recommended={{ width: 1200, height: 630 }} warns below that size; the crop preset named og is stored as asset.crops.og.
Alt textLaptop showing a sales dashboard
Low resolution: 640 × 360 px. Recommended at least 1,200 × 630.
Recommended 1,200 × 630 px or larger
Used by LinkedIn, X and WhatsApp previews.