Skip to content

Commit

Permalink
feat: add Grid component (#39)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
jaredcwhite authored Jun 2, 2023
1 parent 8660d88 commit 5d6366c
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 0 deletions.
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
86 changes: 86 additions & 0 deletions src/layout/Grid.scss
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
47 changes: 47 additions & 0 deletions src/layout/Grid.tsx
Original file line number Diff line number Diff line change
@@ -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 <div id={props.id} className={classNames.join(" ")} role="gridcell">{props.children}</div>
}

export interface GridRowProps extends GridCellProps {
columns?: number | string
}

const GridRow = (props: GridRowProps) => {
const classNames = ["grid-row"]
if (props.className) classNames.push(props.className)

return <div id={props.id} className={classNames.join(" ")} role="row" data-columns={props.columns}>{props.children}</div>
}

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 <div id={props.id} className={classNames.join(" ")} data-spacing={props.spacing} role="grid">{props.children}</div>
}

Grid.Cell = GridCell
Grid.Row = GridRow

export { Grid as default, GridRow, GridCell }
28 changes: 28 additions & 0 deletions src/layout/__stories__/Grid.docs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ArgsTable } from "@storybook/addon-docs"

import Grid from "../Grid"

# &lt;Grid /&gt;

## Properties

<ArgsTable of={Grid} />

## Row Properties

<ArgsTable of={Grid.Row} />

## Cell Properties

<ArgsTable of={Grid.Cell} />

## 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` |
157 changes: 157 additions & 0 deletions src/layout/__stories__/Grid.stories.tsx
Original file line number Diff line number Diff line change
@@ -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 = () => (
<>
<Heading size="xl">Three Columns:</Heading>

<Grid spacing="lg">
<Grid.Row>
<Grid.Cell>Cell 1</Grid.Cell>
<Grid.Cell>Cell 2</Grid.Cell>
<Grid.Cell>Cell 3</Grid.Cell>
</Grid.Row>

<Grid.Row columns={3}>
<Grid.Cell>Cell 4</Grid.Cell>
<Grid.Cell>Cell 5</Grid.Cell>
<Grid.Cell>Cell 6</Grid.Cell>
</Grid.Row>
</Grid>

<Heading size="xl">Four Columns:</Heading>

<Grid spacing="lg">
<Grid.Row columns={4}>
<Grid.Cell>Cell 1</Grid.Cell>
<Grid.Cell>Cell 2</Grid.Cell>
<Grid.Cell>Cell 3</Grid.Cell>
<Grid.Cell>Cell 4</Grid.Cell>
</Grid.Row>
</Grid>

<Heading size="xl">Two Columns:</Heading>

<Grid spacing="lg">
<Grid.Row>
<Grid.Cell>Cell 1</Grid.Cell>
<Grid.Cell>Cell 2</Grid.Cell>
</Grid.Row>
</Grid>

<Heading size="xl">One Column + Two Columns:</Heading>

<Grid spacing="lg">
<Grid.Row columns="1+2">
<Grid.Cell>Cell 1 (Long)</Grid.Cell>
<Grid.Cell>Cell 2</Grid.Cell>
<Grid.Cell>Cell 3</Grid.Cell>
</Grid.Row>
</Grid>

<Heading size="xl">Two Columns + One Column:</Heading>

<Grid spacing="lg">
<Grid.Row columns="2+1">
<Grid.Cell>Cell 1</Grid.Cell>
<Grid.Cell>Cell 2</Grid.Cell>
<Grid.Cell>Cell 3 (Long)</Grid.Cell>
</Grid.Row>
</Grid>

<style>{".grid { margin-block: var(--bloom-spacer-content); } .grid-row > * { background: #eee; padding: .5rem }"}</style>
</>
)

export const gridSpacings = () => (
<>
<Heading size="xl">Small Spacing</Heading>

<Grid spacing="sm">
<Grid.Row>
<Grid.Cell>1</Grid.Cell>
<Grid.Cell>2</Grid.Cell>
<Grid.Cell>3</Grid.Cell>
</Grid.Row>
</Grid>

<Heading size="xl">Medium (Default) Spacing</Heading>

<Grid spacing="md">
<Grid.Row>
<Grid.Cell>1</Grid.Cell>
<Grid.Cell>2</Grid.Cell>
<Grid.Cell>3</Grid.Cell>
</Grid.Row>
</Grid>

<Heading size="xl">Large Spacing</Heading>

<Grid spacing="lg">
<Grid.Row>
<Grid.Cell>1</Grid.Cell>
<Grid.Cell>2</Grid.Cell>
<Grid.Cell>3</Grid.Cell>
</Grid.Row>
</Grid>

<Heading size="xl">Extra Large Spacing</Heading>

<Grid spacing="xl">
<Grid.Row>
<Grid.Cell>1</Grid.Cell>
<Grid.Cell>2</Grid.Cell>
<Grid.Cell>3</Grid.Cell>
</Grid.Row>
</Grid>

<style>{".grid { margin-block: var(--bloom-spacer-content); } .grid-row > * { background: #eee; padding: .5rem }"}</style>
</>
)

export const sectionsAndForms = () => (
<>
<section>
<Heading size="xl">Form Values</Heading>
<Grid spacing="md">
<Grid.Row>
<FieldValue label="Property Amenities">
Pool, BBQ, Rooftop View
</FieldValue>
<FieldValue label="Property Amenities">
Pool, BBQ, Rooftop View
</FieldValue>
<FieldValue label="Property Amenities">
Pool, BBQ, Rooftop View
</FieldValue>
</Grid.Row>
<Grid.Row>
<FieldValue label="Property Amenities">
Pool, BBQ, Rooftop View
</FieldValue>
<FieldValue label="Property Amenities">
Pool, BBQ, Rooftop View
</FieldValue>
</Grid.Row>
</Grid>
</section>

<style>{".grid { background: var(--bloom-bg-color-surface-primary); padding: var(--bloom-spacer-content); margin-block: var(--bloom-spacer-content) }"}</style>
</>
)

0 comments on commit 5d6366c

Please sign in to comment.