# Aurora

Curtains of light that fold, sway and shimmer, drawn as a dither, with knobs for colour, rays, tilt and drift.

> 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/aurora.json](https://dithercn.dev/r/aurora.json), under `files[].content`.

## Installation [#installation]

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

## Usage [#usage]

```tsx
import { Aurora } from "@/components/dithercn/aurora";

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

Each curtain has a bright lower edge that folds slowly, with rays that fade as they rise. Further curtains hang higher and dimmer. `height` sets where the lowest edge hangs, so you can keep the area under it clear for text.

The props group into three jobs:

* Shape: `curtains`, `height`, `spread`, `sway`, `turbulence`, `rays`, `length`.
* Light and colour: `color` for the edges, `tipColor` for the tops of the rays, `background`, `glow`, `intensity`, `shimmer`. Pass `palette` to set every tone yourself.
* Placement and motion: `tilt`, `scale`, `drift`, `direction`, `mask`, plus the engine's `speed`, `cell` and `matrix`.

## Examples [#examples]

### Above a headline [#above-a-headline]

Raising `height` lifts the curtains off the lower third, where the headline sits on clean paper. A `tipColor` of `"blue"` shifts the tops of the rays to a second, cooler hue, and `mask="edges"` fades the sides.

```tsx title="examples/aurora-hero.tsx"
import { Aurora } from "@/components/dithercn/aurora";

export default function AuroraHero() {
  return (
    <section className="relative isolate flex size-full flex-col items-center justify-end gap-3 px-6 pb-14 text-center">
      <Aurora
        height={0.55}
        tipColor="blue"
        intensity={0.85}
        mask="edges"
        className="absolute inset-0 -z-10"
      />
      <h3 className="max-w-md text-3xl font-medium tracking-[-0.03em] text-balance sm:text-4xl">
        Launch week, day three
      </h3>
      <p className="text-muted-foreground max-w-sm text-sm text-pretty">
        The curtains hang above the headline and leave the lower third clear.
      </p>
    </section>
  );
}
```

### Northern lights [#northern-lights]

Your own colours turn it into the real thing: green edges, violet tips and a night-sky `background`. Four curtains, longer rays, a slight `tilt` and a little `drift` give it depth.

```tsx title="examples/aurora-borealis.tsx"
import { Aurora } from "@/components/dithercn/aurora";

export default function AuroraBorealis() {
  return (
    <div className="absolute inset-0 bg-[oklch(0.14_0.03_250)]">
      <Aurora
        background="oklch(0.14 0.03 250)"
        color="oklch(0.8 0.18 150)"
        tipColor="oklch(0.55 0.16 300)"
        curtains={4}
        height={0.28}
        spread={0.08}
        sway={1.6}
        rays={11}
        length={0.7}
        tilt={-6}
        drift={0.5}
        className="absolute inset-0"
      />
    </div>
  );
}
```

### Hanging over a call to action [#hanging-over-a-call-to-action]

`direction="down"` flips the curtains so the rays fall from the top and the button sits on clear paper below. Few broad `rays` and 4px cells give it a coarser, poster-like grain.

```tsx title="examples/aurora-cta.tsx"
import { Aurora } from "@/components/dithercn/aurora";

export default function AuroraCta() {
  return (
    <section className="relative isolate flex size-full flex-col items-center justify-end gap-5 px-6 pb-12 text-center">
      <Aurora
        direction="down"
        height={0.14}
        curtains={2}
        spread={0.06}
        rays={5}
        length={0.4}
        sway={0.75}
        cell={4}
        matrix="bayer4"
        className="absolute inset-0 -z-10"
      />
      <div className="flex flex-col gap-2">
        <h3 className="text-2xl font-medium tracking-[-0.02em] text-balance sm:text-3xl">
          Start shipping tonight
        </h3>
        <p className="text-muted-foreground mx-auto max-w-xs text-sm text-pretty">
          Free for side projects. No card needed.
        </p>
      </div>
      <button
        type="button"
        className="bg-foreground text-background focus-visible:ring-ring/60 inline-flex h-9 items-center rounded-full px-4 text-sm font-medium transition-[scale,opacity] duration-150 outline-none hover:opacity-90 focus-visible:ring-2 active:scale-[0.97]"
      >
        Create a project
      </button>
    </section>
  );
}
```

### Still, in a banner [#still-in-a-banner]

With `animate={false}` it draws one frame. `stillTime` picks which moment, so you can choose a shape you like.

```tsx title="examples/aurora-banner.tsx"
import { Aurora } from "@/components/dithercn/aurora";

export default function AuroraBanner() {
  return (
    <div className="bg-background border-border relative isolate flex h-36 w-full max-w-lg [--dither-paper:var(--background)] items-end overflow-hidden rounded-2xl border p-5">
      <Aurora
        height={0.62}
        sway={0.6}
        animate={false}
        stillTime={40}
        cell={2}
        className="absolute inset-0 -z-10"
      />
      <div className="flex w-full items-end justify-between gap-4">
        <div className="flex flex-col">
          <span className="font-medium">Dark mode is here</span>
          <span className="text-muted-foreground text-sm">
            Turn it on in Settings.
          </span>
        </div>
        <span className="text-muted-foreground font-mono text-xs">v2.4</span>
      </div>
    </div>
  );
}
```

## Props [#props]

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `color` | `DitherColor` | `"--dither-ink"` | The bright lower edge of each curtain. |
| `tipColor` | `DitherColor` | `color` | The faint tops of the rays. Set a second colour for a two-tone sky. |
| `background` | `DitherColor` | `"--dither-paper"` | The sky behind. |
| `curtains` | `number` | `3` | How many curtains, from 1 to 6. Each one hangs higher and dimmer. |
| `height` | `number` | `0.42` | Where the lowest bright edge hangs, from 0 (bottom) to 1 (top). |
| `spread` | `number` | `0.11` | Vertical gap between curtains, from 0 to 0.3. |
| `sway` | `number` | `1` | How far the edges fold. 0 is straight, 3 is deep folds. |
| `turbulence` | `number` | `0.6` | Fine ripples along each edge, from 0 to 2. |
| `rays` | `number` | `8` | How many rays fit across. 2 gives broad bands, 20 fine needles. |
| `length` | `number` | `0.45` | How far the rays reach up, from 0 to 1. |
| `glow` | `number` | `0.9` | Brightness of the line along each edge, from 0 to 2. |
| `intensity` | `number` | `0.95` | Brightness of the curtains, from 0 to 1. |
| `shimmer` | `number` | `0.2` | A slow brightness ripple, from 0 to 1. |
| `scale` | `number` | `1` | Horizontal zoom. Higher values fit more folds across. |
| `tilt` | `number` | `0` | Tilt of the curtains in degrees, from -45 to 45. |
| `drift` | `number` | `0` | Sideways travel, from -2 (left) to 2 (right). |
| `direction` | `"up" \| "down"` | `"up"` | "down" flips it so the rays hang from a bright top edge. |
| `mask` | `"none" \| "top" \| "bottom" \| "edges"` | `"none"` | Fades it to paper where your text sits. |
| `palette` | `[DitherColor, DitherColor, ...DitherColor[]]` | `Built from the colour props` | Takes over the colours: paper first, brightest last. Palette names, CSS variable names or any CSS colour. |
| `matrix` | `"bayer2" \| "bayer4" \| "bayer8" \| "blue-noise"` | `"bayer8"` | The threshold pattern. See Dither engine. |
| `levels` | `number` | `All the matrix can draw` | Tones the field snaps to before dithering. Low values give hard steps. |
| `cell` | `number` | `--dither-cell` | Size of one dither cell in CSS pixels. |
| `speed` | `number` | `1` | How fast it moves. |
| `animate` | `boolean` | `true` | false stops the motion: a still frame if it starts off, the current frame if it was moving. |
| `stillTime` | `number` | `0` | The moment drawn when motion is off or reduced, in seconds. |
| `className` | `string` | `u2013` | 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 CSS approximation in the same colours.
* It costs one small draw per frame at 30 fps, at one pixel per dither cell. More `curtains` cost a little more per pixel. See [Performance](/docs/engine/performance).