# Plasma

Classic plasma: overlapping sine waves that flow into each other, dithered in two colours or a whole palette.

> 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).

> **This is an example, not the only option.** It is one component built on the dithercn engine. Install it when it is what you were asked for. For any other look, don't stretch its props to fit: write your own field on `DitherShader` ([Write your own dither](/docs/engine/write-your-own.md)), and read this example's source for technique. Its full source is in [https://dithercn.dev/r/plasma.json](https://dithercn.dev/r/plasma.json), under `files[].content`.

## Installation [#installation]

```bash
npx shadcn@latest add https://dithercn.dev/r/plasma.json
```

## Usage [#usage]

```tsx
import { Plasma } from "@/components/dithercn/plasma";

export function Hero() {
  return (
    <section className="relative isolate min-h-[480px]">
      <Plasma className="absolute inset-0 -z-10" />
      <h1>Your headline</h1>
    </section>
  );
}
```

Plasma fills its box, so give it a size with `className`. Four sine waves, one of them circling the centre, add up to a pattern that never repeats. A slow noise warp bends it so it doesn't look mechanical. By default it runs from `--dither-paper` through `--chart-5` to `--dither-ink`.

## Examples [#examples]

### Through a palette [#through-a-palette]

Pass any number of colours from paper to ink. More `bands` cycle through the palette more often, and blue noise swaps the Bayer grid for an even grain.

```tsx title="examples/plasma-palette.tsx"
import { Plasma } from "@/components/dithercn/plasma";

export default function PlasmaPalette() {
  return (
    <Plasma
      palette={[
        "--background",
        "--chart-5",
        "--chart-4",
        "--chart-1",
        "--chart-3",
      ]}
      bands={1.6}
      matrix="blue-noise"
      className="absolute inset-0"
    />
  );
}
```

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

`intensity` caps the brightest tone, so the crests never reach full ink and the text stays readable. A smaller `scale` and more `warp` give fewer, softer shapes.

```tsx title="examples/plasma-headline.tsx"
import { Plasma } from "@/components/dithercn/plasma";

export default function PlasmaHeadline() {
  return (
    <section className="relative isolate flex size-full flex-col items-center justify-center gap-3 px-6 text-center">
      <Plasma
        intensity={0.3}
        scale={0.55}
        warp={0.8}
        className="absolute inset-0 -z-10"
      />
      <h3 className="max-w-md text-3xl font-medium tracking-[-0.03em] text-balance">
        Ship the weird idea
      </h3>
      <p className="text-muted-foreground max-w-sm text-sm text-pretty">
        Capped at 30% intensity, the plasma never gets bright enough to fight
        the text.
      </p>
    </section>
  );
}
```

### Coarse and still [#coarse-and-still]

Large cells, the 2×2 matrix and only four `levels` give hard contour bands like an old demo-scene effect. `animate={false}` holds one frame.

```tsx title="examples/plasma-coarse.tsx"
import { Plasma } from "@/components/dithercn/plasma";

export default function PlasmaCoarse() {
  return (
    <Plasma
      matrix="bayer2"
      cell={6}
      levels={4}
      bands={2}
      animate={false}
      className="absolute inset-0"
    />
  );
}
```

## Props [#props]

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `scale` | `number` | `1` | Size of the pattern. Higher values pack more waves in. |
| `warp` | `number` | `0.3` | How far slow noise bends the waves, from 0 (pure sines) to 1. |
| `bands` | `number` | `1.5` | How many times the colours cycle across one wave. |
| `intensity` | `number` | `1` | The brightest tone, from 0 to 1. Lower it to put text on top. |
| `palette` | `[DitherColor, DitherColor, ...DitherColor[]]` | `["--dither-paper", "--chart-5", "--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. |
| `levels` | `number` | `All the matrix can draw` | Tones the plasma snaps to before dithering. Lower values give hard contour bands. |
| `cell` | `number` | `--dither-cell` | Size of one dither cell in CSS pixels. |
| `speed` | `number` | `1` | How fast the waves move. |
| `animate` | `boolean` | `true` | false stops the motion: a still frame if it starts off, the current frame if it was moving. |
| `className` | `string` | `–` | Size and position. The plasma fills this box. |

## Notes [#notes]

* The plasma 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 soft CSS blobs in the same colours.
* One draw per frame at 30 fps, at one pixel per dither cell. See [Performance](/docs/engine/performance).