diff --git a/README.md b/README.md index 5d5a657..90a8905 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,74 @@ -# `styled-css-grid 🍱` - -[![Travis](https://img.shields.io/travis/azz/styled-css-grid.svg?style=flat-square)](https://travis-ci.org/azz/styled-css-grid) -[![Prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) -[![npm](https://img.shields.io/npm/v/styled-css-grid.svg?style=flat-square)](https://npmjs.org/styled-css-grid) -[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)](https://github.com/semantic-release/semantic-release) -[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE) -[![JS.ORG](https://img.shields.io/badge/js.org-dns-ffb400.svg?style=flat-square)](http://js.org) - -> A tiny (~2kb) [CSS grid] layout for React, built with [styled-components] 💅. - -## examples - -See the **[website]**. - -## installation - -Install React and [styled-components], then: - -```bash -$ yarn add styled-css-grid -``` - -## usage - -```jsx -import React from "react"; -import { Grid, Cell } from "styled-css-grid"; - -const MyGrid = () => ( - - foo - bar - baz - -); -``` - -## api - -### `Cell` - -A cell. Not too much to say... - -Props: - -* `width`: Cell width in units, default is `1`. -* `height`: Cell height in units, default is `1`. -* `left`: The [grid-column-start] CSS property. Not provided by default. -* `top`: The [grid-row-start] CSS property. Not provided by default. -* `middle`: Vertically align the contents of the cell. Default is `false`. -* `center`: Horizontally align the text contents of the cell. Default is `false`. - -### `Grid` - -Wrap your cells in `Grid`. Pretty simple. - -Props: - -* `columns`: Number of columns to draw, default is `12`. -* `gap`: Gap between cells. Default is `"8px"`. -* `minRowHeight`: Minimum height of each row. Default is `"20px"`. -* `flow`: The [grid-auto-flow] CSS property. Default is `"row"`. - -[website]: https://styled-css-grid.js.org/ -[CSS grid]: https://mdn.io/CSS_Grid_Layout -[styled-components]: https://github.com/styled-components/styled-components -[grid-auto-flow]: https://mdn.io/grid-auto-flow -[grid-row-start]: https://mdn.io/grid-row-start -[grid-column-start]: https://mdn.io/grid-column-start +# `styled-css-grid 🍱` + +[![Travis](https://img.shields.io/travis/azz/styled-css-grid.svg?style=flat-square)](https://travis-ci.org/azz/styled-css-grid) +[![Prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) +[![npm](https://img.shields.io/npm/v/styled-css-grid.svg?style=flat-square)](https://npmjs.org/styled-css-grid) +[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)](https://github.com/semantic-release/semantic-release) +[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE) +[![JS.ORG](https://img.shields.io/badge/js.org-dns-ffb400.svg?style=flat-square)](http://js.org) + +> A tiny (~2kb) [CSS grid] layout for React, built with [styled-components] 💅. + +## examples + +See the **[website]**. + +## installation + +Install React and [styled-components], then: + +```bash +$ yarn add styled-css-grid +``` + +## usage + +```jsx +import React from "react"; +import { Grid, Cell } from "styled-css-grid"; + +const MyGrid = () => ( + + foo + bar + baz + +); +``` + +## api + +### `Cell` + +A cell. Not too much to say... + +Props: + +* `width`: Cell width in units, default is `1`. +* `height`: Cell height in units, default is `1`. +* `left`: The [grid-column-start] CSS property. Not provided by default. +* `top`: The [grid-row-start] CSS property. Not provided by default. +* `middle`: Vertically align the contents of the cell. Default is `false`. +* `center`: Horizontally align the text contents of the cell. Default is `false`. + +### `Grid` + +Wrap your cells in `Grid`. Pretty simple. + +Props: + +* `columns`: The [grid-template-columns] CSS property. When a number is passed + it is a shorthand to specify the number of columns. Default is `12`. +* `gap`: Gap between cells. Default is `"8px"`. +* `minRowHeight`: Minimum height of each row. Default is `"20px"`. +* `flow`: The [grid-auto-flow] CSS property. Default is `"row"`. +* `rows`: The [grid-template-rows] CSS property. Not provided by default. + +[website]: https://styled-css-grid.js.org/ +[CSS grid]: https://mdn.io/CSS_Grid_Layout +[styled-components]: https://github.com/styled-components/styled-components +[grid-auto-flow]: https://mdn.io/grid-auto-flow +[grid-row-start]: https://mdn.io/grid-row-start +[grid-column-start]: https://mdn.io/grid-column-start +[grid-template-columns]: https://mdn.io/grid-template-columns +[grid-template-rows]: https://mdn.io/grid-template-rows diff --git a/lib/Cell.js b/lib/Cell.js index 3f73176..f1f8c9a 100644 --- a/lib/Cell.js +++ b/lib/Cell.js @@ -1,25 +1,25 @@ -import styled from "styled-components"; - -const Cell = styled.section` - height: 100%; - min-width: 0; - overflow: hidden; - align-content: space-around; - grid-column-end: ${({ width = 1 }) => `span ${width}`}; - grid-row-end: ${({ height = 1 }) => `span ${height}`}; - - ${({ left }) => left && `grid-column-start: ${left}`}; - ${({ top }) => top && `grid-row-start: ${top}`}; - - ${({ center = false }) => center && `text-align: center;`}; - - ${/* prettier-ignore */ - ({ middle = false }) => middle && ` - display: inline-flex; - flex-flow: column wrap; - justify-content: center; - justify-self: stretch; - `}; -`; - -export default Cell; +import styled from "styled-components"; + +const Cell = styled.section` + height: 100%; + min-width: 0; + overflow: hidden; + align-content: space-around; + grid-column-end: ${({ width = 1 }) => `span ${width}`}; + grid-row-end: ${({ height = 1 }) => `span ${height}`}; + + ${({ left }) => left && `grid-column-start: ${left}`}; + ${({ top }) => top && `grid-row-start: ${top}`}; + + ${({ center = false }) => center && `text-align: center;`}; + + ${/* prettier-ignore */ + ({ middle = false }) => middle && ` + display: inline-flex; + flex-flow: column wrap; + justify-content: center; + justify-self: stretch; + `}; +`; + +export default Cell; diff --git a/lib/Grid.js b/lib/Grid.js index bb94e83..10ccd0c 100644 --- a/lib/Grid.js +++ b/lib/Grid.js @@ -1,21 +1,22 @@ -import styled from "styled-components"; - -const minmax = ({ minRowHeight = "20px" }) => `minmax(${minRowHeight}, auto)`; - -const columnRepeat = ({ columns = 12 }) => `repeat(${columns}, 1fr)`; - -const gap = ({ gap = "8px" }) => `${gap} ${gap}`; - -const flow = ({ flow = "row" }) => flow; - -const Grid = styled.div` - min-height: 100%; - display: grid; - grid-auto-flow: ${flow}; - grid-auto-rows: ${minmax}; - grid-template-rows: ${minmax}; - grid-template-columns: ${columnRepeat}; - grid-gap: ${gap}; -`; - -export default Grid; +import styled from "styled-components"; + +const autoRows = ({ minRowHeight = "20px" }) => `minmax(${minRowHeight}, auto)`; + +const columns = ({ columns = 12 }) => + typeof columns === "number" ? `repeat(${columns}, 1fr)` : columns; + +const gap = ({ gap = "8px" }) => `${gap} ${gap}`; + +const flow = ({ flow = "row" }) => flow; + +const Grid = styled.div` + min-height: 100%; + display: grid; + grid-auto-flow: ${flow}; + grid-auto-rows: ${autoRows}; + ${({ rows }) => rows && `grid-template-rows: ${rows}`}; + grid-template-columns: ${columns}; + grid-gap: ${gap}; +`; + +export default Grid; diff --git a/lib/__tests__/Grid.test.js b/lib/__tests__/Grid.test.js index b92fa8a..5eb6c24 100644 --- a/lib/__tests__/Grid.test.js +++ b/lib/__tests__/Grid.test.js @@ -10,20 +10,34 @@ describe("", () => { expect(tree).toMatchSnapshot(); }); - test("'columns' prop sets 'grid-template-columns'", () => { + test("'columns' as number prop sets 'grid-template-columns' to repeat()", () => { const tree = renderer.create().toJSON(); expect(tree).toHaveStyleRule("grid-template-columns", "repeat(7,1fr)"); }); + test("'columns' as string prop sets 'grid-template-columns'", () => { + const tree = renderer + .create() + .toJSON(); + expect(tree).toHaveStyleRule( + "grid-template-columns", + "repeat(auto-fit,minmax(100px,1fr))" + ); + }); + + test("'rows' as string prop sets 'grid-template-rows'", () => { + const tree = renderer.create().toJSON(); + expect(tree).toHaveStyleRule("grid-template-rows", "1fr 2fr 1fr"); + }); + test("'gap' prop sets 'grid-gap'", () => { const tree = renderer.create().toJSON(); expect(tree).toHaveStyleRule("grid-gap", "7px 7px"); }); - test("'minRowHeight' prop sets 'grid-auto-rows' and 'grid-template-rows'", () => { + test("'minRowHeight' prop sets 'grid-auto-rows'", () => { const tree = renderer.create().toJSON(); expect(tree).toHaveStyleRule("grid-auto-rows", "minmax(7px,auto)"); - expect(tree).toHaveStyleRule("grid-template-rows", "minmax(7px,auto)"); }); test("'flow' prop sets 'grid-auto-flow'", () => { diff --git a/lib/__tests__/__snapshots__/Grid.test.js.snap b/lib/__tests__/__snapshots__/Grid.test.js.snap index 69de459..7e1a20d 100644 --- a/lib/__tests__/__snapshots__/Grid.test.js.snap +++ b/lib/__tests__/__snapshots__/Grid.test.js.snap @@ -6,7 +6,6 @@ exports[` matches snapshot with default args 1`] = ` display: grid; grid-auto-flow: row; grid-auto-rows: minmax(20px,auto); - grid-template-rows: minmax(20px,auto); grid-template-columns: repeat(12,1fr); grid-gap: 8px 8px; } diff --git a/website/components/Main.js b/website/components/Main.js index 672a326..aac4463 100644 --- a/website/components/Main.js +++ b/website/components/Main.js @@ -6,15 +6,17 @@ import HolyGrailSection from "./sections/HolyGrail"; import PositioningSection from "./sections/Positioning"; import TraditionalGridSection from "./sections/TraditionalGrid"; import TransposedGridSection from "./sections/TransposedGrid"; +import ResponsiveSection from "./sections/Responsive"; const Main = () =>
- - + + +
; export default Main; diff --git a/website/components/sections/Centering.js b/website/components/sections/Centering.js index 40c1565..d2a0219 100644 --- a/website/components/sections/Centering.js +++ b/website/components/sections/Centering.js @@ -43,7 +43,7 @@ const CenteringSection = () => } output={} - path={"website/components/Centering.js"} + path={"website/components/sections/Centering.js"} /> ; diff --git a/website/components/sections/Dense.js b/website/components/sections/Dense.js index 443d147..6a2cf68 100644 --- a/website/components/sections/Dense.js +++ b/website/components/sections/Dense.js @@ -63,7 +63,7 @@ const DenseSection = () =>

By default, styled-css-grid set the flow property to{" "} row. However, by setting it to row dense you can - turn on CSS grid"s dense cell packing. Notice how the order of the + turn on CSS grid's dense cell packing. Notice how the order of the cells in the markup is not same when it is rendered!

-
- - - Header +
+ + +

Header

- + Menu - + Content - + Ads - + Footer
; const code = stripIndent` - - - Header + + +

Header

- - Menu - - - Content - - - Ads - - + + Menu + Content + Ads + + Footer
@@ -54,7 +55,14 @@ const HolyGrailSection = () => Holy Grail {" "} - layout is trivial! + layout is trivial using the rows prop. This prop is forwarded + to the{" "} + + grid-template-rows + {" "} + CSS property. In this example we set the first and last rows to be at + least 45px tall, but auto-grow if the content grows. The middle row is set + to 1fr, which will grow to take up all available space.

+
+ + + A + + + B + + + C + + + D + + + E + + + F + + +
; + +const code = stripIndent` + + A + B + ... + +`; + +const ResponsiveSection = () => +
+ Responsive Layout +

+ The{" "} + + grid-template-columns + {" "} + CSS property is incredibly powerful for building responsive content. When + the columns prop is a number, it is a shorthand for{" "} + grid-template-columns: repeat(N, 1fr). However, when you pass + a string, the value is passed directly to the CSS property, allowing you + leverage the full power of this property. +

+

+ If you're just after basic responsive content that will automatically + fit to your content, you can use{" "} + repeat(auto-fit, minmax(120px, 1fr)) as your{" "} + columns prop, which will create columns to auto-fit your + content with a minimum width of 120px. +

+

Resize your browser for an example.

+ + + {code} + + + } + output={} + path={"website/components/sections/Responsive.js"} + /> +
; + +export default ResponsiveSection;