<!-- Protocore Design System — Image -->
# Image

- **Category:** Media (`media`)
- **Slug:** `media/image`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { Image } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/media/image

> An <img> wrapper with fixed or fill sizing, object-fit, a sharp fallback placeholder, and an optional caption.

## When to use it

`Image` is the general-purpose picture primitive — product shots, screenshots, chart exports, uploaded media. For a *person's* picture with initials fallback, use **Avatar**; for a fixed-ratio frame, wrap `Image fill` in **AspectRatio**; for decorative brand line work, use **LineArt**.

The fallback is the point: an admin console renders user-supplied URLs that break, and a broken-image icon looks like a bug. `Image` degrades to a deliberate placeholder instead. `alt` is required — pass `""` for purely decorative images so screen readers skip them.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `alt` | `string` | yes | — | Alternative text. Required for meaningful images; pass `""` for decorative. |
| `caption` | `ReactNode` | no | — | Caption rendered under the image; promotes the wrapper to a `<figure>`. |
| `className` | `string` | no | — | — |
| `fallback` | `ReactNode` | no | — | Custom fallback node shown when the image is missing or errors. |
| `fallbackLabel` | `string` | no | `No image` | Mono label for the built-in placeholder (used when no `fallback` is given). |
| `fill` | `boolean` | no | `false` | Fill the positioned parent (absolute inset:0) instead of using width/height. |
| `fit` | `enum` | no | `cover` | `object-fit` for the rendered image. |
| `height` | `string \| number` | no | — | Height — number (px) or any CSS length. Ignored when `fill`. |
| `src` | `string` | no | — | Image source. When absent or it fails to load, the fallback renders. |
| `style` | `CSSProperties` | no | — | — |
| `width` | `string \| number` | no | — | Width — number (px) or any CSS length. Ignored when `fill`. |

## Examples

### Basics

`Image` wraps a plain `<img>` with fixed `width` / `height` and an `object-fit` (default `cover`). Corners stay sharp. It's a thin, framework-agnostic wrapper — no lazy-loading magic, just consistent sizing and a fallback.

```tsx
import { Image } from "@protocore/pds";

// A tiny inline SVG data-URI stands in for a real asset in the sandbox.
const src =
  "data:image/svg+xml;utf8," +
  encodeURIComponent(
    `<svg xmlns='http://www.w3.org/2000/svg' width='240' height='150'>
       <rect width='240' height='150' fill='#0e9e6e'/>
       <text x='50%' y='50%' fill='#fff' font-family='monospace' font-size='16'
         text-anchor='middle' dominant-baseline='middle'>PROTOCORE</text>
     </svg>`,
  );

export default function ImageBasics() {
  return <Image src={src} alt="Protocore brand plate" width={240} height={150} fit="cover" />;
}
```

### Fallback

When `src` is absent or the image fails to load, `Image` swaps in a sharp placeholder box with a broken-image glyph and a mono label — no layout shift, no broken-image chrome. Pass a custom `fallback` node or a `fallbackLabel` to tune it.

```tsx
import { Image, Stack } from "@protocore/pds";

export default function ImageFallback() {
  return (
    <Stack direction="row" gap={4} align="start">
      {/* absent src -> placeholder */}
      <Image alt="Product shot" width={160} height={120} fallbackLabel="No image" />
      {/* broken src -> placeholder after onError */}
      <Image
        src="https://invalid.example/missing.png"
        alt="Broken upload"
        width={160}
        height={120}
        fallbackLabel="Upload failed"
      />
    </Stack>
  );
}
```

## Usage

**Do**

- Always pass `alt` — a description, or `""` for decorative images.
- Use the fallback for user-supplied URLs that may 404.
- Wrap `fill` images in AspectRatio to reserve the space.

**Don't**

- Don't use it for avatars — Avatar has the initials fallback.
- Don't omit dimensions on a fixed image; reserve the space to avoid shift.
- Don't round the corners; keep them sharp.

## Accessibility

**Notes**

- `alt` is a required prop — meaningful images describe themselves; decorative ones pass `alt=""`.
- The fallback placeholder is a `role="img"` with the `alt` (or `fallbackLabel`) as its accessible name, so a missing image is still announced.
- A `caption` renders inside a real `<figure>` / `<figcaption>`, associating the text with the image.

## Related

`avatar`, `aspect-ratio`, `line-art`, `icon`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
