Image
An image inside a message: holds its final size from the first paint, blurs up from a placeholder, fails gracefully and opens a full-screen lightbox.
On this page
A reference photo in an answer, with a blurred placeholder, caption and lightbox.
Installation
Usage
import { Image } from "@/components/ui/chatcn/image"
<Image
src="/uploads/facade.jpg"
alt="A white modular facade with stacked, offset volumes"
width={1200}
height={1700}
placeholder={tinyDataUrl}
caption="Stacked volumes with deep reveals."
/>Pass width and height (or aspectRatio) so the frame reserves the right space before the file arrives. Nothing below it moves when it loads.
Examples
Blur-up and error
With a placeholder, a tiny blurred version fills the frame and fades out when the real image has decoded. Without one, a plain fill holds the space. A failed load says so and offers Retry.
Replay the blur-up load, and the error state with retry.
Props
| Prop | Type | Notes |
|---|---|---|
src | string | |
alt | string | Required. Describe what the image shows |
width, height | number | Intrinsic size. Sets the aspect ratio of the frame |
aspectRatio | number | When the size is unknown, for example 16 / 9 |
placeholder | string | Tiny image shown blurred while loading |
caption | ReactNode | Under the image and as the lightbox title |
fit | "contain" | "cover" | Default contain |
lightbox | boolean | Open full screen on click. Default true |
download | boolean | Download action in the lightbox. Default true |
onOpen | () => void | Replace the built-in lightbox, for example with a shared gallery |
priority | boolean | Load eagerly above the fold |
onStatusChange | (status) => void | loading, loaded or error |
ImageLightbox is exported too: pass images, index, onIndexChange, open and onOpenChange to show any set of images full screen.
Keyboard
| Key | Action |
|---|---|
Enter, Space | Open the lightbox |
Left, Right | Previous and next image in a set (mirrored in right-to-left layouts) |
Esc | Close the lightbox and return focus to the image |
Accessibility
altis required. The open button is labelled with it, so screen readers hear what opens.- The error state keeps the alt text and adds that the image could not load.
- The lightbox is a modal dialog: focus moves in, is trapped, and returns to the image on close. Its title is the caption or the alt text.
- Every image gets a 1 px inner hairline, kept as a real outline under forced colors.
Motion
- The image fades in over 200 ms once decoded. Images already in the cache appear without a fade.
- The lightbox opens with the dialog motion: 220 ms opacity and scale from 0.96, 160 ms out. Opened from the keyboard, it appears instantly.
- Paging through a set swaps instantly. Under reduced motion only opacity changes.