# Electrotype — WebGL Background for React

> Image or seeded procedural plate deposited as a hex grid of metal domes whose radius follows luminance: plates in along a noisy front, glints slide under a drifting key light, and the pointer acts as an electrode that swells nearby dots into a crust with a depleted ring around it. Stacking pulse clicks, multi-image dissolve-and-replate morphs, nickel/copper/gold or custom metal, light tone. Original OGL shader, DPR-clamped, offscreen-paused, reduced-motion static frame.

- Page: https://crucibleui.com/components/backgrounds/electrotype
- 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/electrotype
```

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

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

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

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `ref?` | `React.Ref<ElectrotypeHandle>` | — | React 19 ref-as-prop → {@link ElectrotypeHandle}. |
| `src?` | `string` | — | A single image URL to plate (loaded with `crossOrigin="anonymous"`, so cross-origin hosts must send CORS headers). Ignored when `images` is set. Omit both for three built-in seeded procedural plates. |
| `images?` | `string[]` | — | Several image URLs: every `interval` seconds (and on `next()`), the deposit dissolves along a noisy front and the next image plates back in. |
| `dot?` | `number` | `12` | Dot pitch — distance between neighbouring dot centers — in CSS px, 5–40. |
| `metal?` | `ElectrotypeMetal` | `"nickel"` | Metal finish of the deposit. Ignored when `colors` is set. |
| `colors?` | `[string, string, string]` | — | Custom metal ramp `[shadow, body, highlight]` (hex). Overrides `metal` — e.g. `["#101a2c", "#5d86c9", "#e6f0ff"]` for anodised blue. |
| `contrast?` | `number` | `1.3` | Luminance contrast before it drives dot radius, 0.3–3. |
| `interval?` | `number` | `9` | Seconds between automatic image changes (when there is more than one image), or `0` to disable. Pauses offscreen and under reduced motion. |
| `tone?` | `"dark" \| "light"` | `"dark"` | `"dark"` — bright metal on near-black, dots grow with luminance; `"light"` — metal on pale stock, dots grow with darkness (reads like print). |
| `interactive?` | `boolean` | `true` | Pointer acts as an electrode: nearby dots swell into a crust with a depleted ring just outside; clicks stack plating pulses. When idle, a ghost electrode wanders so the surface never looks dead. Listens on the parent element, so overlay content above it does not block the effect. |
| `paused?` | `boolean` | `false` | Freeze all animation at the current frame. |

Also accepts: `Omit<React.ComponentPropsWithoutRef<"div">, "children">`.

## Usage example

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

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

export default function ElectrotypeDemo() {
  return (
    <DemoScene
      background={<Electrotype />}
      headline="Every pixel, plated"
      subhead="Move the electrode — click to pulse."
    />
  );
}
```

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