shadcn.io is not affiliated with official shadcn/ui
Shaders
ProDigital Tunnel Shader for React
A neon tunnel drawn on the GPU: tight rings that cycle cyan, magenta and blue as they flow out of the center, over a dark screen with scanlines and faint sparkles. For React with Base UI, when a tech, gaming or AI hero should feel like a dive into the network.
Digital Tunnel Shader draws a neon tunnel on the GPU. A WGSL fragment shader on WebGPU ray marches a wavy cylinder from inside it, every pixel, every frame, and colors the wall by depth through three neon colors, so tight rings cycle cyan, magenta and electric blue as they flow out of the center. The base drifts from teal to indigo, a soft blue haze spreads from the core, faint sparkles twinkle along the walls, and fine scanlines and a vignette finish the screen.
Use it behind a tech, gaming or AI launch, a sign-in screen or a full-screen intro. For glowing rings in plain CSS, with no GPU, use the Portal background; for a bright, colorful flight through star-cut planes, Starry Planes Shader; for a lit tunnel of glossy tiles, Advanced Tunnel Shader. It runs only while it's on screen, holds a still frame with reduced motion, and shows a CSS ring gradient of the same colors in browsers without WebGPU.
Installation
Usage
import {
DigitalTunnelShader,
} from "@/components/ui/digital-tunnel-shader";<DigitalTunnelShader className="flex min-h-[32rem] items-center justify-center">
<h1 className="text-5xl font-semibold text-white">Enter the network</h1>
</DigitalTunnelShader>Digital Tunnel Shader is a container: your content sits on top of the tunnel, 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 screen is dark in both color schemes, so put white or light text over it, and keep small text off the bright rings at the center.
Demos
Custom colors
The rings cycle through fromColor, viaColor and toColor, then back to fromColor. Here they run orange, pink and violet, with a violet hazeColor at the core and peach particleColor sparkles. Every color prop takes any CSS color, var(--primary) included.
In a card
The tunnel scales with its box. particles={0} hides the sparkles and scanlines={false} turns off the lines, for a cleaner surface under a form or a stat.
Performance
About 0.3 ms of GPU time a frame at 1280×720 on an M2 Max laptop, so it renders at full resolution; slower GPUs take several times longer. quality={0.5} renders a quarter of the pixels, and the scanlines keep their size, but the rings at the center go soft. 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 gradient of the same rings and scanlines, 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 tunnel 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 teal screen with the rings at the center, and stops. Nothing flashes: the colors flow over seconds and each sparkle fades in and out over about two seconds. White text has at least 6:1 contrast over 95% of the frame and 15:1 on a typical pixel, but the rings at the center drop to about 3.7:1, so keep small body text off them.
FAQ
Can I use my brand colors?
Yes. fromColor, viaColor and toColor are the three neon colors the rings cycle through, hazeColor the glow at the center and particleColor the sparkles. They take any CSS color, var(--primary) included, and follow a theme switch. Bright, saturated colors read best on the dark screen.
How do I turn off the scanlines?
Set scanlines={false}. The lines are sized in CSS pixels, so they look the same on any screen and at any quality.
How do the sparkles work?
The tunnel is divided into a fine 3D grid, and a hash lights about 15% of its cells with a soft dot that twinkles. The grid drifts down the tunnel. particles sets both their brightness and how fast they drift, from 0, which hides them, to 2.
Is it really 3D?
Yes: the shader marches each pixel's ray through a distance field, up to 64 steps, with no geometry. The camera sits inside the tunnel wall's field, so the march runs backward onto the wall behind it, and the rings line up by distance from the center of the screen. That quirk is the look, so it stays.
What changed from shadcn.io's version?
The look is the same, pixel for pixel apart from where the sparkles fall. depth and ringCount are gone: neither changed the picture, because the ring shapes never won against the walls and the backward march made depth only scale the brightness; use glow for brighter rims. The sparkles use an integer hash and the scene is drawn around the camera, so the tunnel stays as crisp after hours open as in its first second. The scanlines keep their CSS size on any screen and at any quality, and the vignette no longer turns negative in very wide boxes. The colors are props now.
Will it slow my page down?
It costs about 0.3 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. None of the props change the cost; on a slow GPU or a large screen, quality={0.75} renders fewer pixels and keeps the rings fairly crisp.
API Reference
DigitalTunnelShader
data-slot="digital-tunnel-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 neon colour of the cycle the rings flow through. Any CSS colour. @default "#00ffff".
- Default
"#00ffff"
glow?number
How bright the neon rims of the rings glow, from 0 (flat) to 2 (vivid). @default 1.
- Default
1
hazeColor?string
The soft haze that spreads from the centre. Any CSS colour. @default "#1a4dcc".
- Default
"#1a4dcc"
interactive?boolean
Whether u.pointer follows the pointer. @default false.
particleColor?string
The twinkling sparkles. Any CSS colour. @default "#33ccff".
- Default
"#33ccff"
particles?number
How bright the sparkles are and how fast they drift, from 0 (none) to 2. @default 1.
- Default
1
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.
scanlines?boolean
Fine horizontal scanlines over the whole picture. @default true.
- Default
true
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.
toColor?string
The last neon colour of the cycle, which leads back to fromColor. Any CSS colour. @default "#0080ff".
- Default
"#0080ff"
viaColor?string
The middle neon colour of the cycle. Any CSS colour. @default "#ff00ff".
- Default
"#ff00ff"
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


Starry Planes Shader
SpaceA bright, colorful flight through star-cut planes
- Pro


Advanced Tunnel Shader
Tunnels & 3DA lit tunnel of glossy tiles
- Pro


Monster Tunnel Shader
Tunnels & 3DA wilder vortex of blades


Matrix Shader
Digital & retroCode rain for a tech hero, free and lighter
- Pro


Synthwave Canyon Shader
Water & landscapesNeon lines on a retro flight


Hologram Shader
Light & glassA sci-fi projection, free and lighter