From 5d6366c804406e4cfb2f19d89cb6323e399dca78 Mon Sep 17 00:00:00 2001 From: Jared White Date: Fri, 2 Jun 2023 16:44:47 -0700 Subject: [PATCH] feat: add Grid component (#39) * feat: add the Grid component * docs: update story presentations * docs: update Grid.docs.mdx * fix: use correct props for grid cells * chore: add Grid export to index.ts --- index.ts | 1 + src/layout/Grid.scss | 86 +++++++++++++ src/layout/Grid.tsx | 47 +++++++ src/layout/__stories__/Grid.docs.mdx | 28 +++++ src/layout/__stories__/Grid.stories.tsx | 157 ++++++++++++++++++++++++ 5 files changed, 319 insertions(+) create mode 100644 src/layout/Grid.scss create mode 100644 src/layout/Grid.tsx create mode 100644 src/layout/__stories__/Grid.docs.mdx create mode 100644 src/layout/__stories__/Grid.stories.tsx diff --git a/index.ts b/index.ts index 041a86e..6ccd627 100644 --- a/index.ts +++ b/index.ts @@ -9,3 +9,4 @@ export { default as Alert } from "./src/blocks/Alert" export { default as Message } from "./src/blocks/Message" export { default as Toast } from "./src/blocks/Toast" export { default as Card } from "./src/blocks/Card" +export { default as Grid } from "./src/layout/Grid" diff --git a/src/layout/Grid.scss b/src/layout/Grid.scss new file mode 100644 index 0000000..21200fd --- /dev/null +++ b/src/layout/Grid.scss @@ -0,0 +1,86 @@ +.grid { + --grid-gap-sm: var(--bloom-s4); + --grid-gap-md: var(--bloom-s6); + --grid-gap-lg: var(--bloom-s8); + --grid-gap-xl: var(--bloom-s12); + + --grid-gap-tablet: var(--grid-gap-sm); + + --grid-gap: var(--grid-gap-md); + + @media (max-width: 1023px) { + --grid-gap: var(--grid-gap-tablet); + } + + display: grid; + gap: var(--grid-gap); + + @media (min-width: 1024px) { + &[data-spacing="sm"] { + --grid-gap: var(--grid-gap-sm); + } + + &[data-spacing="md"] { + --grid-gap: var(--grid-gap-md); + } + + &[data-spacing="lg"] { + --grid-gap: var(--grid-gap-lg); + } + + &[data-spacing="xl"] { + --grid-gap: var(--grid-gap-xl); + } + } +} + +.grid-row { + --grid-columns: auto-fit; + --grid-minimum-column-size: 0; + + @media (max-width: 639px) { + --grid-columns: 1; + } + + display: grid; + gap: inherit; + grid-template-columns: repeat(var(--grid-columns), minmax(var(--grid-minimum-column-size), 1fr)); +} + +.grid-row > * { + overflow-wrap: break-word; +} + +@media (min-width: 640px) { + .grid-row[data-columns="4"] { + --grid-columns: 4; + } + + .grid-row[data-columns="3"] { + --grid-columns: 3; + } + + .grid-row[data-columns="2"] { + --grid-columns: 2; + } + + .grid-row[data-columns="1"] { + --grid-columns: 1; + } + + .grid-row[data-columns="1+2"] { + --grid-columns: 4; + + > *:first-child { + grid-column: span 2; + } + } + + .grid-row[data-columns="2+1"] { + --grid-columns: 4; + + > *:last-child { + grid-column: span 2; + } + } +} diff --git a/src/layout/Grid.tsx b/src/layout/Grid.tsx new file mode 100644 index 0000000..bd3b113 --- /dev/null +++ b/src/layout/Grid.tsx @@ -0,0 +1,47 @@ +import React from "react" + +import "./Grid.scss" + +export interface GridCellProps { + children: React.ReactNode + id?: string + className?: string +} + +const GridCell = (props: GridCellProps) => { + const classNames = ["grid-cell"] + if (props.className) classNames.push(props.className) + + return
{props.children}
+} + +export interface GridRowProps extends GridCellProps { + columns?: number | string +} + +const GridRow = (props: GridRowProps) => { + const classNames = ["grid-row"] + if (props.className) classNames.push(props.className) + + return
{props.children}
+} + +export interface GridProps extends GridCellProps { + /** + * Control the gap between grid cells + * @default md + */ + spacing?: "sm" | "md" | "lg" | "xl" +} + +const Grid = (props: GridProps) => { + const classNames = ["grid"] + if (props.className) classNames.push(props.className) + + return
{props.children}
+} + +Grid.Cell = GridCell +Grid.Row = GridRow + +export { Grid as default, GridRow, GridCell } diff --git a/src/layout/__stories__/Grid.docs.mdx b/src/layout/__stories__/Grid.docs.mdx new file mode 100644 index 0000000..3a0e3e8 --- /dev/null +++ b/src/layout/__stories__/Grid.docs.mdx @@ -0,0 +1,28 @@ +import { ArgsTable } from "@storybook/addon-docs" + +import Grid from "../Grid" + +# <Grid /> + +## Properties + + + +## Row Properties + + + +## Cell Properties + + + +## Theme Variables + +| Name | Description | Default | +| ----------------------------------- | ---------------------------------------------------------------- | ------------------------------------ | +| `--grid-gap-sm` | | `--bloom-s4` | +| `--grid-gap-md` | | `--bloom-s6` | +| `--grid-gap-lg` | | `--bloom-s8` | +| `--grid-gap-xl` | | `--bloom-s12` | +| `--grid-gap-tablet` | | `--grid-gap-sm` | +| `--grid-gap` | | `--grid-gap-md` | diff --git a/src/layout/__stories__/Grid.stories.tsx b/src/layout/__stories__/Grid.stories.tsx new file mode 100644 index 0000000..db19b7f --- /dev/null +++ b/src/layout/__stories__/Grid.stories.tsx @@ -0,0 +1,157 @@ +import React from "react" +import { Story } from "@storybook/react" + +import Grid from "../Grid" +import FieldValue from "../../forms/FieldValue" +import Heading from "../../text/Heading" + +import MDXDocs from "./Grid.docs.mdx" + +export default { + title: "Layout/Grid", + component: Grid, + parameters: { + docs: { + page: MDXDocs, + }, + }, +} + +export const gridExample = () => ( + <> + Three Columns: + + + + Cell 1 + Cell 2 + Cell 3 + + + + Cell 4 + Cell 5 + Cell 6 + + + + Four Columns: + + + + Cell 1 + Cell 2 + Cell 3 + Cell 4 + + + + Two Columns: + + + + Cell 1 + Cell 2 + + + + One Column + Two Columns: + + + + Cell 1 (Long) + Cell 2 + Cell 3 + + + + Two Columns + One Column: + + + + Cell 1 + Cell 2 + Cell 3 (Long) + + + + + +) + +export const gridSpacings = () => ( + <> + Small Spacing + + + + 1 + 2 + 3 + + + + Medium (Default) Spacing + + + + 1 + 2 + 3 + + + + Large Spacing + + + + 1 + 2 + 3 + + + + Extra Large Spacing + + + + 1 + 2 + 3 + + + + + +) + +export const sectionsAndForms = () => ( + <> +
+ Form Values + + + + Pool, BBQ, Rooftop View + + + Pool, BBQ, Rooftop View + + + Pool, BBQ, Rooftop View + + + + + Pool, BBQ, Rooftop View + + + Pool, BBQ, Rooftop View + + + +
+ + + +)