Glin UI
Background / DecorativeAdapted from Magic UIbeta

Light Rays

Soft swaying rays of light for hero and section backgrounds.

Edit on GitHub
SOC 2 Type II

See every login before it becomes an incident

Risk scoring on each sign in, device trust checks and one click session revocation from a single audit trail.

Works with

  • Vercel
  • GitHub
  • Cloudflare
  • Astro

Installation

Install from
pnpm dlx @glinui/cli@latest add light-rays

Credits. Adapted from Magic UI (MIT, (c) Magic UI). Web Animations instead of motion, seeded rays, token colors, reduced motion levels, offscreen pause and RTL mirroring. Attribution details.

Prefer the package?

Usage

Place the component as the first child of a relative parent and keep it behind content (use -z-10 or DOM order). Recommended intensity is 0.5 or lower behind body text so contrast stays at WCAG AA.

Large blur radii are expensive to paint. Count is capped at 24 and only the rays carry will-change.

Variants

Soft rays, crisp rays and another seed for a different layout.

Soft
Crisp
Seed 4
import { LightRays } from "@glinui/ui"
export function Variants() {
return (
<div data-glin-theme="dark" className="grid w-full gap-3 sm:grid-cols-3">
<div className="relative isolate flex h-44 items-end overflow-hidden rounded-xl bg-[var(--surface-0)] p-3">
<LightRays intensity={0.45} />
<span className="relative z-10 rounded-full bg-black/70 px-2.5 py-1 text-xs font-medium text-white">Soft</span>
</div>
<div className="relative isolate flex h-44 items-end overflow-hidden rounded-xl bg-[var(--surface-0)] p-3">
<LightRays variant="crisp" count={5} intensity={0.45} />
<span className="relative z-10 rounded-full bg-black/70 px-2.5 py-1 text-xs font-medium text-white">Crisp</span>
</div>
<div className="relative isolate flex h-44 items-end overflow-hidden rounded-xl bg-[var(--surface-0)] p-3">
<LightRays seed={4} count={9} blur={40} intensity={0.45} />
<span className="relative z-10 rounded-full bg-black/70 px-2.5 py-1 text-xs font-medium text-white">Seed 4</span>
</div>
</div>
)
}

Behind a sign in card

Rays at intensity 0.45 or lower keep body text above AA contrast.

Sign in to Northwind

Use your work email to continue.

import { LightRays, Button, Heading, Input, Label, Text } from "@glinui/ui"
export function SignIn() {
return (
<section data-glin-theme="dark" className="relative isolate flex min-h-[26rem] w-full items-center justify-center overflow-hidden rounded-xl bg-[var(--surface-0)] px-4 py-10">
<LightRays intensity={0.4} />
<form className="relative z-10 flex w-full max-w-sm flex-col gap-4 rounded-2xl border border-[var(--line-soft)] bg-[var(--surface-1)] p-6 text-left [box-shadow:var(--shadow-lg)]">
<div className="flex flex-col gap-1">
<Heading level={2} size="sm">Sign in to Northwind</Heading>
<Text size="sm" variant="muted">Use your work email to continue.</Text>
</div>
<div className="flex flex-col gap-1.5">
<Label htmlFor="email">Work email</Label>
<Input id="email" type="email" autoComplete="email" placeholder="you@company.com" />
</div>
<div className="flex flex-col gap-1.5">
<Label htmlFor="password">Password</Label>
<Input id="password" type="password" autoComplete="current-password" placeholder="At least 12 characters" />
</div>
<Button type="submit" className="w-full">Continue</Button>
</form>
</section>
)
}

Accessibility

  • Purely decorative: aria-hidden and pointer-events none, never focusable.
  • Keep intensity at 0.5 or lower behind text; verify AA contrast on your own background.
  • No information is carried by the rays.

ARIA Attributes

  • `aria-hidden="true"` on the root

Reduced Motion

At motion level full the rays sway with WAAPI. With prefers-reduced-motion or data-glin-motion none or subtle, the rays render as a static frame with no animation. Animations also pause offscreen and in background tabs.

Affected properties

opacitytransform

API Reference

PropTypeRequiredDefaultDescription
countnumberNo7Number of rays, capped at 24.
colorstringNovar(--color-accent)Any CSS color or token.
variant"soft" | "crisp"NosoftSoft uses a 24px blur, crisp uses 6px. An explicit blur wins.
blurnumberNo-Blur radius in px.
speednumberNo14Seconds per sway cycle.
lengthstringNo120%CSS length of each ray.
intensitynumberNo0.35Overall strength from 0 to 1.
seednumberNo1Seed for the deterministic layout.

Source

Import directly from the package or browse the source on GitHub. Click any file to view it.

Import

import { LightRays } from "@glinui/ui"

Dependencies

@glinui/ui@glinui/motionclass-variance-authority

Generated API Snapshot

Beta

Auto-extracted from TypeScript source in packages/ui/src/components/light-rays.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.

Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata

Primary Props Type

LightRaysProps

LightRaysProps

PropTypeRequiredDefaultDescription
blurnumberNo-Blur radius in px. Defaults to 24 (soft) or 6 (crisp).
colorstringNo"var(--color-accent)"Any CSS color. Defaults to the accent token.
countnumberNo7Number of rays, capped at 24.
intensitynumberNo0.35Overall strength from 0 to 1. Keep at or below 0.5 behind text.
lengthstringNo"120%"CSS length of each ray, for example "70%" or "28rem".
seednumberNo1Seed for the deterministic ray layout.
speednumberNo14Seconds for one sway cycle.
variant"soft" | "crisp"No"soft"Variant option from lightRaysVariants.