diff --git a/packages/css/src/components/grid/grid.scss b/packages/css/src/components/grid/grid.scss index 4fd3e6d1d9..56d1773427 100644 --- a/packages/css/src/components/grid/grid.scss +++ b/packages/css/src/components/grid/grid.scss @@ -6,10 +6,11 @@ @import "../../common/breakpoint"; .amsterdam-grid { + column-gap: var(--amsterdam-grid-column-gap); display: grid; - gap: var(--amsterdam-grid-gap); grid-template-columns: repeat(var(--amsterdam-grid-column-count), 1fr); padding-inline: var(--amsterdam-grid-padding-inline); + row-gap: var(--amsterdam-grid-row-gap-md); @media screen and (min-width: $amsterdam-breakpoint-medium) { grid-template-columns: repeat(var(--amsterdam-grid-medium-column-count), 1fr); @@ -25,47 +26,47 @@ } .amsterdam-grid--gap-vertical--small { - row-gap: calc(var(--amsterdam-grid-gap) / 2); + row-gap: var(--amsterdam-grid-row-gap-sm); } .amsterdam-grid--gap-vertical--large { - row-gap: calc(var(--amsterdam-grid-gap) * 2); + row-gap: var(--amsterdam-grid-row-gap-lg); } .amsterdam-grid--padding-bottom--small { - padding-block-end: calc(var(--amsterdam-grid-gap) / 2); + padding-block-end: var(--amsterdam-grid-padding-block-sm); } .amsterdam-grid--padding-bottom--medium { - padding-block-end: var(--amsterdam-grid-gap); + padding-block-end: var(--amsterdam-grid-padding-block-md); } .amsterdam-grid--padding-bottom--large { - padding-block-end: calc(var(--amsterdam-grid-gap) * 2); + padding-block-end: var(--amsterdam-grid-padding-block-lg); } .amsterdam-grid--padding-top--small { - padding-block-start: calc(var(--amsterdam-grid-gap) / 2); + padding-block-start: var(--amsterdam-grid-padding-block-sm); } .amsterdam-grid--padding-top--medium { - padding-block-start: var(--amsterdam-grid-gap); + padding-block-start: var(--amsterdam-grid-padding-block-md); } .amsterdam-grid--padding-top--large { - padding-block-start: calc(var(--amsterdam-grid-gap) * 2); + padding-block-start: var(--amsterdam-grid-padding-block-lg); } .amsterdam-grid--padding-vertical--small { - padding-block: calc(var(--amsterdam-grid-gap) / 2); + padding-block: var(--amsterdam-grid-padding-block-sm); } .amsterdam-grid--padding-vertical--medium { - padding-block: var(--amsterdam-grid-gap); + padding-block: var(--amsterdam-grid-padding-block-md); } .amsterdam-grid--padding-vertical--large { - padding-block: calc(var(--amsterdam-grid-gap) * 2); + padding-block: var(--amsterdam-grid-padding-block-lg); } .amsterdam-grid__cell--span-all { diff --git a/packages/react/src/Grid/Grid.test.tsx b/packages/react/src/Grid/Grid.test.tsx index 05a144ee71..f59d1f4771 100644 --- a/packages/react/src/Grid/Grid.test.tsx +++ b/packages/react/src/Grid/Grid.test.tsx @@ -1,63 +1,101 @@ import { render } from '@testing-library/react' import { createRef } from 'react' import { Grid } from './Grid' +import type { GridPaddingSize } from './Grid' import '@testing-library/jest-dom' +const paddingSizes = ['small', 'medium', 'large'] + describe('Grid', () => { it('renders', () => { const { container } = render() + const component = container.querySelector(':only-child') + expect(component).toBeInTheDocument() + expect(component).toBeVisible() }) it('renders a design system BEM class name', () => { const { container } = render() + const component = container.querySelector(':only-child') + expect(component).toHaveClass('amsterdam-grid') }) it('renders an additional class name', () => { const { container } = render() + const component = container.querySelector(':only-child') + expect(component).toHaveClass('extra') + expect(component).toHaveClass('amsterdam-grid') }) - it('renders a medium vertical padding class name', () => { - const { container } = render() - const component = container.querySelector(':only-child') - expect(component).toHaveClass('amsterdam-grid--padding-vertical--medium') - }) + it('renders the correct class name for a zero gap', () => { + const { container } = render() - it('renders a small top class name', () => { - const { container } = render() const component = container.querySelector(':only-child') - expect(component).toHaveClass('amsterdam-grid--padding-top--small') + + expect(component).toHaveClass('amsterdam-grid--gap-vertical--none') }) - it('renders a large bottom class name', () => { - const { container } = render() + it(`renders the correct class name for a small gap`, () => { + const { container } = render() + const component = container.querySelector(':only-child') - expect(component).toHaveClass('amsterdam-grid--padding-bottom--large') + + expect(component).toHaveClass('amsterdam-grid--gap-vertical--small') }) - it('renders a class name for a vertical gap', () => { + it(`renders the correct class name for a large gap`, () => { const { container } = render() + const component = container.querySelector(':only-child') + expect(component).toHaveClass('amsterdam-grid--gap-vertical--large') }) - it('renders a class name for a vertical gap and a vertical padding', () => { - const { container } = render() - const component = container.querySelector(':only-child') - expect(component).toHaveClass('amsterdam-grid--gap-vertical--small amsterdam-grid--padding-vertical--large') + paddingSizes.forEach((size) => { + it(`renders the correct class name for a ${size} bottom padding`, () => { + const { container } = render() + + const component = container.querySelector(':only-child') + + expect(component).toHaveClass(`amsterdam-grid--padding-bottom--${size}`) + }) + }) + + paddingSizes.forEach((size) => { + it(`renders the correct class name for a ${size} top padding`, () => { + const { container } = render() + + const component = container.querySelector(':only-child') + + expect(component).toHaveClass(`amsterdam-grid--padding-top--${size}`) + }) + }) + + paddingSizes.forEach((size) => { + it(`renders the correct class name for a ${size} vertical padding`, () => { + const { container } = render() + + const component = container.querySelector(':only-child') + + expect(component).toHaveClass(`amsterdam-grid--padding-vertical--${size}`) + }) }) it('supports ForwardRef in React', () => { const ref = createRef() + const { container } = render() + const component = container.querySelector(':only-child') + expect(ref.current).toBe(component) }) }) diff --git a/packages/react/src/Grid/Grid.tsx b/packages/react/src/Grid/Grid.tsx index 2942a49d2c..0bd9ba9e17 100644 --- a/packages/react/src/Grid/Grid.tsx +++ b/packages/react/src/Grid/Grid.tsx @@ -16,7 +16,7 @@ export type GridColumnNumbers = { wide: GridColumnNumber } -type GridPaddingSize = 'small' | 'medium' | 'large' +export type GridPaddingSize = 'small' | 'medium' | 'large' type GridPaddingVerticalProp = { paddingBottom?: never diff --git a/proprietary/tokens/src/brand/amsterdam/space.compact.tokens.json b/proprietary/tokens/src/brand/amsterdam/space.compact.tokens.json index dededef4d8..5e3c91a1dd 100644 --- a/proprietary/tokens/src/brand/amsterdam/space.compact.tokens.json +++ b/proprietary/tokens/src/brand/amsterdam/space.compact.tokens.json @@ -3,7 +3,10 @@ "space": { "xs": { "value": "clamp(0.25rem, calc(0.390625vw - 0.015625rem), 0.625rem)" }, "sm": { "value": "clamp(0.5rem, calc(0.78125vw - 0.03125rem), 1.25rem)" }, - "md": { "value": "clamp(1rem, calc(1.5625vw - 0.0625rem), 2.5rem)" }, + "md": { + "value": "clamp(1rem, calc(1.5625vw - 0.0625rem), 2.5rem)", + "comment": "Grows from 16px at 1088px wide to 40px at 2624px wide." + }, "lg": { "value": "clamp(1.5rem, calc(2.34375vw - 0.09375rem), 3.75rem)" }, "xl": { "value": "clamp(2rem, calc(3.125vw - 0.125rem), 5rem)" } } diff --git a/proprietary/tokens/src/brand/amsterdam/space.tokens.json b/proprietary/tokens/src/brand/amsterdam/space.tokens.json index e47eb6bc33..49aeff7dc9 100644 --- a/proprietary/tokens/src/brand/amsterdam/space.tokens.json +++ b/proprietary/tokens/src/brand/amsterdam/space.tokens.json @@ -3,7 +3,10 @@ "space": { "xs": { "value": "clamp(0.25rem, calc(0.78125vw + 0.09375rem), 0.875rem)" }, "sm": { "value": "clamp(0.5rem, calc(1.5625vw + 0.1875rem), 1.75rem)" }, - "md": { "value": "clamp(1rem, calc(3.125vw + 0.375rem), 3.5rem)" }, + "md": { + "value": "clamp(1rem, calc(3.125vw + 0.375rem), 3.5rem)", + "comment": "Grows from 16px at 320px wide to 56px at 1600px wide." + }, "lg": { "value": "clamp(1.5rem, calc(4.6875vw + 0.5625rem), 5.25rem)" }, "xl": { "value": "clamp(2rem, calc(6.25vw + 0.75rem), 7rem)" } } diff --git a/proprietary/tokens/src/components/amsterdam/grid.compact.tokens.json b/proprietary/tokens/src/components/amsterdam/grid.compact.tokens.json index cc8e5b85e8..e73e5f975e 100644 --- a/proprietary/tokens/src/components/amsterdam/grid.compact.tokens.json +++ b/proprietary/tokens/src/components/amsterdam/grid.compact.tokens.json @@ -1,14 +1,7 @@ { "amsterdam": { "grid": { - "gap": { - "value": "clamp(1rem, calc(1.5625vw - 0.0625rem), 2.5rem)", - "comment": "Grows from 16px at 1088px wide to 40px at 2624px wide." - }, - "padding-inline": { - "value": "clamp(1rem, calc(1.5625vw - 0.0625rem), 2.5rem)", - "comment": "Equals the gap." - } + "padding-inline": { "value": "{amsterdam.space.md}" } } } } diff --git a/proprietary/tokens/src/components/amsterdam/grid.tokens.json b/proprietary/tokens/src/components/amsterdam/grid.tokens.json index a6ec7c33ac..2077aedf86 100644 --- a/proprietary/tokens/src/components/amsterdam/grid.tokens.json +++ b/proprietary/tokens/src/components/amsterdam/grid.tokens.json @@ -2,13 +2,17 @@ "amsterdam": { "grid": { "column-count": { "value": "4" }, - "gap": { - "value": "clamp(1rem, calc(3.125vw + 0.375rem), 3.5rem)", - "comment": "Grows from 16px at 320px wide to 56px at 1600px wide." + "column-gap": { "value": "{amsterdam.space.md}" }, + "padding-block": { + "sm": { "value": "{amsterdam.space.sm}" }, + "md": { "value": "{amsterdam.space.md}" }, + "lg": { "value": "{amsterdam.space.lg}" } }, - "padding-inline": { - "value": "clamp(1.5rem, calc(4.6875vw + 0.5625rem), 5.25rem)", - "comment": "Equals 1.5 times the gap." + "padding-inline": { "value": "{amsterdam.space.lg}" }, + "row-gap": { + "sm": { "value": "{amsterdam.space.sm}" }, + "md": { "value": "{amsterdam.space.md}" }, + "lg": { "value": "{amsterdam.space.lg}" } }, "medium": { "column-count": { "value": "8" } diff --git a/proprietary/tokens/src/components/amsterdam/header.tokens.json b/proprietary/tokens/src/components/amsterdam/header.tokens.json index f45bb65980..7c4d4bfac9 100644 --- a/proprietary/tokens/src/components/amsterdam/header.tokens.json +++ b/proprietary/tokens/src/components/amsterdam/header.tokens.json @@ -1,7 +1,10 @@ { "amsterdam": { "header": { - "column-gap": { "value": "{amsterdam.grid.gap}" } + "column-gap": { + "value": "{amsterdam.space.md}", + "comment": "Must have the same value as `amsterdam.grid.column-gap`." + } } } } diff --git a/proprietary/tokens/src/components/amsterdam/mega-menu.tokens.json b/proprietary/tokens/src/components/amsterdam/mega-menu.tokens.json index 88486b3e30..a739605b63 100644 --- a/proprietary/tokens/src/components/amsterdam/mega-menu.tokens.json +++ b/proprietary/tokens/src/components/amsterdam/mega-menu.tokens.json @@ -2,10 +2,16 @@ "amsterdam": { "mega-menu": { "list-category": { - "column-gap": { "value": "{amsterdam.grid.gap}" }, + "column-gap": { + "value": "{amsterdam.space.md}", + "comment": "Must have the same value as `amsterdam.grid.column-gap`." + }, "column-width": { "value": "20rem" }, "padding-block-start": { "value": "1rem" }, - "padding-block-end": { "value": "{amsterdam.grid.gap}" } + "padding-block-end": { + "value": "{amsterdam.space.md}", + "comment": "Must have the same value as `amsterdam.grid.row-gap.md`." + } } } } diff --git a/storybook/src/components/Grid/Grid.docs.mdx b/storybook/src/components/Grid/Grid.docs.mdx index 59d1933cec..dab60a3c8a 100644 --- a/storybook/src/components/Grid/Grid.docs.mdx +++ b/storybook/src/components/Grid/Grid.docs.mdx @@ -19,7 +19,7 @@ On narrow screens, you will see three rows of four columns; on medium-wide scree ### Vertical Margin Unlike the horizontal margins between columns, the vertical ones above and below are adjustable. -The options `paddingVertical`, `paddingTop`, and `paddingBottom` add white space. +The`paddingVertical`, `paddingTop`, and `paddingBottom` props add white space above and below the grid. This is useful in a coloured area like [Footer](/docs/components-containers-footer--docs) or [Spotlight](/docs/components-containers-spotlight--docs) or between two consecutive grids. Specify a value of `medium` for vertical white space as wide as the horizontal. diff --git a/storybook/src/docs/grid.docs.mdx b/storybook/src/docs/grid.docs.mdx index b577659654..5c0d70f2bc 100644 --- a/storybook/src/docs/grid.docs.mdx +++ b/storybook/src/docs/grid.docs.mdx @@ -39,22 +39,22 @@ There are few options for background colour or borders. Typography and white space remain as tools to keep screens readable. For websites, the grid is quite spacious. -The horizontal white space between columns is 16 pixels wide at a window width of 320 pixels or less. -For every additional 256 pixels of width, the white space grows linearly by 8 pixels. +The gap between columns is 16 pixels wide at a window width of 320 pixels or less. +For every additional 256 pixels of width, it grows linearly by 8 pixels. (This amounts to 3 and 3/8 per cent of the screen width plus 6 pixels.) At a window width of 1600 pixels, it is 56 pixels. -After that, the white space does not grow further. +After that, the gap does not grow further. -In wide windows, the white spaces become almost as wide as the columns. +In wide windows, the gaps become almost as wide as the columns. This may seem unnatural, but it is not a problem. -Elements often occupy multiple columns of the grid, including the intervening white spaces. +Elements often occupy multiple columns of the grid, including the gaps in between. #### Compact -For applications, so much white space is not necessary, even counterproductive. +For applications, so much white space is unnecessary, even counterproductive. Therefore, there is also a compact theme for the grid. -The minimum white space between columns is also 16 pixels here. +The minimum gap between columns is also 16 pixels here. But it only starts growing from a window width of 1088 pixels. The increase is also slower: 4 pixels per 256 pixels of additional width. (This amounts to 1 and 9/16 per cent of the screen width minus 1 pixel.) @@ -66,7 +66,7 @@ On both sides, the grid reserves margins of white space. #### Spacious -The margin is 1½ times as wide as the space between columns. +The margin is 1½ times as wide as the gap between columns. This provides enough space between the grid and the edges of the screen or window. Some elements, such as full-screen images and the page’s footer, can be positioned over these margins. @@ -74,7 +74,7 @@ These are, therefore, slightly wider than the rest of the content. #### Compact -In the compact theme, the margins outside the grid are as wide as the white spaces inside. +In the compact theme, the margins outside the grid are as wide as the gaps inside of it. No elements are placed over these margins. ### Menu bar @@ -106,24 +106,24 @@ In practice, these design choices result in the following dimensions in pixels. ### Widths per breakpoint -The columns, white spaces, and margins have the following widths at the three breakpoints. +The columns, gaps, and margins have the following widths at the three breakpoints. Again, between these widths, the widths grow continuously. #### Spacious -| Breakpoint | From window width | Number of columns | Column width | White space width | Margin width | Grid width | -| :--------- | ----------------: | ----------------: | -----------: | ----------------: | -----------: | ---------: | -| narrow | 320 | 4 | 56 | 16 | 24 | 272 | -| medium | 576 | 8 | 42 | 24 | 36 | 504 | -| wide | 1088 | 12 | 44 | 40 | 60 | 968 | +| Breakpoint | From window width | Number of columns | Column width | Gap width | Margin width | Grid width | +| :--------- | ----------------: | ----------------: | -----------: | --------: | -----------: | ---------: | +| narrow | 320 | 4 | 56 | 16 | 24 | 272 | +| medium | 576 | 8 | 42 | 24 | 36 | 504 | +| wide | 1088 | 12 | 44 | 40 | 60 | 968 | #### Compact -| Breakpoint | From window width | Number of columns | Menu bar width | Column width | White space width | Margin width | Grid width | -| :--------- | ----------------: | ----------------: | -------------: | -----------: | ----------------: | -----------: | ---------: | -| narrow | 320 | 4 | 0 | 60 | 16 | 16 | 288 | -| medium | 576 | 8 | 0 | 54 | 16 | 16 | 544 | -| wide | 1088 | 12 | 112 | 64 | 16 | 16 | 944 | +| Breakpoint | From window width | Number of columns | Menu bar width | Column width | Gap width | Margin width | Grid width | +| :--------- | ----------------: | ----------------: | -------------: | -----------: | --------: | -----------: | ---------: | +| narrow | 320 | 4 | 0 | 60 | 16 | 16 | 288 | +| medium | 576 | 8 | 0 | 54 | 16 | 16 | 544 | +| wide | 1088 | 12 | 112 | 64 | 16 | 16 | 944 | ### Not tied to devices @@ -159,19 +159,19 @@ In these three situations, the dimensions are as follows. #### Spacious -| Device Class | Reference Width | Number of columns | Column width | White space width | Margin width | Grid width | -| :----------- | --------------: | ----------------: | -----------: | ----------------: | -----------: | ---------: | -| phone | 320 | 4 | 56 | 16 | 24 | 272 | -| tablet | 832 | 8 | 64 | 32 | 48 | 736 | -| desktop | 1600 | 12 | 68 | 56 | 84 | 1432 | +| Device Class | Reference Width | Number of columns | Column width | Gap width | Margin width | Grid width | +| :----------- | --------------: | ----------------: | -----------: | --------: | -----------: | ---------: | +| phone | 320 | 4 | 56 | 16 | 24 | 272 | +| tablet | 832 | 8 | 64 | 32 | 48 | 736 | +| desktop | 1600 | 12 | 68 | 56 | 84 | 1432 | #### Compact -| Device Class | Reference Width | Number of columns | Menu bar width | Column width | White space width | Margin width | Grid width | -| :----------- | --------------: | ----------------: | -------------: | -----------: | ----------------: | -----------: | ---------: | -| phone | 320 | 4 | 0 | 60 | 16 | 16 | 288 | -| tablet | 832 | 8 | 0 | 86 | 16 | 16 | 800 | -| desktop | 1600 | 12 | 112 | 98 | 24 | 24 | 1440 | +| Device Class | Reference Width | Number of columns | Menu bar width | Column width | Gap width | Margin width | Grid width | +| :----------- | --------------: | ----------------: | -------------: | -----------: | --------: | -----------: | ---------: | +| phone | 320 | 4 | 0 | 60 | 16 | 16 | 288 | +| tablet | 832 | 8 | 0 | 86 | 16 | 16 | 800 | +| desktop | 1600 | 12 | 112 | 98 | 24 | 24 | 1440 | ### Windows or screens