A card with an image on top and a title, subtitle and meta row below, for artwork lists, artist tiles and booking previews. It composes `atoms.card` with no padding, so fill, border and corners are Card's.
A card with an image on top and a title, subtitle and meta row below, for artwork lists, artist tiles and booking previews. It composes atoms.card with no padding, so fill, border and corners are Card's.
Usage
The ```jsx block above runs live on the docs site. Imports are stripped and every registry export is in scope, so you can compose with other components too.
Behaviour
- With
href, the whole card is one link named by the title. PasslinkComponent(for examplenext/link) for client-side routing. Keepmetanon-interactive: the link covers the card. Withouthrefthe card is static, with no hover or focus stop. - The media box holds its
aspectRatio(4/5,1/1or3/2) before the image loads. Give the image its descriptivealt. - If an
<img>inmediafails to load, including before hydration, the box shows an image icon at the same ratio. The icon is labelledunavailableLabel("Image unavailable") followed by the image's alt text. A newsrcon the image clears the failure, as long asmediais the image element itself (an<img>ornext/image). - The card reads
srcfrom the root element ofmediaonly. Once the image fails it is replaced by the icon and can no longer be read, so a wrapper without asrcprop, or a<picture>, never clears its failure. Whenmediais one of those, give the card akeythat changes with the image (for examplekey={artwork.id}). - The title clamps at two lines and the subtitle at one. In a grid row the card fills the row's height and
metasits on its bottom edge. - The hover glow reads
--brand-glow-violetfrom@behivetech/cms.base-styles; it is transparent in Light. Glow is on the card, never on text.
Examples
Open all 5 →Properties
ImageCard props
| Prop | Type | Default | Description |
|---|---|---|---|
media* | ReactNode | — | The image, or any node that holds one (`next/image` with `fill` works). Give the image its descriptive `alt`. If an `<img>` inside fails to load, including before hydration, the media box swaps it for an image icon at the same aspect ratio, labelled with `unavailableLabel` and the alt text. A new `src` on the image clears the failure, but only when `media` is the image element itself (an `<img>` or `next/image`). If `media` is a wrapper or a `<picture>`, give the card a `key` that changes with the image. |
title* | ReactNode | — | Card title, clamped at two lines. It names the link when `href` is set. |
aspectRatio | "4/5" | "1/1" | "3/2" | 4/5 | Aspect ratio of the media box, held before the image loads. Defaults to `4/5`. |
className | string | — | Additional class names to merge with the component root element |
headingLevel | 1 | 2 | 3 | 4 | 5 | 6 | 3 | Which heading tag (`h1`-`h6`) wraps the title. Defaults to `3`. |
href | string | — | Makes the whole card one link, named by the title. Omit for a static card with no hover and no focus stop. |
linkComponent | ElementType | a | Component that renders the link, for client-side routing (pass `next/link`). Receives `href` and `className`. Defaults to a plain `a`. |
meta | ReactNode | — | Optional row on the card's bottom edge (a price, a status badge); keep it non-interactive |
subtitle | ReactNode | — | Optional line under the title, clamped at one line |
unavailableLabel | string | Image unavailable | Label for the failed-image fallback, read before the image's alt text. Defaults to "Image unavailable"; pass your translation. |
Also accepts the native attributes of its root element (className, aria-*, event handlers, …).