# Trellis — WebGL Background for React

> A perspective-tilted wireframe sheet running a real wave simulation: pointer movement lays a wake of circular ripples that propagate outward, visibly interfere where wakes cross, and reflect off the edges; clicks drop a heavier stone, and a soft seeded rain plus a ghost wake with occasional stones keeps the sheet alive when idle. Wave slope bends the graphite wires and wave height lights the crests emerald with a bright-core-plus-halo glow. CPU wave grid streamed to the GPU each frame, fixed-timestep and frame-rate independent, DPR-clamped, offscreen-paused; reduced motion renders two frozen interfering ripples.

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

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

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

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

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `divisions?` | `number` | `24` | Grid lines across the sheet. Higher = finer weave. Clamped 4–80. |
| `tilt?` | `number` | `0.5` | Perspective lean of the sheet, 0–1. 0 lies flat facing the viewer; 1 tips hard away at the top with strong foreshortening and depth fade. |
| `waveSpeed?` | `number` | `1` | Propagation speed of ripples across the sheet, 0.1–1.5. This is real wave speed — higher values race the wavefronts outward. |
| `damping?` | `number` | `0.4` | How quickly ripples die out, 0–1. Low values let wakes cross the whole sheet and reflect off the edges; high values swallow them near the source. |
| `idleRain?` | `number` | `1` | Idle rain: average tiny seeded ripples per second that keep the sheet alive when nobody is interacting. 0 disables. Clamped ≤8. |
| `colors?` | `[string, string]` | `graphite + emerald (#34d399)` | `[line, crest]` — graphite wire color and the glow that lights the crests. |
| `interactive?` | `boolean` | `true` | Pointer wake + click stones. Waves and rain continue when false. |
| `idle?` | `boolean` | `true` | Idle autoplay: after ~1.5s with no real pointer, a seeded ghost trails a slow wake across the sheet and drops an occasional stone, so thumbnails and heroes never sit still; the real pointer takes over instantly. Requires `interactive`. Never runs under reduced motion. |
| `speed?` | `number` | `1` | Global clock multiplier for the simulation and idle breathing. |
| `intensity?` | `number` | `1` | Response strength, 0–2: line bend, crest brightness and bloom. |
| `paused?` | `boolean` | — | Freeze the render loop, holding the current frame. |
| `ref?` | `React.Ref<TrellisHandle>` | — | React 19 ref prop → {@link TrellisHandle}. |

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

export default function TrellisDemo() {
  return (
    <DemoScene
      background={<Trellis />}
      headline="Waves on a wire"
      subhead="Move your cursor to send ripples across the sheet — click to drop a heavier stone and watch the wakes cross."
    />
  );
}
```

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