Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Shaders

Pro

Simplex Truchet Weave Shader for React

Woven cord knotwork drawn on the GPU: twisted ivory cords with gold edging cross over and under each other on a deep teal ground, drifting slowly. For React with Base UI, when a brand, textile or craft page wants a rich, tactile pattern.

Framework

Simplex Truchet Weave Shader lays cords on a hidden grid of triangles. Every corner of the grid has a ring of cord around it, each triangle holds three arcs of those rings, and each triangle stacks its arcs in a random order, so the cords cross over and under one another and run in S-curves, loops and knots. Each cord is shaded round, wound with a fine twist, edged in gold and outlined, with a soft drop shadow on whatever lies below; the cords warm toward terracotta at the lower right. A WGSL fragment shader on WebGPU draws every pixel each frame while the weave drifts up and to the left.

Use it behind a brand, textile, craft or luxury page that wants a tactile, ornamental pattern. For flat, colorful geometry, use Truchet Shader; for black-and-white line art with depth, Truchet Kaleidoscope Shader. It runs only while it's on screen, holds a still frame with reduced motion, and shows a CSS lattice of rings in the same colors in browsers without WebGPU.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import {
  SimplexTruchetWeaveShader,
} from "@/components/ui/simplex-truchet-weave-shader";
<SimplexTruchetWeaveShader className="flex min-h-[32rem] items-center justify-center">
  <div className="rounded-xl bg-[#0e2329]/80 px-8 py-6">
    <h1 className="text-5xl font-semibold text-white">Ship faster</h1>
  </div>
</SimplexTruchetWeaveShader>

Simplex Truchet Weave Shader is a container: your content sits on top of the weave, 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 light cords and the dark ground alternate everywhere, so put copy on a panel: one in the ground's color at 80%, like the one above, keeps white text above 8.5:1, and bg-black/60 above 5.7:1.

Demos

Stacked

shape="hexagon" bends each cord around a hexagon instead of a circle, and weave={false} turns the crossings off: each ring lies wholly above or below its neighbors, the lower ones darker, like a scatter of washers. shape also takes "dodecagon", a twelve-sided ring between the two.

Preview width

In a card

The cords keep their size in CSS pixels, so a small box shows fewer of them: scale={9} fits nine triangle edges in 750 pixels, for a finer weave at card size. tubeColor, rimColor, backgroundColor and accentColor recolor the cords, their edging, the ground and the tint toward the lower right, here coral and cream on navy, warming to gold.

Preview width

Performance

About 0.4 ms of GPU time a frame at 1280×720 on an M2 Max laptop: three arcs per pixel, each with its shadow, outline, rims and shading. Slower GPUs take several times longer. It keeps full quality: the outlines and edging are thin and go soft at half resolution. 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 lattice of rings in the same colors, 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 weave is decoration: it's hidden from assistive tech and lets every click through to your content. With reduced motion it draws one still frame and stops. Nothing flashes: the weave only drifts, one triangle edge every ten seconds. Light cords on a dark ground make a busy, high-contrast pattern, so never set text on it bare: a panel in the ground's color at 80% keeps white text above 8.5:1.

FAQ

What is a simplex Truchet weave?

Truchet tiles are tiles whose patterns join up however each one is turned. Here the tiles are the triangles of a simplex grid, the grid simplex noise is built on: each triangle carries three arcs of cord, one around each corner, and the arcs join their neighbors' into rings. Drawing each triangle's three arcs in a random order makes the cords cross over and under, so the rings read as woven knotwork.

Which shapes are there?

shape bends the cords around a "circle" (the default), a "hexagon" or a "dodecagon", a twelve-sided polygon between the two. The hexagon gives straight runs and sharp corners, like a honeycomb of cord.

What does turning the weave off do?

With weave={false} the crossings stop alternating: every ring lies wholly above or below its neighbors, and the lower rings are shaded darker, so the pattern reads as a pile of stacked rings rather than a weave.

Can I show the grid?

Yes: grid draws the hidden triangle grid in thin lines of the rim color, over the cords. It's handy to see how the pattern is built, or for a more technical look.

Can I change the colors?

Yes: tubeColor is the cords, rimColor their edging (and the grid), backgroundColor the ground in the holes, and accentColor the tint the cords take on toward the lower right; set it to tubeColor for none. They take any CSS color, var(--primary) included, and follow a theme switch.

Will it slow my page down?

It costs about 0.4 ms of GPU time a frame at 1280×720 on a laptop, and the CPU only sets a few numbers each frame. It stops when it's off screen. On a slow GPU, quality={0.5} renders a quarter of the pixels, but the outlines go soft.

Credits

Inspired by a simplex Truchet weave (opens in a new tab) by Shane on Shadertoy, through shadcn.io's version. This is a new shader written from the idea, not a port: the over-and-under order resolved per triangle stays, while the cord shading, the twist, the edging, the stacked mode, the drift and the colors are ours. The hash is lowbias32 by Chris Wellons, in the public domain.

API Reference

SimplexTruchetWeaveShader

data-slot="simplex-truchet-weave-shader"

PropType
accentColor?string

The tint the cords take on toward the lower right. Any CSS color. @default "#e0805f".

Default
"#e0805f"
backgroundColor?string

The ground that shows through the holes. Any CSS color. @default "#0e2329".

Default
"#0e2329"
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.

grid?boolean

Draws the hidden triangle grid the cords are laid on. @default false.

Default
false
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.

rimColor?string

The thin edging along both sides of each cord. Any CSS color. @default "#c8963e".

Default
"#c8963e"
scale?number

How many triangle edges fit 750 CSS pixels, from 3 (big, bold cords) to 12. @default 7.

Default
7
shape?keyof typeof SHAPES

The shape each cord bends around. @default "circle".

Default
"circle"
speed?number

Animation speed: 1 is normal, 0 holds the frame. @default 1.

time?number

A fixed moment, in seconds: draws it and doesn't animate.

tubeColor?string

The cords themselves. Any CSS color. @default "#ebe0cc".

Default
"#ebe0cc"
weave?boolean

Crosses the cords over and under at random; off stacks whole rings, the lower ones darker. @default true.

Default
true
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.

All 101 shaders