Skip to content

Instantly share code, notes, and snippets.

@mizchi
Created October 9, 2023 07:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mizchi/77879a08714874d259fe824813f533a9 to your computer and use it in GitHub Desktop.
Save mizchi/77879a08714874d259fe824813f533a9 to your computer and use it in GitHub Desktop.
/*
Grid css layout utilities for [x, y, w, h] grid areas.
Example:
export default function App() {
return (
<>
<Grid
rows={["32px", "1fr", "1fr", "1fr", "1fr"]}
columns={5}
style={{ width: "100vw", height: "100vh", gap: "10px" }}
>
<GridItem area={[0, 0, 5, 1]} style={{ backgroundColor: "wheat" }}>
header
</GridItem>
<SubGrid area={[1, 1, 4, 4]} style={{ backgroundColor: "#ddd" }}>
<GridItem area={[0, 0, 1, 1]} style={{ backgroundColor: "wheat" }}>
0-0/1-1
</GridItem>
<GridItem area={[1, 1, 2, 2]} style={{ backgroundColor: "wheat" }}>
1-1/2-2
</GridItem>
</SubGrid>
</Grid>
</>
);
}
*/
type GridProps = {
rows: number | Array<string | number>;
columns: number | Array<string | number>;
children?: React.ReactNode;
} & React.HTMLAttributes<HTMLDivElement>;
/**
* A grid container with a fixed number of rows and columns.
* @param rows - The number of rows or an array of row sizes.
* @param columns - The number of columns or an array of column sizes.
* @param children - The grid items.
*/
export const Grid = ({
rows,
columns,
children,
style,
...htmlProps
}: GridProps) => {
const gridStyle = {
...style,
display: "grid",
gridTemplateRows:
typeof rows === "number" ? `repeat(${rows}, 1fr)` : rows.join(" "),
gridTemplateColumns:
typeof columns === "number"
? `repeat(${columns}, 1fr)`
: columns.join(" "),
};
return (
<div {...htmlProps} style={gridStyle}>
{children}
</div>
);
};
type GridItemProps = {
area: [x: number, y: number, w: number, h: number];
children?: React.ReactNode;
} & React.HTMLAttributes<HTMLDivElement>;
/**
* A grid container with a fixed number of rows and columns.
* @param area - [x, y, w, h]
* @param columns - The number of columns or an array of column sizes.
* @param children - The grid items.
*/
export const GridItem = ({
area,
style,
children,
...htmlProps
}: GridItemProps) => {
const [x, y, w, h] = area;
const gridItemStyle = {
...style,
gridRowStart: y + 1,
gridColumnStart: x + 1,
gridRowEnd: y + h + 1,
gridColumnEnd: x + w + 1,
};
return (
<div style={gridItemStyle} {...htmlProps}>
{children}
</div>
);
};
type SubGridProps = {
area: [x: number, y: number, w: number, h: number];
children?: React.ReactNode;
} & React.HTMLAttributes<HTMLDivElement>;
/**
* A subgrid container with a fixed number of rows and columns.
* @param area - [x, y, w, h]
* @param columns - The number of columns or an array of column sizes.
* @param children - The grid items.
*/
export const SubGrid = ({
area,
children,
style,
...htmlProps
}: SubGridProps) => {
const [x, y, w, h] = area;
const gridStyle = {
...style,
gridRowStart: y + 1,
gridColumnStart: x + 1,
gridRowEnd: y + h + 1,
gridColumnEnd: x + w + 1,
display: "grid",
gridTemplateRows: "subgrid",
gridTemplateColumns: "subgrid",
};
return (
<div {...htmlProps} style={gridStyle}>
{children}
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment