# Smoke

Soft smoke that billows upward and thins out, lit from above, drawn as a dither.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any URL or sending an `Accept: text/markdown` header. The dithercn agent skill, for building any dither on the engine, is at [/.well-known/agent-skills/dithercn/SKILL.md](/.well-known/agent-skills/dithercn/SKILL.md).

<ComponentPreview src="examples/smoke-demo.tsx" size="full" align="stretch" controls="smokeControls">
  <SmokeDemo />
</ComponentPreview>

## Installation [#installation]

<InstallBlock name="smoke" />

## Usage [#usage]

```tsx
import { Smoke } from "@/components/dithercn/smoke";

export function Footer() {
  return (
    <footer className="relative isolate min-h-[360px]">
      <Smoke className="absolute inset-0 -z-10" />
    </footer>
  );
}
```

The smoke is thickest at the bottom and thins out as it climbs. Light from the upper left catches one side of each plume and leaves the other in shadow. The thickest parts stop short of solid ink, so the dither always shows.

## Examples [#examples]

### Behind a headline [#behind-a-headline]

A lower `height` keeps the smoke in the bottom half, and a lower `density` makes it lighter. Negative `wind` blows it to the left.

<ComponentPreview src="examples/smoke-headline.tsx" size="lg" align="stretch">
  <SmokeHeadline />
</ComponentPreview>

### Embers [#embers]

Four warm colours turn the smoke into the glow above a fire. Blue noise gives an even grain instead of the Bayer grid.

<ComponentPreview src="examples/smoke-embers.tsx" size="lg" align="stretch">
  <SmokeEmbers />
</ComponentPreview>

## Props [#props]

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `scale` | `number` | `1` | Size of the plumes. Higher values make more, smaller ones. |
| `height` | `number` | `0.8` | How high the smoke climbs before it thins out, from 0 to 1. |
| `wind` | `number` | `0.2` | Sideways drift. Negative blows left, positive right. |
| `density` | `number` | `1` | How thick the smoke is, from 0 to 1.5. |
| `palette` | `[DitherColor, DitherColor, ...DitherColor[]]` | `["--dither-paper", "--dither-ink"]` | Colours from paper to ink: palette names such as "blue", CSS variable names, or any CSS colour. |
| `matrix` | `"bayer2" \| "bayer4" \| "bayer8" \| "blue-noise"` | `"bayer4"` | The threshold pattern. See Dither engine. |
| `cell` | `number` | `--dither-cell` | Size of one dither cell in CSS pixels. |
| `speed` | `number` | `1` | How fast it moves. |
| `animate` | `boolean` | `true` | false draws one still frame. |
| `className` | `string` | `–` | Size and position. The background fills this box. |

## Notes [#notes]

* It is decorative and hidden from assistive technology. Put real text on top of it, not inside it.
* With reduced motion turned on, it draws one still frame and stops.
* It pauses when scrolled out of view or when the tab is hidden, and releases its WebGL context when far offscreen. Without WebGL it shows a soft CSS haze in the same colours.
* It costs one small draw per frame at 30 fps, at one pixel per dither cell. See [Performance](/docs/engine/performance).