shadcn.io is not affiliated with official shadcn/ui
Truchet Shader tiles the frame with Sébastien Truchet's oldest tile: a square cut on its diagonal, laid in one of four turns at random, so the halves meet in triangles, chevrons and zigzags. Each half is a facet folded up from the crease, with a linear ramp along a three-color gradient and a tilt that catches a light from the upper left, so the mosaic looks like folded paper. The gradient, indigo to rose to amber, sways slowly across the tiles while the grid drifts diagonally and turns; a WGSL fragment shader on WebGPU draws every pixel each frame, four samples per pixel, so the creases stay crisp.
Use it behind a hero, a launch or a brand page that wants bold, colorful geometry. For black-and-white line art with depth, use Truchet Kaleidoscope Shader; for woven arcs on a triangle grid, Simplex Truchet Weave Shader. It runs only while it's on screen, holds a still frame with reduced motion, and shows a CSS checker of facets over the same gradient in browsers without WebGPU.
Installation
Usage
import { TruchetShader } from "@/components/ui/truchet-shader";<TruchetShader className="flex min-h-[32rem] items-center justify-center">
<div className="rounded-xl bg-black/50 px-8 py-6 backdrop-blur-sm">
<h1 className="text-5xl font-semibold text-white">Ship faster</h1>
</div>
</TruchetShader>Truchet Shader is a container: your content sits on top of the mosaic, in normal flow. It fills its own box, so give it a height or content. For a backdrop behind the whole page, render it empty with className="fixed inset-0 -z-10". The gradient runs from dark to light, so no text color reads on it bare everywhere: a bg-black/50 panel keeps white text above 4.7:1 over the whole frame, and bg-black/60 above 6.6:1; a bg-white/70 panel keeps black text above 10:1.
Demos
Lagoon
fromColor, viaColor and toColor are the gradient's three stops, here navy, teal and pale mint. scale={1.6} fits more, smaller tiles, and spread={0.6} stretches the gradient so one wide sweep crosses the frame.
In a card
The mosaic scales with its box: the tile count follows the height. scale={0.75} makes bigger tiles that read at card size, and shading={1.5} deepens the folds. It keeps full quality: the creases are sharp and go soft at half resolution, and a card-sized box costs the GPU next to nothing.
Performance
About 0.3 ms of GPU time a frame at 1280×720 on an M2 Max laptop, with four samples per pixel for smooth creases; slower GPUs take several times longer. quality={0.5} renders a quarter of the pixels but softens the creases, so keep it at 1 unless the GPU needs the room. The animation stops when the shader scrolls out of view, and the browser pauses it in a hidden tab. Every shader on a page shares one GPU device and one frame loop, and vgpu (about 50 KB gzipped) loads only when the first one mounts.
Browser support
The shader needs WebGPU: Chrome and Edge, Safari 26 and later, and Firefox on Windows and macOS. Elsewhere, and until the first frame, the box shows a CSS checker of light and dark facets over the same gradient, so the layout never jumps. data-state on the root reads unsupported there, if you want to style around it. See Shader Canvas.
Accessibility
The mosaic is decoration: it's hidden from assistive tech and lets every click through to your content. With reduced motion it draws one still frame, the full gradient from indigo to amber, and stops. Nothing flashes: the tiles drift under a tile a second, and the colors sway across them over almost a minute. The pattern is busy and runs from dark to light, so keep copy on a panel: a bg-black/50 panel keeps white text above 4.7:1, and a bg-white/70 one keeps black text above 10:1.
FAQ
What are Truchet tiles?
Square tiles described by Sébastien Truchet in 1704: a square cut on its diagonal into a dark and a light half. Laid in random turns, their edges always line up, and the halves join into triangles, chevrons and zigzags. Later variants draw quarter circles instead, which make the winding paths most people know.
Why don't I see arcs?
This one uses Truchet's original diagonal tile, so it's all triangles. For arcs, use Simplex Truchet Weave Shader, which weaves them over and under on a triangle grid, or Truchet Kaleidoscope Shader, which mirrors them into a tunnel.
Can I use my own colors?
Yes: fromColor, viaColor and toColor are the gradient's three stops. They take any CSS color, var(--primary) included, and follow a theme switch. A dark first stop and a light last one give the folds the most depth. spread sets how many bands cross the frame, and shading how far each fold shifts along the gradient.
How is it anti-aliased?
Every pixel averages four samples, so the creases stay smooth at any size. There's no setting for it: it's cheap at four, and the screen's own pixel density does the rest.
Credits
Inspired by a Truchet shader (opens in a new tab) by Xor on Shadertoy, through shadcn.io's version. This is a new shader written from the idea, not a port: Truchet's diagonal tiles shaded as folded paper, with its own tile code, hash, light, gradient, motion and colors. The hash is lowbias32 by Chris Wellons, in the public domain.
API Reference
TruchetShader
data-slot="truchet-shader"
fallback?string
What shows until the first frame and in browsers without WebGPU: a CSS
background value (gradients, sizes, a colour) that looks like the
shader. It can use the colour props' --shader-<field> variables.
fromColor?string
The first stop of the gradient that sweeps across the tiles. Any CSS color. @default "#1d1b5e".
- Default
"#1d1b5e"
interactive?boolean
Whether u.pointer follows the pointer. @default false.
paused?boolean
Holds the current frame. @default false.
quality?number
Render scale, from 0.25 to 1, of the screen's pixels (capped at 2×). @default 1.
scale?number
How many tiles fit the height, as a multiple of 6, from 0.5 to 3. @default 1.
- Default
1
shading?number
How far each fold shifts along the gradient, from 0 (flat color bands) to 2 (every facet a full ramp). @default 1.
- Default
1
speed?number
Animation speed: 1 is normal, 0 holds the frame. @default 1.
spread?number
How many color bands cross the frame, from 0.5 (one wide sweep) to 2. @default 1.
- Default
1
time?number
A fixed moment, in seconds: draws it and doesn't animate.
toColor?string
The last stop of the gradient. Any CSS color. @default "#ffcf5c".
- Default
"#ffcf5c"
viaColor?string
The middle stop of the gradient. Any CSS color. @default "#f2547d".
- Default
"#f2547d"
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Forwarded to the part.
Related
- Pro


Truchet Kaleidoscope Shader
Patterns & tilingsBlack-and-white line art with depth
- Pro


Simplex Truchet Weave Shader
Patterns & tilingsWoven arcs on a triangle grid
- Pro


Minimal Jigsaw Shader
Patterns & tilingsFlat pieces that interlock
- Pro


Penrose Tiling Shader
GeometryA tiling that never repeats
- Pro


Hexagon Grid Pattern Shader
Patterns & tilingsOp-art pinwheels on a hex grid
- Pro


Random Grid Subdivision Shader
Patterns & tilingsJewel-toned glass cut into shards