Mesh Gradient
betaAnimated WebGL mesh gradient that blends up to six colours in OKLab, with distortion, swirl, grain and a pointer lens — for heroes and empty states.
Theme-aware signal gradient
minimal
Presets and controls
Every preset plus distortion, swirl, speed, grain and pause.
full
Hero section
Headline, badge and Button rendered as children on top of the gradient.
composition
Hand off the busywork. Keep the judgement.
Kura agents read your repo, plan the change and wait for your approval before touching anything.
Installation
npx shadcn@latest add https://kuro.abstergo.fyi/r/mesh-gradient.jsonCopies the source into components/kura/mesh-gradient with its dependencies (kura-theme, kura-merge-refs, kura-shader-color, shader-canvas, use-reduced-motion, utils). Tokens come from the kura-theme item.
When to use it
Use it for
- A hero, landing or onboarding section that needs a calm, living background behind a headline.
- An empty state or a 'start a conversation' panel that should feel warm instead of blank.
- A card or banner announcing an AI feature, using the theme-aware `signal` preset.
- Any container where content should sit on a soft, slowly moving colour field (pass children).
Reach for something else when
- Northern-lights curtains or a night-sky feel — use aurora.
- Showing that an agent is listening or speaking — use agent-orb.
- Signalling that a container is busy — use border-beam (it outlines instead of filling).
- Small inline indicators — use thinking-indicator or shimmer-text.
- Just adding texture to an existing background — use grain.
- A fully custom GLSL effect — build it on shader-canvas.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| colors | "signal" | "paper" | "jade" | "dusk" | "ember" | "glacier" | readonly string[] | "signal" | A preset, or 2–6 CSS colours (OKLCH, hex, rgb, `var(--kura-*)`). `signal` and `paper` are built from tokens and follow light/dark; the others are fixed palettes. |
| distortion | number | 0.5 | Organic noise warping of the colour field, 0–1. |
| swirl | number | 0.25 | Twist around the centre, 0–1. Keep ≤ 0.5 behind text. |
| speed | number | 1 | Animation speed multiplier. 0 renders a still frame. |
| grain | number | 0.12 | Film-grain amount, 0–1. A little grain hides banding on large surfaces. |
| interactive | boolean | true | Gently lens the colour field toward the pointer while it is over the element. |
| paused | boolean | false | Freeze the animation on the current frame. |
| seed | number | 0 | Changes where the colour wells start, so two gradients on a page differ. |
| maxDpr | number | 1.5 | Device-pixel-ratio cap. The field is soft, so 1–1.5 keeps it cheap. |
| children | React.ReactNode | — | Content rendered on top of the gradient (it sits in normal flow). |
All native attributes of the root element, className and ref pass through.
Anatomy
- MeshGradientRoot container (`relative isolate overflow-hidden`). Size it with classes. `data-state` = animating | still.
data-slot="mesh-gradient" - ShaderCanvasThe WebGL layer behind the children (aria-hidden).
data-slot="mesh-gradient-canvas" - FallbackLayered CSS radial gradients shown when WebGL2 is unavailable.
data-slot="mesh-gradient-fallback"
Accessibility
- The gradient is decorative and aria-hidden; children keep their normal semantics.
- Text on top needs contrast: use `signal`/`paper` with text-kura-fg, or a dark preset with light text, and check both themes.
- The pointer lens is purely visual; nothing is interactive about the gradient itself.
- Reduced motion: Renders a single still frame (no flow, no pointer lens). Theme changes still redraw it.
Notes for agents
- Always give the root a size (e.g. `className="h-64 w-full rounded-kura-xl"` or `min-h-80`); it has no intrinsic height without children.
- Children render in normal flow on top — use the root as the section itself (add padding/flex), not as an absolutely positioned layer.
- Custom colours are resolved once per theme change; CSS variables work (`['var(--kura-accent)', 'oklch(0.9 0.04 90)']`).
- Pair with `<Grain />` as the last child for a print-like finish on large heroes.
- Use at most one or two animated gradients per page; give each a different `seed`.