# Image

> A responsive `<img>` primitive with a required `alt` contract. Pair with a `<figure>` + `<figcaption>` compound when the image needs a caption.

- Category: primitive
- Status: stable (since 0.1.0)
- A11y pattern: https://www.w3.org/WAI/tutorials/images/
- Tokens: --background-secondary, --foreground-quaternary
- Playground: https://design.freecodecamp.org/playground#image
- npm dependencies: `react@>=18 <20`
- Registry dependencies: [theme](https://design.freecodecamp.org/registry/theme.md)
- Files:
  - `Image.tsx` → `src/ui/image/Image.tsx` (raw: https://design.freecodecamp.org/registry/image/Image.tsx)
  - `image.css` → `src/ui/image/image.css` (raw: https://design.freecodecamp.org/registry/image/image.css)

## Install (copy source)

1. Ensure the theme is installed once per project - tokens.css + base.css imported globally, fonts available. See https://design.freecodecamp.org/registry/theme.md and https://design.freecodecamp.org/registry/starter.md.
2. Copy the files below into `src/ui/image/` (adjust to your project layout) and import the CSS once from your global stylesheet, e.g. `@import './ui/image/image.css';`.
3. Colors, spacing and type come from tokens - tailor the component by editing the copied source; recolour by editing tokens.css, not the component CSS.

## Usage

`<Image>` is the responsive image primitive. It forwards every native
`<img>` attribute and enforces the `alt` contract at the type level -
there's no way to render the component without declaring one, which
keeps the accessibility floor high.

## Accessibility

Renders a native `<img>`; screen readers read `alt` in place of the
image. Empty `alt=""` signals purely decorative - the image is skipped
in the reading order. Use `caption` when the image is meaningful but
the surrounding prose already describes it; captions are
programmatically associated via `<figcaption>`.

## Example

```tsx
import { Image } from './ui/image/Image';

<Image src="/brand/fcc-secondary.svg" alt="freeCodeCamp mark" caption="freeCodeCamp mark" />
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `caption` | `ReactNode` | no | - |  |
| `figureClassName` | `string` | no | `` |  |

## Source: Image.tsx

```tsx
import React, { forwardRef } from 'react';

export interface ImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
  caption?: React.ReactNode;
  figureClassName?: string;
}

export const Image = forwardRef<HTMLImageElement, ImageProps>(
  ({ caption, className = '', figureClassName = '', alt, ...rest }, ref) => {
    const imgClasses = ['img--responsive', className].filter(Boolean).join(' ');
    if (caption === undefined) {
      return <img ref={ref} alt={alt} className={imgClasses} {...rest} />;
    }
    return (
      <figure className={figureClassName}>
        <img ref={ref} alt={alt} className={imgClasses} {...rest} />
        <figcaption>{caption}</figcaption>
      </figure>
    );
  }
);
Image.displayName = 'Image';
```

## Source: image.css

```css
.img--responsive {
  max-width: 100%;
  height: auto;
  display: block;
}
```

## HTML / vanilla variant

```html
<figure>
  <img class="img--responsive" src="/brand/fcc-secondary.svg" alt="freeCodeCamp mark" />
  <figcaption>freeCodeCamp mark</figcaption>
</figure>
```

Interactive behaviours for plain HTML come from the vanilla runtime (data-uikit-* attributes): https://design.freecodecamp.org/registry/vanilla.md - or download https://design.freecodecamp.org/cdn/uikit.global.js once and self-host it (do not hotlink).

## For coding agents

This library is distributed as copyable source, not an npm package. Start at https://design.freecodecamp.org/registry/starter.md, discover components via https://design.freecodecamp.org/llms.txt, and copy files into the consuming project. Keep token names intact; recolour by editing the copied tokens.css.
