A line grid background whose edges dissolve through a gradient fade mask. Static, pure CSS — border-token lines that sit quietly in both themes.
npx shadcn@latest add @paragon/grid-fadeimport * as React from "react";
import { cn } from "@/lib/utils";
export interface GridFadeProps extends React.ComponentProps<"div"> {
/** Grid cell size in px. */
cellSize?: number;
/** Line thickness in px. */
strokeWidth?: number;
/** Which edge(s) of the grid dissolve into the background. */
fade?: "edges" | "top" | "bottom" | "none";
/** Overall effect opacity, 0–1. */
strength?: number;
}
const FADE_MASKS: Record<Exclude<NonNullable<GridFadeProps["fade"]>, "none">, string> = {
edges: "radial-gradient(ellipse 85% 85% at 50% 50%, #000 25%, transparent 82%)",
top: "linear-gradient(to bottom, transparent 2%, #000 60%)",
bottom: "linear-gradient(to bottom, #000 40%, transparent 98%)",
};
/**
* A line grid background whose edges dissolve through a gradient fade mask.
*
* Static, pure CSS: two repeating linear-gradients draw the lines and a
* mask-image fades them out toward the chosen edge(s). Lines are painted
* with `currentColor` seeded from the border token, so the grid sits
* quietly in both themes and recolors via any `text-*` utility.
* Absolutely positioned — parent needs `position: relative` (and usually
* `overflow-hidden`).
*/
export function GridFade({
cellSize = 32,
strokeWidth = 1,
fade = "edges",
strength = 1,
className,
style,
...props
}: GridFadeProps) {
const mask = fade === "none" ? undefined : FADE_MASKS[fade];
return (
<div
aria-hidden
data-slot="grid-fade"
className={cn("pointer-events-none absolute inset-0 text-border", className)}
style={{
opacity: strength,
backgroundImage: `linear-gradient(to right, currentColor ${strokeWidth}px, transparent ${strokeWidth}px), linear-gradient(to bottom, currentColor ${strokeWidth}px, transparent ${strokeWidth}px)`,
backgroundSize: `${cellSize}px ${cellSize}px`,
backgroundPosition: "50% 50%",
...(mask ? { maskImage: mask, WebkitMaskImage: mask } : {}),
...style,
}}
{...props}
/>
);
}