rdloom's signature backdrop: warp and weft threads crossing in a woven grid, with an ember shuttle that passes through slowly.
Optional, and kept apart.
Nothing here is included in a project unless you add it, and the plain component it builds on is unchanged. This effect is decoration: it is hidden from screen readers, stands still for visitors who prefer reduced motion, and can be paused. Use Still on a preview to see that version.
Warp and weft
An ember shuttle passes through
import { WeaveGrid } from "@rdloom/react";
export default function WeaveGridBasic() {
return (
<div className="flex w-full justify-center">
<div className="relative flex h-96 w-full items-center justify-center overflow-hidden rounded-xl border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-default)]">
<WeaveGrid />
<div className="relative text-center">
<p className="text-4xl font-semibold tracking-tight text-[var(--rd-color-text-default)]">Warp and weft</p>
<p className="text-base text-[var(--rd-color-text-muted)]">An ember shuttle passes through</p>
</div>
</div>
</div>
);
}Installation
npx rdloom add weave-gridCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.
It also adds rdloom-motion.css next to your tokens and imports it from the tokens file, once: no setup, and no inline styles. The plain components you already use are untouched.
Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/weave-grid.jsonWorks, but without upgrade tracking, and you import the motion CSS yourself.
Usage
import { WeaveGrid } from "@rdloom/react";
<div className="flex w-full justify-center">
<div className="relative flex h-96 w-full items-center justify-center overflow-hidden rounded-xl border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-default)]">
<WeaveGrid />
<div className="relative text-center">
<p className="text-4xl font-semibold tracking-tight text-[var(--rd-color-text-default)]">Warp and weft</p>
<p className="text-base text-[var(--rd-color-text-muted)]">An ember shuttle passes through</p>
</div>
</div>
</div>Faded
Edge to edge
No fade at the sides
import { WeaveGrid } from "@rdloom/react";
export default function WeaveGridFaded() {
return (
<div className="flex w-full justify-center">
<div className="relative flex h-96 w-full items-center justify-center overflow-hidden rounded-xl border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-default)]">
<WeaveGrid size={32} fade={false} />
<div className="relative text-center">
<p className="text-4xl font-semibold tracking-tight text-[var(--rd-color-text-default)]">Edge to edge</p>
<p className="text-base text-[var(--rd-color-text-muted)]">No fade at the sides</p>
</div>
</div>
</div>
);
}Still
Held still
The shuttle stays out
import { WeaveGrid } from "@rdloom/react";
export default function WeaveGridStill() {
return (
<div className="flex w-full justify-center">
<div className="relative flex h-96 w-full items-center justify-center overflow-hidden rounded-xl border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-default)]">
<WeaveGrid isStill />
<div className="relative text-center">
<p className="text-4xl font-semibold tracking-tight text-[var(--rd-color-text-default)]">Held still</p>
<p className="text-base text-[var(--rd-color-text-muted)]">The shuttle stays out</p>
</div>
</div>
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
sizeDistance between threads in pixels. | number | 24 |
warpColorColour of the vertical warp threads. | string | "color-mix(in srgb, var(--rd-color-text-default) 16%, transparent)" |
weftColorColour of the horizontal weft threads. | string | "color-mix(in srgb, var(--rd-color-text-default) 16%, transparent)" |
accentColour of the shuttle pass. Defaults to the ember token. | string | "var(--rd-color-ember-500)" |
fadeFades the weave out toward its edges. | boolean | true |
durationSeconds one shuttle pass takes. | number | 9 |
isStillStops all movement. Moving content should be stoppable. | boolean | false |
Accessibility
Role presentation, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.
Keyboard
Not interactive.
Screen readers announce
- Ignored: it is not announced
What your code must do
- Pure decoration: aria-hidden, never focusable, and pointer-events none so content on top stays usable
- Drawn with CSS only, so it needs no JavaScript and is safe in server HTML
- The shuttle is a soft band that crosses slowly, never a flash
- Stands still for visitors who ask for less motion (prefers-reduced-motion), with isStill, and inside an rdm-still container
- Nothing flashes more than 3 times a second (WCAG 2.3.1) and moving content can be stopped (WCAG 2.2.2)
- Hidden in forced-colors (high contrast) mode so it never fights system colours
- Keep text on top at 4.5:1 against the effect: use a low-contrast colour
Guidelines
Use it when
- Branded hero sections and empty states
- A signature backdrop for rdloom-styled pages
Avoid it when
- Behind long text
- Next to other animated backgrounds
Don't
- A strong thread colour that competes with content
- Running more than one WeaveGrid in view
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-border-default