# Gimbal — WebGL Background for React

> A machined armillary instrument: nested brushed-metal rings with engraved scales pivot at mutually-prime rates under studio light. Drag to spin on detented bearings, click to align every ring. Offscreen-paused and reduced-motion-safe.

- Page: https://crucibleui.com/components/backgrounds/gimbal
- Category: [backgrounds](https://crucibleui.com/backgrounds)
- Tier: pro (one-time purchase, see https://crucibleui.com/pricing)
- Engine: r3f
- npm dependencies: three, @react-three/fiber

## Install

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

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

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

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

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `rings?` | `number` | `4` | Number of nested rings, 3–5. |
| `speed?` | `number` | — | Drift-rate multiplier for the rings' slow, mutually-prime rotations. 1 = default, 0 holds the rings still (drag and observe still work). |
| `material?` | `GimbalMaterial` | — | Finish of the instrument: brushed `"steel"` (default, cool neutral), warm turned `"brass"`, or dark `"graphite"` with light paint-filled engravings. |
| `engraving?` | `boolean` | `true` | Engraved tick scales on every ring and a degree band on the outer ring. |
| `interactive?` | `boolean` | `true. Programmatic `observe()` works either way` | Drag to spin the instrument on its bearings, click to align the rings. |
| `tone?` | `"dark" \| "light"` | — | Studio backdrop: `"dark"` (default) or `"light"`. |
| `paused?` | `boolean` | `false` | Freeze the instrument at a composed static pose. Also forced on when the user prefers reduced motion. |
| `className?` | `string` | — | Extra classes for the wrapper. Positioned `absolute inset-0 -z-10`. |
| `ref?` | `React.Ref<GimbalHandle>` | — | Imperative handle — see {@link GimbalHandle}. |

## 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 { Gimbal } from "@/components/crucible/gimbal";

export default function GimbalDemo() {
  return (
    <DemoScene
      background={<Gimbal />}
      headline="Precision you can turn"
      subhead="Drag to spin — click to align the rings."
    />
  );
}
```

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