Browse the docs
BackgroundsNo. 89 of 109
Aurora
Slow, soft light drifting behind its content, from three radial gradients.
Installation
pnpm dlx shadcn@latest add @corsair-ui/auroraNo setup needed: the CLI finds @corsair-ui in the shadcn registry directory. The files land in your project as source: edit them like your own code. More in Installation.
- Also adds
- utilsuse-in-view
- npm
clsxtailwind-merge
Examples
Theme colours
Theme colours
Custom colours
Brass, sea and dusk
API
| Prop | Type | Default |
|---|---|---|
colorsOne CSS colour per light. | [string, string, string] | — |
durationSeconds for one drift. | number | 20 |
intensityOpacity of the lights. | number | 0.3 |
Accessibility
- The lights are aria-hidden; check the contrast of text on top of them.
- They pause off screen. With prefers-reduced-motion it holds still and shows the finished state.
Compatibility
- Tailwind CSS
- 3.4 and 4, both checked in CI
- React
- 19
- Rendering
- Client component ("use client")
Source
1 file, installed as source you own
aurora.tsxView on GitHub"use client";
import { useMemo, type ComponentProps, type Ref } from "react";
import { useInView } from "@/registry/default/hooks/use-in-view";
import { cn } from "@/registry/default/lib/utils";
function mergeRefs<T>(...refs: (Ref<T> | undefined)[]) {
return (node: T | null) => {
for (const ref of refs) {
if (typeof ref === "function") ref(node);
else if (ref) ref.current = node;
}
};
}
// Where each light starts, how much slower than `duration` it drifts, and
// how far into its drift it begins, so the three never move in step.
const LIGHTS = [
{ left: "-15%", top: "-30%", pace: 1, start: 0 },
{ left: "40%", top: "-15%", pace: 1.35, start: -0.3 },
{ left: "10%", top: "35%", pace: 1.7, start: -0.65 },
];
interface AuroraProps extends ComponentProps<"div"> {
/** Three CSS colours, one per light. Theme variables work. */
colors?: [string, string, string];
/** Seconds for the fastest light to finish one drift. */
duration?: number;
/** Opacity of the lights, from 0 to 1. */
intensity?: number;
}
/**
* Slow, soft light drifting behind its content. Three radial gradients
* moved with transforms only: no blur filters, no canvas. The lights pause
* while off screen and hold still with `prefers-reduced-motion`.
*
* @example
* <Aurora className="rounded-xl border p-10" colors={["#38bdf8", "#a78bfa", "#f472b6"]}>
* <h2>…</h2>
* </Aurora>
*/
function Aurora({
colors = ["var(--primary)", "var(--muted-foreground)", "var(--accent-foreground)"],
duration = 20,
intensity = 0.3,
className,
children,
ref,
...props
}: AuroraProps) {
const [observe, inView] = useInView<HTMLDivElement>({ rootMargin: "200px" });
const mergedRef = useMemo(() => mergeRefs(ref, observe), [ref, observe]);
return (
<div
ref={mergedRef}
data-slot="aurora"
className={cn("relative isolate overflow-hidden", className)}
{...props}
>
<div
aria-hidden="true"
data-slot="aurora-lights"
className="pointer-events-none absolute inset-0 -z-10"
>
{LIGHTS.map((light, index) => (
<span
key={index}
className="animate-aurora absolute size-[75%] rounded-full motion-reduce:animate-none"
style={{
left: light.left,
top: light.top,
background: `radial-gradient(closest-side, ${colors[index]}, transparent)`,
opacity: intensity,
animationDuration: `${duration * light.pace}s`,
animationDelay: `${duration * light.start}s`,
animationPlayState: inView ? "running" : "paused",
}}
/>
))}
</div>
{children}
</div>
);
}
export { Aurora, type AuroraProps };