Image
Shows a photo in a frame, with an optional caption, a loading skeleton and a fallback that keeps the layout when the file fails to load.
Installation
Set up Camaleo once (Installation), then import it. It is a client component, because it watches the image's error event.
import { Image } from "@camaleo/react";Anatomy
A <figure> while the image works, and a <div> in its place when it fails. style and className go to the outer element; every other prop goes to the <img>.
When it fails, the default fallback replaces the whole figure:
Examples
Every example is a real file you can copy. They all wear the skin, mode and brand from the bar above.
Caption and credit
caption becomes a <figcaption> that screen readers tie to the image; put the credit or file size in captionMeta.
Size and crop
width and height reserve the space before the file arrives; an aspectRatio in style crops the same photo to 16:9 or 1:1 with object-fit: cover.
Loading skeleton
Set loadingState while you wait for the file and clear it in onLoad; the component doesn't clear it for you.
Couldn’t load the cover photo
serra-da-bocaina-cover.jpg
When the file fails
The default fallback keeps the frame and shows the file name. It takes role="img" and the alt as its name, so screen readers still hear what was meant to be there.
Photo didn’t load
The connection dropped. The file is still on the server.
Fallback with a retry
Click Try again. A custom fallback can hold controls, and it gets role="group" so they stay reachable; after the retry, focus stays on the box and a status message confirms it.
The three states
Switch between loaded, loading and failed. The failed state is read only on mount, so change key when you need to reset it.
Decorative image
Use alt="" only when the text next to it already says everything. alt defaults to empty, so a photo without alt is hidden from screen readers too.
In context
Images usually sit at the top of a card or in a grid of thumbnails. These are whole pieces of UI you can copy, in the skin you picked.
Media library
3 files · Campaign “Serra 2026”
File not found
team-photo.jpg
Guidelines
alt="Two green mountain ridges under an orange evening sky"Say what matters in this context, in one sentence, as you would to someone on the phone.
alt="image.png"Screen readers already say "image", and "image.png" tells nothing about the content.
Give every thumbnail the same aspectRatio, so rows line up whatever shape each photo has.
The row turns ragged, and the eye follows the gaps instead of the pictures.
Props
role="group" named by alt.src.<figcaption>.key to reset it.onLoad.loadingState here."", which marks the image as decorative.width, the browser reserves the space before it loads.height, the browser reserves the space before it loads.style and className go to the outer <figure> or fallback; an aspectRatio or height there crops the image. Every other <img> attribute, like loading="lazy" or srcSet, goes to the image.
Styling hooks
Restyle it without forking: target the slots, or set the tokens on a parent, a skin or the image itself.
Attributes
Tokens it reads
Color
Shape & size
This component only
Accessibility
- Loaded, it is an <img> inside a <figure>; the caption is a <figcaption>.
- Give every image that carries meaning an alt. Without one, alt is "" and screen readers skip it.
- The default fallback is role="img" named by alt, so a broken photo still has a name. Without alt it is named "Unavailable image", in English.
- The skeleton is aria-hidden and the figure has no busy state, so a slow image is not announced.