# Spectra — WebGL Background for React

> White light dispersing through an off-screen prism: a fan of rays spreads from a configurable origin, each frequency band refracting at its own angle so the spectrum separates red to violet — pinched to a white-hot throat at the prism and widening with distance. Rays flicker slowly like light through moving air, a slow hue-phase drift cycles which band leads, and the pointer tilts the dispersion axis with damped easing. True premultiplied-alpha transparency composites over any backdrop; an N-stop colors gradient overrides the spectral ramp. Original OGL fragment shader, jitter-dithered, DPR-clamped, offscreen-paused, reduced-motion-safe; idles on its own when untouched — the beam sways slowly.

- Page: https://crucibleui.com/components/backgrounds/spectra
- Category: [backgrounds](https://crucibleui.com/backgrounds)
- Tier: pro (one-time purchase, see https://crucibleui.com/pricing)
- Engine: ogl
- npm dependencies: ogl

## Install

```bash
npx shadcn@latest add @crucible/spectra
```

Pro install requires adding the token-bearing `@crucible` registry to components.json (issued at https://crucibleui.com/account after purchase).

Import from `@/components/crucible/spectra`.

Backgrounds render `absolute inset-0 -z-10`. Their parent must be a stacking context — wrap in `relative isolate` and put your content in a `relative z-10` child, or the background disappears behind an opaque ancestor.

## Props (`SpectraProps`)

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `origin?` | `[number, number]` | `[-0.06, 0.12]` | Where the unseen prism sits, as fractional container coordinates — `[0, 0]` is the top-left corner, `[1, 1]` the bottom-right. Values outside 0–1 push the prism off-screen (the intended look: only the dispersed fan enters the frame). The fan always aims from here toward the frame center. |
| `spreadAngle?` | `number` | `70` | Full angular width of the dispersed fan, in degrees, 10–160. Wider floods the frame; narrower reads as a single searching beam. |
| `dispersion?` | `number` | `1` | How strongly the spectrum separates with distance, 0–2. At 0 the bands leave the prism already fanned out; at higher values the light exits as a pinched white throat and the red→violet separation visibly widens as the rays travel. |
| `rayDensity?` | `number` | `26` | Number of discernible rays across the fan, 4–80. Lower is a few broad searchlight blades; higher is a fine comb of filaments. |
| `colors?` | `string[]` | — | N-stop gradient (2–8 hex colors) overriding the spectral ramp across the fan, first stop at the leading edge. Omit for the true red→violet dispersion spectrum. E.g. `["#f43f5e", "#a855f7", "#38bdf8"]`. |
| `speed?` | `number` | `1` | Animation-speed multiplier — flicker, hue drift. 1 = default. |
| `intensity?` | `number` | `1` | Overall luminosity of the fan, 0–2. Higher blooms the ray cores toward white; lower is a faint ghost of light. |
| `interactive?` | `boolean` | `true` | Cursor interaction: the pointer tilts the dispersion axis a few degrees (exponentially damped), as if nudging the prism. |
| `idle?` | `boolean` | `true` | Idle autoplay: after ~1.5s with no real pointer, a seeded ghost sweeps the dispersion axis slowly back and forth, so thumbnails and heroes never sit still; the real pointer takes over instantly. Requires `interactive`. Never runs under reduced motion. |
| `paused?` | `boolean` | `false` | Freeze the animation at its current frame. |

Also accepts: `React.ComponentPropsWithoutRef<"div">`.

## Usage example

`DemoScene` is a site-only preview harness, not part of the component — replace it with your own layout.

```tsx
import { Spectra } from "@/components/crucible/spectra";
import { DemoScene } from "@/components/registry/demo-scene";

export default function SpectraDemo() {
  return (
    <DemoScene
      background={<Spectra />}
      headline="Split the light"
      subhead="White light fans through an unseen prism and disperses red to violet. Move your cursor to tilt the beam."
    />
  );
}
```

## Accessibility & performance

Honors `prefers-reduced-motion` with a designed static frame or fade (never a blank box) and passes `className` through. Pauses offscreen and on hidden tabs, clamps device pixel ratio, and tears down its GL/canvas context on unmount.
