registry
@automindzsheets 01–77shadcn 4.x
SHEET 48

Grid Beams

component / background / motion

A grid with light travelling along its lines — the atmosphere layer for a hero, with every beam's line, phase and resting frame derived from the beam count and the grid pitch.

type
component
files
2
registry deps
@automindz/backdrop
npm deps
none

installs

  • components/automindz/grid-beams.tsx
  • styles/automindz-beams.css
  • The grid is @automindz/backdrop, so one per-theme alpha table rather than two
  • Interior lines only — a beam on the box's edge is half-clipped and reads as a border glow
  • Entry rate capped at 1.5Hz in the arithmetic, whatever beam count you pass
  • Phases are (i + ½)/n, so the resting frame is a frame of the crossing, never off-screen
  • Import styles/automindz-beams.css once in your layout

The stylesheet is not optional: add import "@/styles/automindz-beams.css" to your root layout once, or nothing travels. Skipping it is safe, never blank — the grid is still a grid at the intensity you asked for, faded at the edges, and every beam is still parked at the frame its animation holds at t = 0, which is also the prefers-reduced-motion path. **The caller wires one thing: the parent.** Like Backdrop, this renders absolute inset-0 -z-10, so its container needs relative isolate — without a stacking context the negative z-index escapes upward and the grid paints behind an ancestor's background. <section className="relative isolate overflow-hidden py-24"><GridBeams /><h1>…</h1></section> is the whole integration; no prop is required and there is no config file. It composes @automindz/backdrop rather than drawing its own grid, so intensity goes straight through and a client app gets one per-theme alpha table instead of two that disagree about how dark a hairline is. Cells are square only when columns / rows matches the box's aspect ratio (the 12 × 8 default is square at 3:2, the usual hero); a px pitch would keep them square and would need a ResizeObserver behind a decorative background. Beams sit on **interior** lines only, fade along a single line and never turn at an intersection — a turn needs a path, a path needs vertices, and vertices need a measured box. beams={0} is a complete backdrop, not an empty one. **The entry rate is capped, not documented**: gridBeamsDuration() stretches the lap until beams cross at 1.5Hz or slower, so set it with the duration prop and never by overriding --automindz-beams-duration, which the component writes and the per-beam delays are already measured against. It is currentColor and alpha throughout — give it text-primary and both the grid and the beams follow. Dials: --automindz-beams-width, --automindz-beams-alpha / --automindz-beams-alpha-dark, --automindz-beams-fade.

Variations

one state per section

01

Default, 12 × 8

Five streaks, alternating down column lines and across row lines, each one exactly on a 1px grid line rather than near it. Watch a beam leave the frame: the next one is already a fifth of a lap behind it, because the phases are (i + ½)/n and the delays are negative.

fluid

Light that follows the lines

The grid is @automindz/backdrop. This item adds the travel and nothing else — one alpha table, one pattern, one dissolve at the edges.

02

Sixteen by nine, ten beams

The rate cap doing its job: ten beams over the asked-for 7s would arrive at 1.43Hz, so the lap is left alone — ask for 3s and it stretches to 6.667s instead of flickering. The 16 × 9 pitch makes the cells square in a wide frame.

fluid

Declared in cells, not in pixels

A percentage pitch is what lets a beam sit on a line by arithmetic — no ref, no ResizeObserver, no client boundary behind a background.

03

Tinted, and one beam

text-primary on the layer tints the grid and the streak together, because the nested Backdrop is handed text-inherit rather than its own text-foreground. One beam parks dead centre at rest — never off-screen, which is what the half-step in the phase buys.

fluid

currentColor and alpha, never a hex

Give it any colour utility and both halves follow. The per-theme alphas are Backdrop's, so this grid and every other grid in the app agree about how dark a hairline is.

04

No beams at all

beams={0} is the empty state and it is a complete backdrop, not a gap: the grid renders on its own. This is also what a reduced-motion visitor sees, except that their beams are still there, parked at the frame the animation holds at t = 0.

fluid

Never blank, at any intensity

Drop the stylesheet and the picture is the same one, minus the travel. There is no state in which this renders an empty box.