Skip to content

Instantly share code, notes, and snippets.

@pffigueiredo
Created August 21, 2023 13:56
Show Gist options
  • Save pffigueiredo/8acab4b4cd7f7e554944d64260659379 to your computer and use it in GitHub Desktop.
Save pffigueiredo/8acab4b4cd7f7e554944d64260659379 to your computer and use it in GitHub Desktop.
Grid React component
import { Box, box } from "@singlestore/fusion/components/layout";
import classNames from "classnames";
import React from "react";
import "./grid.scss";
type DynamicTemplate = {
type: "dynamic";
repeat: "auto-fill" | "auto-fit";
minDimension: `${number}px`;
maxDimension: `${number}px` | `${number}fr` | `${number}%`;
};
type StaticTemplate = {
type: "static";
count: number;
dimension: `${number}px` | `${number}fr` | `${number}%`;
};
type GridBaseProps = {
gridTemplateColumns?: DynamicTemplate | StaticTemplate;
gridTemplateRows?: DynamicTemplate | StaticTemplate;
gap: React.ComponentProps<typeof Box>["gap"];
};
type GridComponentProps = {
children: React.ReactNode;
} & GridBaseProps;
type GridClassProps = {
// need a ref to inject CSS variables into the DOM
ref: React.RefObject<HTMLElement>;
} & GridBaseProps;
function buildTemplateString(template: DynamicTemplate | StaticTemplate) {
if (template.type === "dynamic") {
return `repeat(${template.repeat}, minmax(${template.minDimension}, ${template.maxDimension}))`;
}
if (template.type === "static") {
return `repeat(${template.count}, ${template.dimension})`;
}
throw new Error("Invalid template type");
}
export function grid({
gridTemplateColumns,
gridTemplateRows,
gap,
ref,
}: GridClassProps) {
if (!ref.current) {
return "";
}
if (gridTemplateColumns) {
ref.current.style.setProperty(
"--grid-template-columns",
buildTemplateString(gridTemplateColumns)
);
}
if (gridTemplateRows) {
ref.current.style.setProperty(
"--grid-template-columns",
buildTemplateString(gridTemplateRows)
);
}
return classNames("grid", box({ gap }));
}
export function Grid({
children,
gap,
gridTemplateColumns,
gridTemplateRows,
}: GridComponentProps) {
const style: Record<string, string> = {};
const refDiv = React.useRef<HTMLDivElement>(null);
return (
<Box
className={grid({
ref: refDiv,
gap,
gridTemplateColumns,
gridTemplateRows,
})}
gap={gap}
style={style}
ref={refDiv}
>
{children}
</Box>
);
}
<Grid
gap="2x"
gridTemplateColumns={{
type: "dynamic",
repeat: "auto-fit",
minDimension: "200px",
maxDimension: "1fr",
}}
>
123
</Grid>;
---
.grid {
--grid-template-columns: 1fr;
--grid-template-rows: 1fr;
display: grid;
grid-template-columns: var(--grid-template-columns) !important;
grid-template-rows: var(--grid-template-rows) !important;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment