A dynamic border component with rotation, blur, and glow effects for highlighting content.
import AuroraBorder from "@/registry/visual-effects/aurora-border/aurora-border";
const AuroraBorderPreview = () => {
return (
<div className="isolate">
<AuroraBorder
className="max-w-sm rounded-xl p-6 bg-neutral-50 dark:bg-neutral-900"
width={2}
speed={1}
colors={[
"#60A5FA",
"#A78BFA",
"#F472B6",
"#38BDF8",
"#60A5FA",
]}
>
<ChartIcon className="inline-block w-10 h-10 mb-6 text-gray-900 dark:text-white"/>
<h2 className="text-gray-900 dark:text-white text-2xl font-bold mb-3">
AI-Powered Insights
</h2>
<p className="text-gray-700 dark:text-gray-400">
Instantly analyze complex datasets with advanced AI algorithms, turning raw information into actionable insights that help you make smarter, faster, and more accurate decisions every single day.
</p>
</AuroraBorder>
</div>
);
};
const ChartIcon = (props) => {
return (
<svg {...props} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="currentColor" d="M5 20q-.425 0-.712-.288T4 19V9q0-.425.288-.712T5 8h2q.425 0 .713.288T8 9v10q0 .425-.288.713T7 20zm5 0q-.425 0-.712-.288T9 19v-5q0-.425.288-.712T10 13h2q.425 0 .713.288T13 14v5q0 .425-.288.713T12 20zm7 0q-.425 0-.712-.288T16 19V5q0-.425.288-.712T17 4h2q.425 0 .713.288T20 5v14q0 .425-.288.713T19 20z" />
</svg>
)
};
export default AuroraBorderPreview; Install the following packages before using this component.
import { memo, useLayoutEffect, useMemo, useRef, type ReactNode } from "react";
import cn from "@/utils/cn";
export type AuroraBorderProps = {
colors?: string[];
width?: number;
glowIntensity?: number;
speed?: number;
className?: string;
children?: ReactNode;
} & React.ComponentProps<"div">;
const AuroraBorder = (
props: AuroraBorderProps
) => {
const {
children,
colors = ["rgba(127, 127, 127, 1)"],
width = 1,
speed = 0.5,
glowIntensity = 0.5,
className,
style,
...restProps
} = props;
const ref = useRef<HTMLDivElement>(null);
const _width = useMemo(() => (
Math.max(0, width)
), [width]);
const _speed = useMemo(() => (
Math.min(1, Math.max(0, speed))
), [speed]);
const _intensity = useMemo(() => (
20 * Math.min(1, Math.max(0, glowIntensity))
), [glowIntensity]);
const gradient = useMemo(() => (
`conic-gradient(from var(--conic-angle), ${colors.join()})`
), [colors]);
useLayoutEffect(() => {
let rafId: ReturnType<typeof requestAnimationFrame> | null = null;
let conicAngle = 0;
const updateConicAngle = () => {
conicAngle += (_speed * 2);
conicAngle = conicAngle % 360;
if (ref.current) {
ref.current.style.setProperty("--conic-angle", `${conicAngle}deg`);
}
rafId = requestAnimationFrame(updateConicAngle);
};
rafId = requestAnimationFrame(updateConicAngle);
return () => {
if (!rafId) return;
cancelAnimationFrame(rafId);
};
}, [_speed]);
return (
<div
{...restProps}
className={cn(
"relative bg-neutal-900 dark:bg-gray-900 transition-[background] duration-100 ease-linear",
"before:rounded-[inherit] before:content-[''] before:z-[-1] before:absolute before:[inset:calc(-1_*_var(--border-width))] before:[background:var(--gradient)]",
"after:rounded-[inherit] after:content-[''] after:z-[-1] after:absolute after:inset-0 after:[filter:blur(var(--intensity))] after:[background:var(--gradient)]",
className,
)}
ref={ref}
style={{
...style,
"--conic-angle-deg": "0deg",
"--gradient": gradient,
"--intensity": `${_intensity}px`,
"--border-width": `${_width}px`,
} as React.CSSProperties}
>
{children}
</div>
);
};
export default memo(AuroraBorder); | Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| children | ReactNode | Yes | — | The content to be wrapped inside the AuraBorder. |
| colors | string[] | No | ["rgba(127, 127, 127, 1)"] | Array of colors or gradients for the border glow. Accepts any valid CSS color. |
| width | number | No | 1 | Width of the border in pixels. Minimum value: 0. |
| speed | number | No | 0.5 | Speed of rotation. Value between 0 (no rotation) and 1 (fastest). |
| intensity | number | No | 0.5 | Glow intensity. Value between 0 (no glow) and 1 (maximum glow). |
| className | string | No | — | Additional CSS class names applied to the wrapper. |
| style | React.CSSProperties | No | — | Inline styles applied directly to the wrapper container. |
If you find this component useful, consider starring the repository on GitHub. Found a bug or have a suggestion? Open an issue to help improve it.