mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-12 08:45:38 +02:00
feat(web): Use a better grid system
This commit is contained in:
@@ -1,5 +1,24 @@
|
|||||||
---
|
---
|
||||||
import { Stack, Grid } from "../solidjs/index.ts";
|
import { Stack, Grid } from "../solidjs/index.ts";
|
||||||
|
|
||||||
|
// Define which areas are occupied by content at different breakpoints
|
||||||
|
const occupiedAreas = {
|
||||||
|
xs: [
|
||||||
|
{ startRow: 2, endRow: 6, startCol: 1, endCol: 9 }, // Hero content spans rows 2-6, cols 1-9
|
||||||
|
],
|
||||||
|
sm: [
|
||||||
|
{ startRow: 2, endRow: 5, startCol: 2, endCol: 8 }, // Hero content spans rows 2-5, cols 2-8
|
||||||
|
],
|
||||||
|
smd: [
|
||||||
|
{ startRow: 2, endRow: 4, startCol: 2, endCol: 12 }, // Hero content spans rows 2-4, cols 2-12
|
||||||
|
],
|
||||||
|
md: [
|
||||||
|
{ startRow: 2, endRow: 4, startCol: 2, endCol: 12 }, // Same as smd
|
||||||
|
],
|
||||||
|
lg: [
|
||||||
|
{ startRow: 2, endRow: 6, startCol: 2, endCol: 12 }, // Same as smd
|
||||||
|
],
|
||||||
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
<Stack
|
<Stack
|
||||||
@@ -10,30 +29,13 @@ import { Stack, Grid } from "../solidjs/index.ts";
|
|||||||
>
|
>
|
||||||
<div class="flex justify-center items-center flex-col">
|
<div class="flex justify-center items-center flex-col">
|
||||||
<Grid.Root
|
<Grid.Root
|
||||||
style={{ "border-bottom": "none" }}
|
xsGridRows={6}
|
||||||
|
smGridRows={5}
|
||||||
|
mdGridRows={6}
|
||||||
|
xsGridColumns={8}
|
||||||
smGridColumns={8}
|
smGridColumns={8}
|
||||||
mdGridColumns={10}
|
mdGridColumns={12}
|
||||||
lgGridColumns={12}
|
occupiedAreas={occupiedAreas}
|
||||||
>
|
|
||||||
<Grid.Cross crossRow={1} crossColumn={0} />
|
|
||||||
</Grid.Root>
|
|
||||||
<Grid.Root
|
|
||||||
class="before:!border-t-0"
|
|
||||||
style={{ "border-bottom": "none" }}
|
|
||||||
smGridColumns={1}
|
|
||||||
mdGridColumns={1}
|
|
||||||
lgGridColumns={3}
|
|
||||||
heroHeading={true}
|
|
||||||
/>
|
/>
|
||||||
<Grid.Root
|
|
||||||
style={{ "border-bottom": "none" }}
|
|
||||||
class="before:!border-t-0"
|
|
||||||
smGridColumns={8}
|
|
||||||
gridRows={5}
|
|
||||||
mdGridColumns={10}
|
|
||||||
lgGridColumns={12}
|
|
||||||
>
|
|
||||||
<Grid.Cross crossRow={-1} crossColumn={-1} />
|
|
||||||
</Grid.Root>
|
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,46 +1,68 @@
|
|||||||
import { splitProps, For } from "solid-js";
|
import { type ParentProps, splitProps, For, type JSX } from "solid-js";
|
||||||
import type { ParentProps, JSX } from 'solid-js';
|
|
||||||
import styles from "./index.module.css";
|
import styles from "./index.module.css";
|
||||||
|
|
||||||
|
export interface GridCell {
|
||||||
|
startRow: number;
|
||||||
|
endRow: number;
|
||||||
|
startCol: number;
|
||||||
|
endCol: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GridOccupiedAreas {
|
||||||
|
xs?: GridCell[];
|
||||||
|
sm?: GridCell[];
|
||||||
|
smd?: GridCell[];
|
||||||
|
md?: GridCell[];
|
||||||
|
lg?: GridCell[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface GridRootProps {
|
export interface GridRootProps {
|
||||||
gridRows?: number;
|
xsGridRows?: number;
|
||||||
|
smGridRows?: number;
|
||||||
|
mdGridRows?: number;
|
||||||
|
xsGridColumns?: number;
|
||||||
smGridColumns?: number;
|
smGridColumns?: number;
|
||||||
mdGridColumns?: number;
|
mdGridColumns?: number;
|
||||||
lgGridColumns?: number;
|
|
||||||
smHeight?: string;
|
smHeight?: string;
|
||||||
heroHeading?: boolean;
|
occupiedAreas?: GridOccupiedAreas;
|
||||||
class?: string;
|
class?: string;
|
||||||
style?: JSX.CSSProperties;
|
style?: JSX.CSSProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultProps: GridRootProps = {
|
const defaultProps: GridRootProps = {
|
||||||
gridRows: 1,
|
xsGridRows: 6,
|
||||||
lgGridColumns: 1,
|
smGridRows: 5,
|
||||||
mdGridColumns: 1,
|
mdGridRows: 4,
|
||||||
heroHeading: false,
|
xsGridColumns: 8,
|
||||||
|
smGridColumns: 8,
|
||||||
|
mdGridColumns: 12,
|
||||||
smHeight: "calc(var(--width) / var(--grid-cols) * var(--grid-rows))",
|
smHeight: "calc(var(--width) / var(--grid-cols) * var(--grid-rows))",
|
||||||
smGridColumns: 1,
|
occupiedAreas: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Root(props: ParentProps<GridRootProps>) {
|
export function Root(props: ParentProps<GridRootProps>) {
|
||||||
const [local, others] = splitProps({ ...defaultProps, ...props }, [
|
const [local, others] = splitProps({ ...defaultProps, ...props }, [
|
||||||
"gridRows",
|
"xsGridRows",
|
||||||
|
"smGridRows",
|
||||||
|
"mdGridRows",
|
||||||
|
"xsGridColumns",
|
||||||
"smGridColumns",
|
"smGridColumns",
|
||||||
"mdGridColumns",
|
"mdGridColumns",
|
||||||
"lgGridColumns",
|
|
||||||
"smHeight",
|
"smHeight",
|
||||||
"heroHeading",
|
"occupiedAreas",
|
||||||
"class",
|
"class",
|
||||||
"style",
|
"style",
|
||||||
"children"
|
"children"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const styleVars: Record<string, string> = {
|
const styleVars: Record<string, string> = {
|
||||||
...(local.smHeight && { "--sm-height": local.smHeight }),
|
...(local.xsGridRows && { "--xs-grid-rows": local.xsGridRows.toString() }),
|
||||||
|
...(local.smGridRows && { "--sm-grid-rows": local.smGridRows.toString() }),
|
||||||
|
...(local.mdGridRows && { "--md-grid-rows": local.mdGridRows.toString() }),
|
||||||
|
...(local.xsGridColumns && { "--xs-grid-cols": local.xsGridColumns.toString() }),
|
||||||
...(local.smGridColumns && { "--sm-grid-cols": local.smGridColumns.toString() }),
|
...(local.smGridColumns && { "--sm-grid-cols": local.smGridColumns.toString() }),
|
||||||
...(local.mdGridColumns && { "--md-grid-cols": local.mdGridColumns.toString() }),
|
...(local.mdGridColumns && { "--md-grid-cols": local.mdGridColumns.toString() }),
|
||||||
...(local.lgGridColumns && { "--lg-grid-cols": local.lgGridColumns.toString() }),
|
...(local.smHeight && { "--sm-height": local.smHeight }),
|
||||||
...(local.gridRows && { "--grid-rows": local.gridRows.toString() }),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const styleStr = Object.entries({ ...styleVars, ...local.style })
|
const styleStr = Object.entries({ ...styleVars, ...local.style })
|
||||||
@@ -48,128 +70,112 @@ export function Root(props: ParentProps<GridRootProps>) {
|
|||||||
.map(([k, v]) => `${k}: ${v}`)
|
.map(([k, v]) => `${k}: ${v}`)
|
||||||
.join("; ");
|
.join("; ");
|
||||||
|
|
||||||
|
// Helper function to check if a cell is occupied
|
||||||
|
const isCellOccupied = (breakpoint: keyof GridOccupiedAreas, col: number, row: number): boolean => {
|
||||||
|
const areas = local.occupiedAreas?.[breakpoint] || [];
|
||||||
|
return areas.some(area =>
|
||||||
|
col >= area.startCol && col < area.endCol &&
|
||||||
|
row >= area.startRow && row < area.endRow
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to determine border styles for a cell
|
||||||
|
const getCellBorderStyle = (
|
||||||
|
breakpoint: keyof GridOccupiedAreas,
|
||||||
|
col: number,
|
||||||
|
row: number,
|
||||||
|
maxCols: number,
|
||||||
|
maxRows: number
|
||||||
|
) => {
|
||||||
|
const isOccupied = isCellOccupied(breakpoint, col, row);
|
||||||
|
const isLastCol = col === maxCols;
|
||||||
|
const isLastRow = row === maxRows;
|
||||||
|
|
||||||
|
// Check if the cell to the right is also occupied (to remove internal borders)
|
||||||
|
const rightCellOccupied = !isLastCol && isCellOccupied(breakpoint, col + 1, row);
|
||||||
|
// Check if the cell below is also occupied (to remove internal borders)
|
||||||
|
const bottomCellOccupied = !isLastRow && isCellOccupied(breakpoint, col, row + 1);
|
||||||
|
|
||||||
|
return {
|
||||||
|
// Remove right border only if both current and right cell are occupied
|
||||||
|
...(isOccupied && rightCellOccupied && { "border-right": "none" }),
|
||||||
|
// Remove bottom border only if both current and bottom cell are occupied
|
||||||
|
...(isOccupied && bottomCellOccupied && { "border-bottom": "none" }),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render grid guides for a specific breakpoint
|
||||||
|
const renderGridGuides = (
|
||||||
|
breakpoint: keyof GridOccupiedAreas,
|
||||||
|
className: string,
|
||||||
|
cols: number,
|
||||||
|
rows: number
|
||||||
|
) => (
|
||||||
|
<div class={styles.grid_gridGuides} aria-hidden="true" data-grid-guides="true">
|
||||||
|
<For each={Array.from({ length: rows })}>
|
||||||
|
{(_, rowIndex) => (
|
||||||
|
<For each={Array.from({ length: cols })}>
|
||||||
|
{(_, colIndex) => {
|
||||||
|
const row = rowIndex() + 1;
|
||||||
|
const col = colIndex() + 1;
|
||||||
|
const borderStyle = getCellBorderStyle(breakpoint, col, row, cols, rows);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={`${styles.grid_system} ${styles.grid_grid} ${local.heroHeading ? styles.grid_headingGrid : ""} ${local.class || ""}`}
|
aria-hidden="true"
|
||||||
|
class={`${styles.grid_gridGuide} ${className}`}
|
||||||
|
style={{
|
||||||
|
"--x": col,
|
||||||
|
"--y": row,
|
||||||
|
...borderStyle
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</For>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
class={`${styles.grid_system} ${styles.grid_grid} ${local.class || ""}`}
|
||||||
|
data-grid=""
|
||||||
style={styleStr}
|
style={styleStr}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
{local.children}
|
{local.children}
|
||||||
<div class={styles.grid_gridGuides}>
|
|
||||||
<For each={Array.from({ length: local.gridRows || 1 })}>
|
{/* XS Grid Guides */}
|
||||||
{(_, rowIndex) => (
|
{renderGridGuides("xs", styles.grid_xsGuide, local.xsGridColumns || 8, local.xsGridRows || 6)}
|
||||||
<For each={Array.from({ length: local.smGridColumns || 0 })}>
|
|
||||||
{(_, colIndex) => (
|
{/* SM Grid Guides */}
|
||||||
<div
|
{renderGridGuides("sm", styles.grid_smGuide, local.smGridColumns || 8, local.smGridRows || 5)}
|
||||||
class={`${styles.grid_gridGuide} ${styles.grid_xsGuide}`}
|
|
||||||
style={{
|
{/* SMD Grid Guides */}
|
||||||
"--x": colIndex() + 1,
|
{renderGridGuides("smd", styles.grid_smdGuide, local.mdGridColumns || 12, local.mdGridRows || 4)}
|
||||||
"--y": rowIndex() + 1,
|
|
||||||
...(((local.gridRows || 1) > 1 && rowIndex() < (local.gridRows || 1) - 1) && {
|
{/* MD Grid Guides */}
|
||||||
"border-bottom-width": "var(--guide-width)"
|
{renderGridGuides("md", styles.grid_mdGuide, local.mdGridColumns || 12, local.mdGridRows || 4)}
|
||||||
})
|
|
||||||
}}
|
{/* LG Grid Guides */}
|
||||||
/>
|
{renderGridGuides("lg", styles.grid_lgGuide, local.mdGridColumns || 12, local.mdGridRows || 4)}
|
||||||
)}
|
</section>
|
||||||
</For>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
<div class={styles.grid_gridGuides}>
|
|
||||||
<For each={Array.from({ length: local.gridRows || 1 })}>
|
|
||||||
{(_, rowIndex) => (
|
|
||||||
<For each={Array.from({ length: local.smGridColumns || 0 })}>
|
|
||||||
{(_, colIndex) => (
|
|
||||||
<div
|
|
||||||
class={`${styles.grid_gridGuide} ${styles.grid_smGuide}`}
|
|
||||||
style={{
|
|
||||||
"--x": colIndex() + 1,
|
|
||||||
"--y": rowIndex() + 1,
|
|
||||||
...(((local.gridRows || 1) > 1 && rowIndex() < (local.gridRows || 1) - 1) && {
|
|
||||||
"border-bottom-width": "var(--guide-width)"
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
<div class={styles.grid_gridGuides}>
|
|
||||||
<For each={Array.from({ length: local.gridRows || 1 })}>
|
|
||||||
{(_, rowIndex) => (
|
|
||||||
<For each={Array.from({ length: local.mdGridColumns || 0 })}>
|
|
||||||
{(_, colIndex) => (
|
|
||||||
<div
|
|
||||||
class={`${styles.grid_gridGuide} ${styles.grid_smdGuide}`}
|
|
||||||
style={{
|
|
||||||
"--x": colIndex() + 1,
|
|
||||||
"--y": rowIndex() + 1,
|
|
||||||
...(((local.gridRows || 1) > 1 && rowIndex() < (local.gridRows || 1) - 1) && {
|
|
||||||
"border-bottom-width": "var(--guide-width)"
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
<div class={styles.grid_gridGuides}>
|
|
||||||
<For each={Array.from({ length: local.gridRows || 1 })}>
|
|
||||||
{(_, rowIndex) => (
|
|
||||||
<For each={Array.from({ length: local.mdGridColumns || 1 })}>
|
|
||||||
{(_, colIndex) => (
|
|
||||||
<div
|
|
||||||
class={`${styles.grid_gridGuide} ${styles.grid_mdGuide}`}
|
|
||||||
style={{
|
|
||||||
"--x": colIndex() + 1,
|
|
||||||
"--y": rowIndex() + 1,
|
|
||||||
...(((local.gridRows || 1) > 1 && rowIndex() < (local.gridRows || 1) - 1) && {
|
|
||||||
"border-bottom-width": "var(--guide-width)"
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
<div class={styles.grid_gridGuides}>
|
|
||||||
<For each={Array.from({ length: local.gridRows || 1 })}>
|
|
||||||
{(_, rowIndex) => (
|
|
||||||
<For each={Array.from({ length: local.lgGridColumns || 0 })}>
|
|
||||||
{(_, colIndex) => (
|
|
||||||
<div
|
|
||||||
class={`${styles.grid_gridGuide} ${styles.grid_lgGuide}`}
|
|
||||||
style={{
|
|
||||||
"--x": colIndex() + 1,
|
|
||||||
"--y": rowIndex() + 1,
|
|
||||||
...(((local.gridRows || 1) > 1 && rowIndex() < (local.gridRows || 1) - 1) && {
|
|
||||||
"border-bottom-width": "var(--guide-width)"
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface GridCrossProps {
|
interface GridCrossProps {
|
||||||
crossRow: number;
|
row: number;
|
||||||
crossColumn: number;
|
column: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Cross(props: GridCrossProps) {
|
export function Cross(props: GridCrossProps) {
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
"--cross-row": props.crossRow,
|
"--cross-row": props.row,
|
||||||
"--cross-column": props.crossColumn,
|
"--cross-column": props.column,
|
||||||
}} class={styles.grid_cross}>
|
}} class={styles.grid_cross}>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
Reference in New Issue
Block a user