# Spall — Animated Background for React

> Pixel shatter bursts: an invisible mosaic of chunky cells where a click (or seeded auto-strike) detonates a radial shockwave — struck cells flash ultraviolet, physically eject along the radius with per-cell jitter in crisp integer-snapped steps, then cool and settle home; overlapping bursts interfere additively and hover leaves a faint warm-up trail. Canvas 2D, idle-silent between bursts, seeded, offscreen-paused, reduced-motion-safe.

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

## Install

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

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

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

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 (`SpallProps`)

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `colors?` | `[string, string]` | `["#a78bfa", "#4c1d95"]` | Two tones `[flash, cool]`. `flash` is the hue a cell burns with the instant a shockwave hits it; `cool` is the deep tone it decays through on the way back to dark. Defaults to ultraviolet — a pale violet flash cooling through deep indigo. Pass warm tones for sparks off steel, or two whites for a mono static-burst look. |
| `speed?` | `number` | `1` | Shockwave expansion + cooling speed multiplier. 1 = default. |
| `intensity?` | `number` | `1` | Overall flash brightness, 0–2. |
| `pixelSize?` | `number` | `10` | Size of one mosaic cell in CSS px. Clamped 4–24. |
| `burstRadius?` | `number` | `170` | Shockwave reach of one burst in CSS px. Clamped 40–480. |
| `ejection?` | `number` | `1` | How far struck cells eject along the burst radius, as a multiple of `pixelSize` (offsets are always snapped to whole pixels — crisp, quantized motion). 0 disables displacement (cells only flash). Clamped 0–3. |
| `decay?` | `number` | `1` | Cooling / settle-home rate multiplier — higher fades bursts faster. Clamped 0.25–4. |
| `autoStrike?` | `number` | `2.6` | Seconds between seeded automatic strikes while no burst is live. Strikes land at deterministic seeded positions so the surface periodically detonates on its own. 0 disables auto-strikes (interaction only). |
| `idle?` | `boolean` | `true` | Idle autoplay: the seeded auto-strikes only fire once no real pointer has moved for ~1.5s, so the visitor's own clicks are never upstaged; `false` disables auto-strikes entirely (same as `autoStrike={0}`). Never runs under reduced motion. |
| `interactive?` | `boolean` | `true` | Detonate a burst on click/tap and leave a faint warm-up trail on hover. |
| `dpr?` | `number` | `2` | devicePixelRatio ceiling. Clamped 1–2. |
| `paused?` | `boolean` | `false` | Freeze at a static frame — one burst frozen at peak radius. |
| `ref?` | `React.Ref<SpallHandle>` | — | React 19 ref prop → {@link SpallHandle}. |

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 { Spall } from "@/components/crucible/spall";
import { DemoScene } from "@/components/registry/demo-scene";

export default function SpallDemo() {
  return (
    <DemoScene
      background={<Spall />}
      headline="Click anywhere to strike"
      subhead="Pixels shatter outward from the impact, then cool and settle home."
    />
  );
}
```

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