Created
October 9, 2023 07:21
-
-
Save mizchi/77879a08714874d259fe824813f533a9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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