shadcn.io is not affiliated with official shadcn/ui
Abstract Mod Shader flies you down a vortex built from thousands of small rounded slabs. They stand in rings around the axis, several shells deep, and the rings twist as they recede, so the slabs gather into three spiral arms with black between them. Neon pulses race along the columns of slabs toward you, a sun glows at the far end, and the whole scene breathes slowly brighter and dimmer. A WGSL fragment shader on WebGPU raymarches the scene: one rounded box, repeated round a twisted polar grid with modulo arithmetic, which gives the shader its name.
Use it behind a developer tool, a launch or a sci-fi hero, where it adds depth and forward motion. For a whirlpool in plain CSS, with no GPU, use the Vortex background; for a grid tunnel with light streaks, the Warp background. It runs only while it's on screen, holds a still frame with reduced motion, and shows a gradient of the same colors in browsers without WebGPU.
Installation
Usage
import { AbstractModShader } from "@/components/ui/abstract-mod-shader";<AbstractModShader className="flex min-h-[32rem] items-center justify-center">
<h1 className="text-5xl font-semibold text-white">Ship faster</h1>
</AbstractModShader>Abstract Mod Shader is a container: your content sits on top of the vortex, 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 vortex is dark in both color schemes, so use white text; for body text, a panel such as bg-black/60 keeps it clear of the pulses and the sun.
Demos
Magenta
pulseColor="#ff4fd8" turns the pulses and the sun magenta, slabColor="#2d3a6b" makes the slabs a deeper blue, and twist={1.8} winds the arms tighter, so they curl into the sun.
In a card
The vortex scales with its box. speed={0.5} halves the flight and the pulses, which is calmer next to text. The slab edges are the detail here, so the card keeps full quality; the shader is light enough for it.
Performance
About 2.4 ms of GPU time a frame at 1280×720 on an M2 Max laptop; slower GPUs take several times longer. Each pixel marches up to 80 steps through the repeated slabs; empty cells are skipped a cell at a time, and the march stops at the first slab or once it's 50 units deep. At quality={0.5} the slab edges blur, so keep it for slow GPUs. 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 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 gradient of the same colors, three slate wedges round a small glowing sun on black, 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 vortex is decoration: it's hidden from assistive tech and lets every click through to your content. With reduced motion it draws one still frame, at the peak of its breathing, and stops. Nothing flashes across the view: the brightness breathes over about ten seconds, and each column's pulse passes a given point about once a second, as a small streak far below WCAG's flash area. Across the renders we measured, white text reaches 4.5:1 on 98% of the shader; the misses are the pulses and the sun. White text on a bg-black/60 panel stayed above 6:1 on every pixel.
FAQ
How is the vortex built?
From one rounded box. The shader splits space into rings along the axis, shells outward from it and slots around each shell, with modulo arithmetic, and puts a box in every slot. The angle turns with depth, so the rings twist into a spiral, and slots outside three angular arms stay empty, which opens the black gaps between the arms.
What are the pulses?
A sawtooth wave along the depth of the tunnel, moving toward you, lights the slabs it passes, sharp at the front and fading behind. A hash of each column's place decides which quarter of the columns carry one, and where in its cycle each starts.
How do I see further into it?
Raise visibility, from 0.5 (thick fog: only the nearest rings show) to 1.5 (clear: the arms stay visible deep into the tunnel). Higher means clearer.
Can I change the colors?
Yes: pulseColor sets the pulses and the sun, and slabColor the slabs. Both take any CSS color, including theme variables such as var(--primary), and follow a theme switch. The background stays black.
Credits
Inspired by Abstract Mod (opens in a new tab) by revers on Shadertoy. This is a new shader written from a description of the look, not a port: the polar slab grid, the arms, the pulses, the sun, the palette and the code are ours. The rounded box distance is by Inigo Quilez, under the MIT licence, and the hash is lowbias32 by Chris Wellons, in the public domain; both keep their credit lines in the WGSL.
API Reference
AbstractModShader
data-slot="abstract-mod-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.
interactive?boolean
Whether u.pointer follows the pointer. @default false.
paused?boolean
Holds the current frame. @default false.
pulseColor?string
The pulses that run along the slabs, and the sun at the far end. Any CSS colour. @default "#c6ff3d".
- Default
"#c6ff3d"
quality?number
Render scale, from 0.25 to 1, of the screen's pixels (capped at 2×). @default 1.
slabColor?string
The slabs. Any CSS colour. @default "#3a4560".
- Default
"#3a4560"
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.
twist?number
How tightly the vortex winds, from 0 (straight rows) to 2. @default 1.
- Default
1
visibility?number
How far you see into the vortex, from 0.5 (thick fog) to 1.5 (clear). @default 1.
- Default
1
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


Monster Tunnel Shader
Tunnels & 3DBlades twisting into a dark core
- Pro


Digital Tunnel Shader
Tunnels & 3DA neon tunnel with scanlines
- Pro


Accretion Shader
SpaceA glowing centerpiece in space
- Pro


Spiral Galaxy Shader
SpaceSpiral arms, as a whole galaxy
- Pro


Sphere Field Shader
Tunnels & 3DA flight through glowing spheres
- Pro


Isometric Blocks Shader
GeometryCalm blocks for a developer tool