# Image
> Generated from image.contract.json — do not edit by hand.

A framed image with rounded corners, a hover preview mask, a loading placeholder and a broken-src fallback.

Tier: **leaf-lit**. Frameworks: HTML (paste-and-run, no build step) · React · Vue 3.

Surfaces: editor, dashboard, audience.

## Props
| Prop | Type | Default | Notes |
| --- | --- | --- | --- |
| `src` | string | `—` | Image source URL (empty/broken → the fallback state) |
| `alt` | string | `—` | Alternative text for the image |
| `width` | number | `—` | Frame width in px |
| `height` | number | `—` | Frame height in px |
| `preview` | 'true' | 'false' | `true` | Click-to-zoom modal. `false` → a plain framed picture (no mask, no click, no dialog) |
| `radius` | 'xs'|'sm'|'default'|'lg'|'xl'|'pill' | `default` | Frame corner from the DS radius scale |
| `placeholder` | boolean | `off` | Show a shimmer loading skeleton until the image loads |
| `fallback` | string | `Image unavailable` | Label shown in the broken-src error state (its presence never forces the state — a broken/empty src does) |
| `(default slot)` | slot | `Preview` | The label shown in the hover mask |

## Visual standard (measured)
- Frame: radius 8px (radius attr xs 4·sm 6·default 8·lg 12·xl 16·pill) · bg #F7F7F7 · overflow hidden · role=button, keyboard-focusable
- Image: object-fit cover · scale 1.06 on hover, motion-slow ease-out
- Mask: overlay rgba(26,26,46,.7) · #FFFFFF 13/SemiBold · fade motion-mid
- Preview: click/Enter opens a modal dialog (role=dialog, aria-modal); Esc / close button / backdrop dismiss; focus moves in and is restored on close. preview="false" → plain picture, no mask/click/dialog
- Placeholder: shimmer skeleton (icon-muted on bg-secondary) shown while loading; fades on the image load, persistent node
- Fallback: broken/empty src → system-image-square glyph + label, text-tertiary on bg-secondary, role=img
- Sizing: width/height attributes drive the frame

## When to use
- **Image** — a framed picture that invites a click to preview (a deck cover, an upload)
- **Avatar** — a small round identity image
- **Card** — a picture is one part of a larger grouped surface

Always set alt for accessibility. Keep the mask label short — 'Preview', 'View' — it is an invitation, not a caption.
