feat(web): Add grid component

This commit is contained in:
Wanjohi
2025-07-21 21:20:37 +03:00
parent 9cf3ad5397
commit 67ba04eced
6 changed files with 306 additions and 241 deletions

View File

@@ -1,2 +1 @@
/// <reference types="astro/client" /> /// <reference types="astro/client" />
/// <reference path="content.d.ts" />

View File

@@ -1,173 +1,41 @@
--- ---
import { Stack } from "../solidjs/index.ts"; import { Stack, Grid } from "../solidjs/index.ts";
--- ---
<div <Stack
style={{ stackDirection="column"
"--width": stackJustify="flex-start"
"clamp(calc(250px - 1px),calc(100vw - 1px - (1rem * 2)),calc(1080px - 1px))", stackPadding="0px"
"--height": "fit-content", stackGap="0px"
}}
class="overflow-hidden"
> >
<!-- Hero Component on Mobile --> <div class="flex justify-center items-center flex-col">
<section <Grid smGridColumns={8} mdGridColumns={10} lgGridColumns={12} />
style={{
"--grid-rows": 2,
"--grid-cols": 1,
"--column-width": "calc(var(--width) / var(--grid-cols))",
"--row-height": "calc(var(--height) / var(--grid-rows))",
}}
class="max-mobile:grid hidden w-(--width) h-(--height) relative grid-template after:absolute after:block after:left-0 after:right-0 after:size-full after:bg-gradient-to-b after:from-background-200 after:from-70% after:to-transparent after:to-80% pointer-events-none"
>
<div class="overflow-hidden z-20 mb-px mt-px col-auto row-auto p-6">
<div
class="max-mobile:gap-6 max-w-5xl:gap-6 h-full flex flex-col justify-center items-center"
>
<div class="flex items-center gap-2 flex-col text-center">
<h1
class="max-[520px]:max-w-[360px] max-mobile:text-2xl max-mobile:leading-[133%] max-mobile:-tracking-[.96px] text-venter font-semibold text-3xl text-balance text-center mb-4"
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</h1>
<p
style={{
"--xs-text-size": "1rem",
"--xs-text-line-height": "1.5rem",
"--xs-text-weight": "400",
"--xs-text-letter-spacing": "0px",
"--sm-text-size": "1rem",
"--sm-text-line-height": "1.5rem",
"--sm-text-weight": "400",
"--sm-text-letter-spacing": "0px",
"--smd-text-size": "1rem",
"--smd-text-line-height": "1.5rem",
"--smd-text-weight": "400",
"--smd-text-letter-spacing": "0px",
"--md-text-size": "1rem",
"--md-text-line-height": "1.5rem",
"--md-text-weight": "400",
"--md-text-letter-spacing": "0px",
"--lg-text-size": "1.25rem",
"--lg-text-line-height": "2.25rem",
"--lg-text-weight": "400",
"--lg-text-letter-spacing": "0px",
}}
class="text-lg text-center mb-6 text_wrapper max-mobile:max-w-4/5 max-[768px]:text-sm text-balance"
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
</p>
</div> </div>
<Stack client:load> </Stack>
<a
href="/"
class="rounded-full leading-6 outline-offset-2 bg-gray-1000 text-gray-100 max-w-full justify-center items-center p-3 px-[14px] h-10 flex cursor-pointer select-none outline-none text-sm"
>
Start Playing
</a>
<a
href="/"
class="bg-background-100 hover:bg-background-200 shadow-shadow-border-small rounded-full leading-6 outline-offset-2 text-gray-1000 border border-gray-alpha-400 max-w-full justify-center items-center p-3 px-[14px] h-10 flex cursor-pointer select-none outline-none text-sm"
>
View Pricing
</a>
</Stack>
</div>
</div>
</section>
<section
style={{
"--sm-grid-rows": 4,
"--md-grid-rows": 8,
"--sm-grid-cols": 8,
"--md-grid-cols": 12,
"--column-width": "calc(var(--width) / var(--md-grid-cols))",
"--row-height": "calc(var(--height) / var(--md-grid-rows))",
"--sm-height": "calc(var(--width) / var(--grid-cols) * var(--grid-rows))",
}}
class="w-(--width) h-(--sm-height) grid relative grid-template overflow-hidden isolate border-b border-gray-200"
>
<!--TODO: Fix TailwindCSS dark-mode system to use the CSS class-->
<div
style={{
"--sm-grid-row": "1 / -1",
"--sm-grid-column": "1 / -1",
"--sm-cell-rows": -2,
"--sm-cell-columns": -2,
}}
] class="z-0 p-0 overflow-hidden mr-px mb-px col-span-full row-span-full select-none transform-[translateY(calc(var(--row-height)/1.2))] relative before:absolute before:inset-0 before:z-100 before:dark:[background:radial-gradient(150%_150%_at_50%_140%,transparent_0,transparent_50%,var(--color-background-200)_76%)] before:[background:radial-gradient(120%_70%_at_50%_100%,transparent_50%,rgba(255,255,255,.95)_88%,var(--color-background-200)_95%)]"
>
<div class="rainbow"></div>
</div>
</section>
<section>
<div
style={{
"--grid-cols": 12,
"--row-height": "calc(var(--width) / var(--grid-cols))",
"--column-width": "var(--width)"
"--grid-rows":1,
}}
class="border-gray-200 border-b grid-template grid relative"
>
<div class=" e"></div>
</div>
</section>
</div>
<style> <style>
.grid-template { .grid_system {
grid-template-columns: repeat(var(--grid-cols), var(--column-width)); --max-width: 1080px;
grid-template-rows: repeat(var(--grid-rows), var(--row-height)); --min-width: 250px;
--guide-width: 1px;
--horizontal-margin: 2rem;
--grid-system-width: 100vw;
--guide-color: var(--color-gray-200);
--cross-color: var(--color-gray-600);
display: flex;
position: relative;
flex-direction: column;
max-width: var(--max-width);
min-width: var(--min-width);
margin-top: var(--guide-width);
margin-left: var(--guide-width);
} }
.grid_system::before {
@media screen and (min-width: 0px) {
.text_wrapper {
--text-size: var(--sm-text-size);
--text-weight: var(--sm-text-weight);
--text-line-height: var(--sm-text-line-height);
--text-letter-spacing: var(--sm-text-letter-spacing);
}
}
@media screen and (min-width: 601px) {
.text_wrapper {
--text-size: var(--md-text-size);
--text-weight: var(--md-text-weight);
--text-line-height: var(--md-text-line-height);
--text-letter-spacing: var(--md-text-letter-spacing);
}
}
@media screen and (min-width: 961px) {
.text_wrapper {
--text-size: var(--lg-text-size);
--text-weight: var(--lg-text-weight);
--text-line-height: var(--lg-text-line-height);
--text-letter-spacing: var(--lg-text-letter-spacing);
}
}
.rainbow {
--yellow: rgba(255, 206, 32, 0.8);
--red: rgba(197, 0, 0, 0.8);
--blue: rgba(0, 89, 171, 0.8);
--cyan: rgba(15, 255, 169, 0.8);
--angle: 180deg;
--offset: 70%;
mix-blend-mode: hard-light;
width: 100%;
inset: 0;
height: 100%;
position: absolute; position: absolute;
background: conic-gradient( inset: 0;
from var(--angle) at 50% var(--offset), left: calc(-1 * var(--guide-width));
rgba(0, 0, 0, 0) 0deg, top: calc(-1 * var(--guide-width));
var(--blue) 72.0000010728836deg, content: "";
var(--cyan) 144.0000021457672deg, border: var(--guide-width) solid var(--guide-color);
var(--yellow) 216.00000858306885deg, pointer-events: none;
var(--red) 288.0000042915344deg,
rgba(0, 0, 0, 0) 1turn
);
background-color: black;
} }
</style> </style>

View File

@@ -5,8 +5,9 @@ export interface StackProps {
stackFlex?: string; stackFlex?: string;
stackDirection?: "column" | "row" | "row-reverse" | "column-reverse"; stackDirection?: "column" | "row" | "row-reverse" | "column-reverse";
stackAlign?: "start" | "end" | "center" | "stretch" | "baseline"; stackAlign?: "start" | "end" | "center" | "stretch" | "baseline";
stackJustify?: "start" | "end" | "center" | "space-between" | "space-around" | "space-evenly"; stackJustify?: "center" | "space-between" | "space-around" | "space-evenly" | "flex-start" | "flex-end";
stackPadding?: string; stackPadding?: string;
stackGap?: string;
smStackGap?: string; smStackGap?: string;
mdStackGap?: string; mdStackGap?: string;
lgStackGap?: string; lgStackGap?: string;
@@ -37,6 +38,7 @@ const defaultProps: Omit<StackProps, "children" | "class"> = {
stackAlign: "stretch", stackAlign: "stretch",
stackJustify: "center", stackJustify: "center",
stackPadding: "0px", stackPadding: "0px",
stackGap: "16px",
smStackGap: "16px", smStackGap: "16px",
mdStackGap: "24px", mdStackGap: "24px",
lgStackGap: "24px", lgStackGap: "24px",
@@ -66,6 +68,7 @@ export function Stack(props: StackProps) {
"stackAlign", "stackAlign",
"stackJustify", "stackJustify",
"stackPadding", "stackPadding",
"stackGap",
"smStackGap", "smStackGap",
"mdStackGap", "mdStackGap",
"lgStackGap", "lgStackGap",
@@ -95,6 +98,7 @@ export function Stack(props: StackProps) {
"--stack-direction": local.stackDirection, "--stack-direction": local.stackDirection,
"--stack-align": local.stackAlign, "--stack-align": local.stackAlign,
"--stack-justify": local.stackJustify, "--stack-justify": local.stackJustify,
"--stack-gap": local.stackGap,
"--stack-padding": local.stackPadding, "--stack-padding": local.stackPadding,
"--sm-stack-gap": local.smStackGap, "--sm-stack-gap": local.smStackGap,
"--md-stack-gap": local.mdStackGap, "--md-stack-gap": local.mdStackGap,

View File

@@ -33,60 +33,278 @@
@media screen and (min-width: 961px) and (max-width: 1200px) { @media screen and (min-width: 961px) and (max-width: 1200px) {
.stack { .stack {
--stack-direction: var( --stack-direction: var(--lg-stack-direction,
--lg-stack-direction, var(--md-stack-direction, var(--sm-stack-direction)));
var(--md-stack-direction, var(--sm-stack-direction)) --stack-align: var(--lg-stack-align,
); var(--md-stack-align, var(--sm-stack-align)));
--stack-align: var( --stack-justify: var(--lg-stack-justify,
--lg-stack-align, var(--md-stack-justify, var(--sm-stack-justify)));
var(--md-stack-align, var(--sm-stack-align)) --stack-padding: var(--lg-stack-padding,
); var(--md-stack-padding, var(--sm-stack-padding)));
--stack-justify: var( --stack-gap: var(--lg-stack-gap,
--lg-stack-justify, var(--md-stack-gap, var(--sm-stack-gap)));
var(--md-stack-justify, var(--sm-stack-justify))
);
--stack-padding: var(
--lg-stack-padding,
var(--md-stack-padding, var(--sm-stack-padding))
);
--stack-gap: var(
--lg-stack-gap,
var(--md-stack-gap, var(--sm-stack-gap))
);
} }
} }
@media screen and (min-width: 1201px) { @media screen and (min-width: 1201px) {
.stack { .stack {
--stack-direction: var( --stack-direction: var(--xl-stack-direction,
--xl-stack-direction, var(--lg-stack-direction,
var( var(--md-stack-direction, var(--sm-stack-direction))));
--lg-stack-direction, --stack-align: var(--xl-stack-align,
var(--md-stack-direction, var(--sm-stack-direction)) var(--lg-stack-align, var(--md-stack-align, var(--sm-stack-align))));
) --stack-justify: var(--xl-stack-justify,
); var(--lg-stack-justify,
--stack-align: var( var(--md-stack-justify, var(--sm-stack-justify))));
--xl-stack-align, --stack-padding: var(--xl-stack-padding,
var(--lg-stack-align, var(--md-stack-align, var(--sm-stack-align))) var(--lg-stack-padding,
); var(--md-stack-padding, var(--sm-stack-padding))));
--stack-justify: var( --stack-gap: var(--xl-stack-gap,
--xl-stack-justify, var(--lg-stack-gap, var(--md-stack-gap, var(--sm-stack-gap))));
var(
--lg-stack-justify,
var(--md-stack-justify, var(--sm-stack-justify))
)
);
--stack-padding: var(
--xl-stack-padding,
var(
--lg-stack-padding,
var(--md-stack-padding, var(--sm-stack-padding))
)
);
--stack-gap: var(
--xl-stack-gap,
var(--lg-stack-gap, var(--md-stack-gap, var(--sm-stack-gap)))
);
} }
} }
.dark .grid_system {
--guide-color: var(--color-gray-200);
}
.grid_system {
--max-width: 1080px;
--min-width: 368px;
--guide-width: 1px;
--horizontal-margin: 2rem;
--grid-system-width: 100vw;
--guide-color: var(--color-gray-400);
--cross-color: var(--color-gray-600);
display: flex;
position: relative;
flex-direction: column;
max-width: var(--max-width);
min-width: var(--min-width);
margin-top: var(--guide-width);
border-bottom: var(--guide-width) solid var(--guide-color);
margin-left: var(--guide-width);
}
.grid_system::before {
position: absolute;
inset: 0;
left: calc(-1 * var(--guide-width));
top: calc(-1 * var(--guide-width));
content: "";
border: var(--guide-width) solid var(--guide-color);
pointer-events: none;
}
.grid_grid {
--width: clamp(calc(var(--min-width) - var(--guide-width)), calc(var(--grid-system-width) - var(--guide-width) - (var(--horizontal-margin) * 2)), calc(var(--max-width) - var(--guide-width)));
width: var(--width);
height: var(--height);
display: grid;
position: relative;
--column-width: calc(var(--width) / var(--grid-cols));
--row-height: calc(var(--height) / var(--grid-rows));
grid-template-columns: repeat(var(--grid-cols), var(--column-width));
grid-template-rows: repeat(var(--grid-rows), var(--row-height));
}
.grid_cross {
width: -moz-fit-content;
width: fit-content;
height: -moz-fit-content;
height: fit-content;
pointer-events: none;
position: absolute;
grid-column-start: var(--cross-column);
grid-row-start: var(--cross-row);
z-index: 2;
--cross-size: 21px;
--cross-half-size: calc((var(--cross-size) / 2) + var(--guide-width) - 0.5px);
inset: calc(var(--cross-half-size) * -1);
}
.grid_crossLine {
position: absolute;
border: var(--guide-width) solid var(--cross-color);
border-width: 0;
}
.grid_gridGuides {
pointer-events: none;
z-index: 1;
display: contents;
}
.grid_gridGuide {
inset: 0;
position: absolute;
grid-column-start: var(--x);
grid-row-start: var(--y);
grid-column-end: span 1;
grid-row-end: span 1;
border: var(--guide-width) solid var(--guide-color);
border-left: none;
border-top: none;
}
@media screen and (max-width: 400px) {
.grid_system {
--horizontal-margin: 1rem
}
.grid_grid {
--height: var(--xs-height, var(--sm-height));
--grid-rows: var(--xs-grid-rows, var(--sm-grid-rows));
--grid-cols: var(--xs-grid-cols, var(--sm-grid-cols));
--cell-padding: 24px;
--grid-divider-gap: calc(72px - var(--cell-padding))
}
.grid_block {
--grid-row: var(--xs-grid-row, var(--sm-grid-row));
--grid-column: var(--xs-grid-column, var(--sm-grid-column));
--block-display: var(--xs-block-display, var(--sm-block-display));
--cell-rows: var(--xs-cell-rows, var(--sm-cell-rows));
--cell-columns: var(--xs-cell-columns, var(--sm-cell-columns))
}
.grid_cross {
--cross-size: 11px;
--cross-row: var(--xs-cross-row, var(--sm-cross-row));
--cross-column: var(--xs-cross-column, var(--sm-cross-column))
}
.grid_lgGuide,
.grid_mdGuide,
.grid_smGuide,
.grid_smdGuide {
display: none
}
}
@media screen and (min-width: 401px) and (max-width:600px) {
.grid_system {
--horizontal-margin: 1rem
}
.grid_grid {
--height: var(--sm-height);
--grid-rows: var(--sm-grid-rows);
--grid-cols: var(--sm-grid-cols);
--cell-padding: 24px;
--grid-divider-gap: calc(72px - var(--cell-padding))
}
.grid_block {
--grid-row: var(--sm-grid-row);
--grid-column: var(--sm-grid-column);
--cell-rows: var(--sm-cell-rows);
--cell-columns: var(--sm-cell-columns);
--block-display: var(--sm-block-display)
}
.grid_cross {
--cross-size: 11px;
--cross-row: var(--sm-cross-row);
--cross-column: var(--sm-cross-column)
}
.grid_lgGuide,
.grid_mdGuide,
.grid_smdGuide,
.grid_xsGuide {
display: none
}
}
@media screen and (min-width: 601px) and (max-width:768px) {
.grid_grid {
--height: var(--smd-height, var(--md-height, var(--sm-height)));
--grid-rows: var(--smd-grid-rows, var(--md-grid-rows, var(--sm-grid-rows)));
--grid-cols: var(--smd-grid-cols, var(--md-grid-cols, var(--sm-grid-cols)));
--cell-padding: 40px;
--grid-divider-gap: calc(120px - var(--cell-padding))
}
.grid_block {
--grid-row: var(--smd-grid-row, var(--md-grid-row, var(--sm-grid-row)));
--grid-column: var(--smd-grid-column, var(--md-grid-column, var(--sm-grid-column)));
--cell-rows: var(--smd-cell-rows, var(--md-cell-rows, var(--sm-cell-rows)));
--cell-columns: var(--smd-cell-columns, var(--md-cell-columns, var(--sm-cell-columns)));
--block-display: var(--smd-block-display)
}
.grid_cross {
--cross-size: 15px;
--cross-row: var(--smd-cross-row, var(--md-cross-row, var(--sm-cross-row)));
--cross-column: var(--smd-cross-column, var(--md-cross-column, var(--sm-cross-column)))
}
.grid_lgGuide,
.grid_mdGuide,
.grid_smGuide,
.grid_xsGuide {
display: none
}
}
@media screen and (min-width: 769px) and (max-width:960px) {
.grid_grid {
--height: var(--md-height, var(--smd-height, var(--sm-height)));
--grid-rows: var(--md-grid-rows, var(--smd-grid-rows, var(--sm-grid-rows)));
--grid-cols: var(--md-grid-cols, var(--smd-grid-cols, var(--sm-grid-cols)));
--cell-padding: 40px;
--grid-divider-gap: calc(140px - var(--cell-padding))
}
.grid_block {
--grid-row: var(--md-grid-row, var(--smd-grid-row, var(--sm-grid-row)));
--grid-column: var(--md-grid-column, var(--smd-grid-column, var(--sm-grid-column)));
--cell-rows: var(--md-cell-rows, var(--smd-cell-rows, var(--sm-cell-rows)));
--cell-columns: var(--md-cell-columns, var(--smd-cell-columns, var(--sm-cell-columns)));
--block-display: var(--md-block-display, var(--smd-block-display))
}
.grid_cross {
--cross-size: 15px;
--cross-row: var(--md-cross-row, var(--smd-cross-row, var(--sm-cross-row)));
--cross-column: var(--md-cross-column, var(--smd-cross-column, var(--sm-cross-column)))
}
.grid_lgGuide,
.grid_smGuide,
.grid_smdGuide,
.grid_xsGuide {
display: none
}
}
@media screen and (min-width: 961px) {
.grid_grid {
--height: var(--lg-height, var(--md-height, var(--smd-height, var(--sm-height))));
--grid-rows: var(--lg-grid-rows, var(--md-grid-rows, var(--smd-grid-rows, var(--sm-grid-rows))));
--grid-cols: var(--lg-grid-cols, var(--md-grid-cols, var(--smd-grid-cols, var(--sm-grid-cols))));
--cell-padding: 48px;
--grid-divider-gap: calc(140px - var(--cell-padding))
}
.grid_block {
--grid-row: var(--lg-grid-row, var(--md-grid-row, var(--smd-grid-row, var(--sm-grid-row))));
--grid-column: var(--lg-grid-column, var(--md-grid-column, var(--smd-grid-column, var(--sm-grid-column))));
--cell-rows: var(--lg-cell-rows, var(--md-cell-rows, var(--smd-cell-rows, var(--sm-cell-rows))));
--cell-columns: var(--lg-cell-columns, var(--md-cell-columns, var(--smd-cell-columns, var(--sm-cell-columns))));
--block-display: var(--smd-block-display)
}
.grid_cross {
--cross-row: var(--lg-cross-row, var(--md-cross-row, var(--smd-cross-row, var(--sm-cross-row))));
--cross-column: var(--lg-cross-column, var(--md-cross-column, var(--smd-cross-column, var(--sm-cross-column))));
}
.grid_mdGuide,
.grid_smGuide,
.grid_smdGuide,
.grid_xsGuide {
display: none
}
}

View File

@@ -1 +1,2 @@
export * from "./Stack" export * from "./Stack"
export * from "./Grid"

View File

@@ -5,31 +5,6 @@ import HeroComponent from "../components/astro/HeroComponent.astro";
<Layout> <Layout>
<main class="container py-20"> <main class="container py-20">
<div class="flex flex-col items-center justify-center">
<div
class="flex relative max-w-[1080px] min-w-3xs mt-xs mr-xs before:absolute before:inset-0 before:-left-xs before:-top-xs border border-gray-200 pointer-events-none"
>
<!-- Cross -->
<!-- <div
style={{
"--cross-size": "21px",
"--cross-half-size":
"calc(var(--cross-size) / 2) + var(--guide-width, 1px) - 0.5px",
}}
class="w-fit h-fit pointer-events-none z-20 col-start-1 row-start-1 -inset-(--cross-half-size)"
>
<div
class="w-(--cross-half-size) h-(--cross-size) border-r absolute border-gray-600"
>
</div>
<div
class="h-(--cross-half-size) w-(--cross-size) border-b absolute border-gray-600"
>
</div>
</div>
<!-- Hero -->
<HeroComponent /> <HeroComponent />
</div>
</div>
</main> </main>
</Layout> </Layout>