gridPattern
A Backgrounds block/component from Magic UI — clean-room reimplemented for Domphy (see methodology). Call gridPattern() with no arguments for a working demo, or edit the code below live.
Implementation notes
Fully static, zero-JS implementation matching the spec's own description ('no animation of its own'): a single SVG <pattern> (patternUnits=userSpaceOnUse) tiled across a background <rect> draws the line grid natively, so it reflows on resize with no ResizeObserver needed at all. squares renders as solid <rect> highlights layered on top, keyed by ${column}-${row}. External edge-fade masks / skew transforms remain the caller's responsibility exactly as upstream documents (exposed via the returned demo wrapper's style passthrough). This is the static sibling animatedGridPattern's line-grid layer is copied from (both use the same <pattern> technique).
Status: ported · Reference: Magic UI original
// Magic UI "Grid Pattern" — clean-room reimplementation.
//
// A static SVG background of thin graph-paper-style grid lines, with an
// optional list of individual cells rendered as solid-filled squares on top
// — useful for spotlighting or tracing particular cells. Purely decorative
// and stateless: no animation of its own. Edge fades (radial/linear mask) or
// skew/rotation are expected to be layered on externally via plain CSS by
// the consumer, exactly as upstream documents it. Implemented purely from
// the block's public functional/visual spec — no upstream Magic UI source
// was viewed or copied.
//
// The line grid is a single SVG `<pattern>` (`patternUnits="userSpaceOnUse"`)
// stamped across a full-size background `<rect>` — the browser tiles it
// natively, so the grid always covers the container exactly and reflows for
// free on resize without any JS measurement at all. This is the static
// sibling of `animatedGridPattern` — same line-pattern base, minus the
// pulsing animated squares layer.
import type { DomphyElement, Listener, StyleObject } from "@domphy/core";
import { hashString } from "@domphy/core";
import { heading, paragraph } from "@domphy/ui";
import { type ThemeColor, themeColor, themeSpacing } from "@domphy/theme";
export interface GridPatternProps {
/** Grid cell width, in px. Defaults to `40`. */
width?: number;
/** Grid cell height, in px. Defaults to `40`. */
height?: number;
/** Pattern horizontal offset, in px — `-1` keeps the thin stroke crisply aligned to pixels. Defaults to `-1`. */
x?: number;
/** Pattern vertical offset, in px. Defaults to `-1`. */
y?: number;
/** `[column, row]` coordinate pairs rendered as solid-filled highlighted cells. Defaults to a small illustrative set. */
squares?: Array<[number, number]>;
/** Solid vs dashed line style, e.g. `"4 2"`. Defaults to solid (`undefined`). */
strokeDasharray?: string;
/** Theme color family for the lines and highlighted squares. Defaults to `"neutral"`. */
color?: ThemeColor;
/** Passthrough style merged onto the outer demo container. */
style?: StyleObject;
}
let gridPatternInstanceCounter = 0;
const DEFAULT_SQUARES: Array<[number, number]> = [
[2, 1],
[5, 3],
[8, 2],
[3, 5],
];
/**
* A static SVG background of thin graph-paper-style grid lines, with an
* optional list of highlighted cells rendered as solid squares on top. Call
* with no arguments for a working demo — a faint grid with a few highlighted
* cells behind a heading.
*/
function gridPattern(props: GridPatternProps = {}): DomphyElement<"div"> {
const width = props.width ?? 40;
const height = props.height ?? 40;
const x = props.x ?? -1;
const y = props.y ?? -1;
const squares = props.squares ?? DEFAULT_SQUARES;
const strokeDasharray = props.strokeDasharray;
const color = props.color ?? "neutral";
const instanceId = ++gridPatternInstanceCounter;
const patternId = `domphy-grid-pattern-${instanceId}-${hashString(
JSON.stringify({ width, height, x, y }),
)}`;
const patternElement: DomphyElement = {
pattern: [
{
path: null,
d: `M ${width} 0 L 0 0 0 ${height}`,
fill: "none",
// Decorative line path, no text of its own.
_doctorDisable: "missing-color",
style: {
stroke: (listener: Listener) => themeColor(listener, "shift-4", color),
strokeDasharray,
} as StyleObject,
} as DomphyElement,
],
id: patternId,
width,
height,
patternUnits: "userSpaceOnUse",
x,
y,
} as DomphyElement;
const squareElements: DomphyElement[] = squares.map(([column, row]) => ({
rect: null,
_key: `square-${column}-${row}`,
x: column * width + x,
y: row * height + y,
width,
height,
ariaHidden: "true",
_doctorDisable: "missing-color",
style: {
fill: (listener: Listener) => themeColor(listener, "shift-8", color),
} as StyleObject,
} as DomphyElement));
const gridSvg: DomphyElement = {
svg: [
{ defs: [patternElement] } as DomphyElement,
{
rect: null,
width: "100%",
height: "100%",
style: { fill: `url(#${patternId})` } as StyleObject,
} as DomphyElement,
{ g: squareElements, _key: "highlighted-squares" } as DomphyElement,
],
ariaHidden: "true",
style: {
position: "absolute",
inset: 0,
width: "100%",
height: "100%",
pointerEvents: "none",
} as StyleObject,
} as DomphyElement;
return {
div: [
gridSvg,
{
div: [
{ h2: "Grid Pattern", $: [heading()] } as DomphyElement,
{
p: "A static graph-paper grid with optional highlighted cells.",
$: [paragraph()],
} as DomphyElement,
],
style: { position: "relative", zIndex: 1 },
} as DomphyElement,
],
dataTone: "shift-15",
style: {
position: "relative",
overflow: "hidden",
borderRadius: themeSpacing(4),
padding: themeSpacing(8),
minHeight: themeSpacing(64),
backgroundColor: (listener: Listener) => themeColor(listener, "inherit"),
color: (listener: Listener) => themeColor(listener, "shift-9"),
...(props.style ?? {}),
} as StyleObject,
};
}
export { gridPattern };