A picture with labelled, selectable spots — rooms on a floor plan, parts of a product, buildings on a campus map. Each spot is a real button placed in % of the picture; pick one (a radio group) or several (toggle buttons), with a tooltip, an optional callout, or your own detail panel.
Recording studio
4 seats · Booth, two condenser mics
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 { ImageHotspots } from "@vamos-ui/react";
<ImageHotspots aria-label="Third floor" aspectRatio={16 / 10} hotspots={rooms} value={room} onValueChange={setRoom}>
<img src="/plans/floor-3.svg" alt="" />
</ImageHotspots>One tab stop; arrow keys go to the nearest spot in that direction, Home / End to the first / last, Escape clears.
Coordinates are physical (the picture does not mirror in RTL); left / right arrows follow the reading direction.
For geographic coordinates use pin-map.
Examples
Product parts
numbered markers and the default callout (label + description).
Steam valve
- Handle
- Lid
- Steam valve
- Base
Multiple selection
type="multiple" with always-visible labels; disabled spots are skipped by the arrow keys.
Tour: Main hall
API
ImageHotspots
| Prop | Type | Default |
|---|---|---|
hotspotsx / y in % (0–100) from the top-left of the picture. label is the accessible name. | { id, x, y, label, description?, marker?, disabled? }[] | — |
childrenThe picture: an img, inline SVG or any element. img / svg children fill the box. | ReactNode | — |
aspectRatioBox ratio; also used for the arrow-key geometry. Omit to size from the children. | number | string | — |
typeRadio group (arrows move and select) or toggle buttons (arrows move, Space toggles). | "single" | "multiple" | "single" |
value / defaultValue / onValueChangeSelection, per type. | string | null · string[] | — |
numbered1, 2, 3… in the markers. | boolean | — |
showLabelsLabels always visible instead of a hover / focus tooltip. | boolean | — |
calloutPopover by the selected spot (single). Default: label + description when there is one. | false | (spot) => ReactNode | — |
aria-labelRequired: what the picture shows. | string | — |