From c2a62f9ce71c9570e9de21d266ccfe81f0ae3e18 Mon Sep 17 00:00:00 2001 From: Taylor Jones Date: Fri, 11 Feb 2022 12:31:11 -0600 Subject: [PATCH] fix(flexgrid): include flexgrid styles in `@carbon/styles` and `@carbon/react` (#10666) * fix(flexgrid): include flexgrid styles in and * fix(flexgrid): correct mixin name, update tests and snaps * fix(flexgrid): call mixin, update docs, remove carbon prefix * fix(flexgrid): 12 column configuration option * fix(flexgrid): update snaps Co-authored-by: Josefina Mancilla <32556167+jnm2377@users.noreply.github.com> --- docs/migration/v11.md | 4 +- packages/carbon-react/tasks/build-styles.js | 10 + .../__tests__/__snapshots__/scss-test.js.snap | 2 +- packages/grid/index.scss | 2 + packages/grid/scss/modules/_config.scss | 6 + packages/grid/scss/modules/_css-grid.scss | 68 ---- packages/grid/scss/modules/_flex-grid.scss | 374 ++++++++++++++++++ .../src/components/Grid/next/FlexGrid.mdx | 252 ++++++++++++ .../components/Grid/next/FlexGrid.stories.js | 291 ++++++++++++++ .../Grid/next/FlexGrid.stories.scss | 87 ++++ .../__snapshots__/config-test.js.snap | 1 + packages/styles/scss/__tests__/grid-test.js | 2 + packages/styles/scss/_config.scss | 6 + packages/styles/scss/_grid.scss | 4 +- packages/styles/scss/components/_index.scss | 1 + .../aspect-ratio/_aspect-ratio.scss | 72 ++++ .../scss/components/aspect-ratio/_index.scss | 11 + 17 files changed, 1121 insertions(+), 72 deletions(-) create mode 100644 packages/grid/scss/modules/_flex-grid.scss create mode 100644 packages/react/src/components/Grid/next/FlexGrid.mdx create mode 100644 packages/react/src/components/Grid/next/FlexGrid.stories.js create mode 100644 packages/react/src/components/Grid/next/FlexGrid.stories.scss create mode 100644 packages/styles/scss/components/aspect-ratio/_aspect-ratio.scss create mode 100644 packages/styles/scss/components/aspect-ratio/_index.scss diff --git a/docs/migration/v11.md b/docs/migration/v11.md index 424be15e4c66..945f54ca142b 100644 --- a/docs/migration/v11.md +++ b/docs/migration/v11.md @@ -1270,8 +1270,8 @@ For full Sass API documentation, visit the | `scss/grid.scss` | | Moved to `index.scss` | | `scss/index.scss` | | Moved to `index.scss` | | `scss/_css-grid.scss` | | New | -| `scss/_flexbox.scss` | | New | -| `scss/_mixins.scss` | | Moved to `scss/_flexbox.scss` | +| `scss/flex-grid.scss` | | New | +| `scss/_mixins.scss` | | Moved to `scss/flex-grid.scss` | | `scss/_prefix.scss` | | Moved to `scss/_config.scss` | | `scss/12.scss` | | This file has been removed, to configure the grid use `scss/_config.scss` | diff --git a/packages/carbon-react/tasks/build-styles.js b/packages/carbon-react/tasks/build-styles.js index 61ac23df7f4b..c5ffb9f1fc67 100644 --- a/packages/carbon-react/tasks/build-styles.js +++ b/packages/carbon-react/tasks/build-styles.js @@ -95,6 +95,16 @@ async function build() { }, ], }, + { + type: 'directory', + filepath: 'aspect-ratio', + files: [ + { + type: 'file', + filepath: '_index.scss', + }, + ], + }, { type: 'directory', filepath: 'breadcrumb', diff --git a/packages/grid/__tests__/__snapshots__/scss-test.js.snap b/packages/grid/__tests__/__snapshots__/scss-test.js.snap index cf593f131ca2..438ba91b0e7e 100644 --- a/packages/grid/__tests__/__snapshots__/scss-test.js.snap +++ b/packages/grid/__tests__/__snapshots__/scss-test.js.snap @@ -3,9 +3,9 @@ exports[`@carbon/grid Public API 1`] = ` Array [ "prefix", + "flex-grid-columns", "grid-gutter", "grid-gutter--condensed", "grid-breakpoints", - "carbon--aspect-ratios", ] `; diff --git a/packages/grid/index.scss b/packages/grid/index.scss index 693d3fc8ee1d..8b6f9c3cb551 100644 --- a/packages/grid/index.scss +++ b/packages/grid/index.scss @@ -7,6 +7,8 @@ @forward 'scss/modules/config' with ( $prefix: 'bx' !default, + $flex-grid-columns: 16 !default, ); @forward 'scss/modules/breakpoint'; @forward 'scss/modules/css-grid'; +@forward 'scss/modules/flex-grid'; diff --git a/packages/grid/scss/modules/_config.scss b/packages/grid/scss/modules/_config.scss index 7598b1e4c065..f7f9f748cb01 100644 --- a/packages/grid/scss/modules/_config.scss +++ b/packages/grid/scss/modules/_config.scss @@ -10,3 +10,9 @@ /// @access public /// @group @carbon/grid $prefix: 'bx' !default; + +/// Total columns used in the flex grid +/// @type Number +/// @access public +/// @group @carbon/grid +$flex-grid-columns: 16 !default; diff --git a/packages/grid/scss/modules/_css-grid.scss b/packages/grid/scss/modules/_css-grid.scss index 19f1261ba553..3dd082e763bb 100644 --- a/packages/grid/scss/modules/_css-grid.scss +++ b/packages/grid/scss/modules/_css-grid.scss @@ -356,71 +356,3 @@ .#{$prefix}--align-items-center { align-items: center; } - -// ----------------------------------------------------------------------------- -// Aspect ratio -- TODO: in v11 should this move to a new file to live alongside the AspectRatio component? -// ----------------------------------------------------------------------------- - -/// The aspect ratios that are used to generate corresponding aspect ratio -/// classes in code -/// @type List -/// @access public -/// @group @carbon/grid -$carbon--aspect-ratios: ( - (16, 9), - (9, 16), - (2, 1), - (1, 2), - (4, 3), - (3, 4), - (3, 2), - (2, 3), - (1, 1) -); - -/// Generates the CSS classname utilities for the aspect ratios -/// -/// CSS Tricks article on aspect ratios and all the different ways it can be done. -/// https://css-tricks.com/aspect-ratio-boxes/#article-header-id-6 -/// -/// That article references an earlier article on the topic. -/// https://keithjgrant.com/posts/2017/03/aspect-ratios/ -/// -/// @param {Number} $width width from an aspect ratio -/// @param {Number} $height height from an aspect ratio -/// @access private -/// @group @carbon/grid -@mixin carbon--aspect-ratio($aspect-ratios: $carbon--aspect-ratios) { - .#{$prefix}--aspect-ratio { - position: relative; - } - - .#{$prefix}--aspect-ratio::before { - width: 1px; - height: 0; - margin-left: -1px; - content: ''; - float: left; - } - - .#{$prefix}--aspect-ratio::after { - display: table; - clear: both; - content: ''; - } - - @each $aspect-ratio in $aspect-ratios { - $width: nth($aspect-ratio, 1); - $height: nth($aspect-ratio, 2); - - .#{$prefix}--aspect-ratio--#{$width}x#{$height}::before { - @if meta.function-exists('div', 'math') { - padding-top: percentage(math.div($height, $width)); - } @else { - padding-top: percentage(($height / $width)); - } - } - } -} - -@include carbon--aspect-ratio(); diff --git a/packages/grid/scss/modules/_flex-grid.scss b/packages/grid/scss/modules/_flex-grid.scss new file mode 100644 index 000000000000..a043110e97b3 --- /dev/null +++ b/packages/grid/scss/modules/_flex-grid.scss @@ -0,0 +1,374 @@ +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +// Helpers for defining columns, rows, and containers are heavily inspired by, +// and often derived from, bootstrap: +// https://github.com/twbs/bootstrap/blob/v4-dev/scss/mixins/_grid.scss + +@use 'sass:meta'; +@use 'sass:math'; +@use 'sass:map'; + +@use 'config' as *; +@use 'breakpoint' as *; + +// ----------------------------------------------------------------------------- +// Columns +// ----------------------------------------------------------------------------- + +/// Used to initialize the default properties for a column class, most notably +/// for setting width and default gutters when a column's breakpoint has not been +/// hit yet. +/// @param {Number} $gutter [$grid-gutter] - The gutter for the grid system +/// @param {Number} $collapsed-gutter [$grid-gutter--condensed] - The condensed mode gutter +/// @access private +/// @group @carbon/grid +@mixin -make-col-ready( + $gutter: $grid-gutter, + $condensed-gutter: $grid-gutter--condensed +) { + // Prevent columns from becoming too narrow when at smaller grid tiers by + // always setting `width: 100%;`. This works because we use `flex` values + // later on to override this initial width. + width: 100%; + padding-right: $gutter * 0.5; + padding-left: $gutter * 0.5; + + // For our condensed use-case, our gutters collapse to 2px solid, 1px on each + // side. + .#{$prefix}--row--condensed &, + .#{$prefix}--grid--condensed & { + padding-right: $condensed-gutter * 0.5; + padding-left: $condensed-gutter * 0.5; + } + + // For our narrow use-case, our container hangs 16px into the gutter + .#{$prefix}--row--narrow &, + .#{$prefix}--grid--narrow & { + padding-right: $gutter * 0.5; + padding-left: 0; + } +} + +/// Define the width of the column for a given span and column count. +/// A width of 0 will hide the column entirely. +/// @param {Number} $span - The number of columns covered +/// @param {Number} $columns - The total number of columns available +/// @access private +/// @group @carbon/grid +@mixin -make-col($span, $columns) { + @if $span == 0 { + display: none; + } @else { + // Explicitly include `display: block` to override + display: block; + // Add a `max-width` to ensure content within each column does not blow out + // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari + // do not appear to require this. + @if meta.function-exists('div', 'math') { + max-width: percentage(math.div($span, $columns)); + flex: 0 0 percentage(math.div($span, $columns)); + } @else { + max-width: percentage(($span / $columns)); + flex: 0 0 percentage(($span / $columns)); + } + } +} + +/// Create a column offset for a given span and column count. +/// @param {Number} $span - The number of columns the offset should cover +/// @param {Number} $columns - The total number of columns available +/// @access private +/// @group @carbon/grid +@mixin -make-col-offset($span, $columns) { + $offset: 0; + @if meta.function-exists('div', 'math') { + $offset: math.div($span, $columns); + } @else { + $offset: ($span / $columns); + } + @if $offset == 0 { + margin-left: 0; + } @else { + margin-left: percentage($offset); + } +} + +/// Output the CSS required for all the columns in a given grid system. +/// @param {Map} $breakpoints [$grid-breakpoints] - The breakpoints in the grid system +/// @param {Number} $gutter [$grid-gutter] - The gutter for the grid system +/// @access private +/// @group @carbon/grid +@mixin -make-grid-columns( + $breakpoints: $grid-breakpoints, + $gutter: $grid-gutter +) { + .#{$prefix}--col { + @include -make-col-ready($gutter); + } + + @each $breakpoint in map-keys($breakpoints) { + $infix: breakpoint-infix($breakpoint); + $columns: map-get(map-get($breakpoints, $breakpoint), columns); + + // Allow columns to stretch full width below their breakpoints + @for $i from 0 through $columns { + .#{$prefix}--col#{$infix}-#{$i} { + @include -make-col-ready($gutter); + } + } + + .#{$prefix}--col#{$infix}, + .#{$prefix}--col#{$infix}--auto { + @include -make-col-ready($gutter); + } + + @include breakpoint($breakpoint, $breakpoints) { + // Provide basic `.col-{bp}` classes for equal-width flexbox columns + .#{$prefix}--col, + .#{$prefix}--col#{$infix} { + max-width: 100%; + flex-basis: 0; + flex-grow: 1; + } + + .#{$prefix}--col--auto, + .#{$prefix}--col#{$infix}--auto { + width: auto; + // Reset earlier grid tiers + max-width: 100%; + flex: 1 0 0%; + } + + @for $i from 0 through $columns { + .#{$prefix}--col#{$infix}-#{$i} { + @include -make-col($i, $columns); + } + } + + @for $i from 0 through ($columns - 1) { + @if not($infix == '') { + .#{$prefix}--offset#{$infix}-#{$i} { + @include -make-col-offset($i, $columns); + } + } + } + } + } +} + +// ----------------------------------------------------------------------------- +// Rows +// ----------------------------------------------------------------------------- + +/// Define the properties for a selector assigned to a row in the grid system. +/// @param {Number} $gutter [$grid-gutter] - The gutter in the grid system +/// @access private +/// @group @carbon/grid +@mixin -make-row($gutter: $grid-gutter) { + display: flex; + flex-wrap: wrap; + margin-right: -1 * $gutter * 0.5; + margin-left: -1 * $gutter * 0.5; +} + +// ----------------------------------------------------------------------------- +// No gutter +// ----------------------------------------------------------------------------- + +/// Add `no-gutter` and `no-gutter--{start,end}` classes to the output CSS. These +/// classes are useful for dropping the gutter in fluid situations. +/// @access private +/// @group @carbon/grid +@mixin -no-gutter { + .#{$prefix}--no-gutter, + .#{$prefix}--row.#{$prefix}--no-gutter [class*='#{$prefix}--col'] { + padding-right: 0; + padding-left: 0; + } + + .#{$prefix}--no-gutter--start, + .#{$prefix}--row.#{$prefix}--no-gutter--start [class*='#{$prefix}--col'] { + padding-left: 0; + } + + .#{$prefix}--no-gutter--end, + .#{$prefix}--row.#{$prefix}--no-gutter--end [class*='#{$prefix}--col'] { + padding-right: 0; + } + + // Deprecated ☠️ + .#{$prefix}--no-gutter--left, + .#{$prefix}--row.#{$prefix}--no-gutter--left [class*='#{$prefix}--col'] { + padding-left: 0; + } + + .#{$prefix}--no-gutter--right, + .#{$prefix}--row.#{$prefix}--no-gutter--right [class*='#{$prefix}--col'] { + padding-right: 0; + } +} + +// ----------------------------------------------------------------------------- +// Hang +// ----------------------------------------------------------------------------- + +/// Add `hang--start` and `hang--end` classes for a given gutter. These classes are +/// used alongside `no-gutter--start` and `no-gutter--end` to "hang" type. +/// @param {Number} $gutter [$grid-gutter] - The gutter in the grid system +/// @access private +/// @group @carbon/grid +@mixin -hang($gutter: $grid-gutter) { + .#{$prefix}--hang--start { + padding-left: $gutter * 0.5; + } + + .#{$prefix}--hang--end { + padding-right: $gutter * 0.5; + } + + // Deprecated ☠️ + .#{$prefix}--hang--left { + padding-left: $gutter * 0.5; + } + + .#{$prefix}--hang--right { + padding-right: $gutter * 0.5; + } +} + +// ----------------------------------------------------------------------------- +// Grid +// ----------------------------------------------------------------------------- + +/// Create the container for a grid. Will cause full-bleed for the grid unless +/// max-width properties are added with `make-container-max-widths` +/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name +/// @access private +/// @group @carbon/grid +@mixin -make-container($breakpoints: $grid-breakpoints) { + margin-right: auto; + margin-left: auto; + + @include -set-largest-breakpoint(); + + @each $name, $value in $breakpoints { + $prev-breakpoint: map-get($breakpoints, breakpoint-prev($name)); + $margin: map-get($value, margin); + + @if $prev-breakpoint { + $prev-margin: map-get($prev-breakpoint, margin); + @if $prev-margin != $margin { + @include breakpoint($name) { + padding-right: #{($grid-gutter * 0.5) + $margin}; + padding-left: #{($grid-gutter * 0.5) + $margin}; + } + } + } @else { + @include breakpoint($name) { + padding-right: #{($grid-gutter * 0.5) + $margin}; + padding-left: #{($grid-gutter * 0.5) + $margin}; + } + } + } +} + +/// Get the last breakpoint width and set max-width to its value +/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name +/// @access private +/// @group @carbon/grid +@mixin -set-largest-breakpoint($breakpoints: $grid-breakpoints) { + $largest-breakpoint: last-map-item($breakpoints); + + max-width: map-get($largest-breakpoint, 'width'); +} + +/// Add in the max-widths for each breakpoint to the container +/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name +/// @access private +/// @group @carbon/grid +@mixin -make-container-max-widths($breakpoints: $grid-breakpoints) { + @each $name, $value in $breakpoints { + @include breakpoint($name) { + max-width: map-get($value, width); + } + } +} + +/// Generate the CSS for a grid for the given breakpoints and gutters +/// @param {Map} $breakpoints [$grid-breakpoints] - The default breakpoints +/// @param {Number} $grid-gutter [$grid-gutter] - The default gutters +/// @param {Number} $condensed-gutter [$grid-gutter--condensed] - The condensed mode gutter +/// @access public +/// @group @carbon/grid +@mixin flex-grid( + $breakpoints: $grid-breakpoints, + $grid-gutter: $grid-gutter, + $condensed-gutter: $grid-gutter--condensed +) { + .#{$prefix}--grid { + @include -make-container($breakpoints); + } + + @include largest-breakpoint($breakpoints) { + .#{$prefix}--grid--full-width { + max-width: 100%; + } + } + + .#{$prefix}--row { + @include -make-row(); + } + + .#{$prefix}--row-padding [class*='#{$prefix}--col'], + .#{$prefix}--col-padding { + padding-top: $grid-gutter * 0.5; + padding-bottom: $grid-gutter * 0.5; + } + + .#{$prefix}--grid--condensed [class*='#{$prefix}--col'] { + padding-top: $condensed-gutter * 0.5; + padding-bottom: $condensed-gutter * 0.5; + } + + @include -make-grid-columns($breakpoints, $grid-gutter); + @include -no-gutter(); + @include -hang($grid-gutter); +} + +@if $flex-grid-columns == 12 { + $flex-12-column-grid: map-merge( + $grid-breakpoints, + ( + lg: + map-merge( + map-get($grid-breakpoints, lg), + ( + columns: 12, + ) + ), + xlg: + map-merge( + map-get($grid-breakpoints, xlg), + ( + columns: 12, + ) + ), + max: + map-merge( + map-get($grid-breakpoints, max), + ( + columns: 12, + ) + ), + ) + ); + + @include flex-grid($breakpoints: $flex-12-column-grid); +} @else { + @include flex-grid(); +} diff --git a/packages/react/src/components/Grid/next/FlexGrid.mdx b/packages/react/src/components/Grid/next/FlexGrid.mdx new file mode 100644 index 000000000000..232c26e0a3ee --- /dev/null +++ b/packages/react/src/components/Grid/next/FlexGrid.mdx @@ -0,0 +1,252 @@ +import { Story, Preview, Props } from '@storybook/addon-docs/blocks'; + +# Grid + +[Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/Grid) + |  +[Usage guidelines](https://www.carbondesignsystem.com/guidelines/2x-grid/overview) + + + + +## Table of Contents + +- [Overview](#overview) +- [Grid modes](#grid-modes) + - [Wide grid](#wide-grid) + - [Narrow grid](#narrow-grid) + - [Condensed grid](#condensed-grid) + - [Mix-and-match](#mix-and-match) +- [Auto columns](#auto-columns) +- [Offset columns](#offset-columns) +- [Component API](#component-api) + - [Using the `as` prop](#using-the-as-prop) +- [FAQ](#faq) + - [How can I hide columns at a certain breakpoint?](#how-can-i-hide-columns-at-a-certain-breakpoint) + - [Can I nest grid components?](#can-i-nest-grid-components) +- [Feedback](#feedback) + + + + +Carbon's grid components help developers use the +[2x Grid](https://www.carbondesignsystem.com/guidelines/2x-grid/overview). The +project provides `FlexGrid`, `Row`, and `Column` components which can be used to +build a variety of layouts. You can import these components from +`@carbon/react`: + +```js +import { FlexGrid, Row, Column } from '@carbon/react'; +``` + + + + + +## Overview + +Every layout starts with the `FlexGrid` component. You can specify a `FlexGrid` +at the top-level of your project, or at different depths provided that it can +span 100% width of its container. + +Next, you will use a combination of `Row` and `Column`. You can have multiple +`Row` components in a `FlexGrid`, and multiple `Column` components in a `Row`. +Each `Row` will contain all the `Column` components provided to it, as long as +they don't span more columns than the total number of columns in the grid. + +To specify how many columns the `Column` component should span, you can use the +`sm`, `md`, `lg`, `xlg`, or `max` props. These props are shorthand versions of +the names given to each of the breakpoints defined by the +[2x Grid](https://www.carbondesignsystem.com/guidelines/2x-grid/implementation/#responsive-options). +In the example below, we will use the `lg` prop for the large breakpoint and the +number `4` to specify that each `Column` component should span 4 columns at that +breakpoint. + +```js +import { FlexGrid, Row, Column } from '@carbon/react'; + +function MyComponent() { + return ( + + + Span 4 of 12 + Span 4 of 12 + Span 4 of 12 + Span 4 of 12 + + + ); +} +``` + +You can pair up multiple breakpoint props to specify how many columns the +`Column` component should span at different break points. In the example below, +we will use the `sm`, `md`, and `lg` prop to specify how many columns the +`Column` components should span at the small, medium, and large breakpoints. + + + + + +## Grid modes + +There are several +[grid modes](https://www.carbondesignsystem.com/guidelines/2x-grid/implementation/#grid-modes) +that you can use depending on the layout effect you're looking to achieve. By +default, `FlexGrid` uses the wide grid mode with a 32px gutter. However, you can +use the `narrow` or `condensed` props to enable the narrow and condensed grid +modes, respectively. + +The same way that you can pass in `narrow` or `condensed` to the `FlexGrid` +component, you can also pass in `narrow` or `condensed` to a `Row` component to +enable a certain grid mode but only for a row. This can be useful when you need +to mix-and-match certain grid modes to achieve a particular layout. + +### Wide grid + + + + + +### Narrow grid + + + + + +### Condensed grid + + + + + +### Mix-and-match + + + + + +## Auto columns + +In some situations, you may want your content to span a specific proportion of +the grid without having to calculate it across every breakpoint. A common +use-case for this is if you have a row of four cards and want each to span 25% +width each. + +In these situations, you can make use of the auto columns feature of the +`Column` component. Auto columns is enabled when you do not provide any +breakpoint props, and it will automatically set each column to a percentage of +the total available width. + +For example, if you have on `Column` component it would span 100%, two `Column` +components would span 50% each, four `Column` components would span 25% each, +and so on. + + + + + +## Offset columns + +You can offset your `Column` components by a specific amount of columns using +the object form for each breakpoint prop. This specific prop type allows you to +pass in an object to each breakpoint prop and this object has two keys, `span` +and `offset`, which allow you to specify the total numbers of columns the +`Column` component spans, and how many columns to offset it by. + +You can specify either prop in this object form, and can mix-and-match across +breakpoints. For example, the following snippet will have the `Column` component +span two columns at the small breakpoint and then four columns at the medium +breakpoint. At the medium breakpoint, it will be offset by two columns. + +```jsx + +``` + + + + + +## Component API + + + +### Using the `as` prop + +By default, `FlexGrid`, `Row`, and `Column` will render as a `div`. However, you +can use the `as` prop to change this to another HTML element, or a custom +component from your project. + +In the example below, we use the `as` prop on `Row` to change it from a `div` to +a `section`. Similarly, we use the `as` prop on `Column` to change it from a +`div` to an `article`. + +```jsx +import { FlexGrid, Row, Column } from '@carbon/react'; + +function MyComponent() { + return ( + + + Example content + Example content + Example content + Example content + + + ); +} +``` + +You can also provide a custom component to the `as` prop. This custom component +should accept all props passed to it, like a class name for the column. + +```jsx +import { FlexGrid, Row, Column } from '@carbon/react'; + +function Article({ children, ...rest }) { + return
{children}
; +} + +function CustomColumn({ children, ...rest }) { + return {children} + + Example content + Example content
+ Example content + Example content + + + ); +} +``` + +## FAQ + +### How can I hide columns at a certain breakpoint? + +To hide a column at a specific breakpoint, you should specify 0 for the span of +the column at that particular breakpoint. For example, you can use the following +two forms for specifying column span and pass in 0 to either to hide the column +at the small breakpoint. + +```jsx + + +``` + +### Can I nest FlexGrid components? + +`FlexGrid` does not support nested grids. For nested grids, use the `Grid` +(`CSSGrid`) component. + +## Feedback + +Help us improve this component by providing feedback, asking questions on Slack, +or updating this file on +[GitHub](https://github.com/carbon-design-system/carbon/edit/main/packages/react/src/components/Grid/Grid.mdx). diff --git a/packages/react/src/components/Grid/next/FlexGrid.stories.js b/packages/react/src/components/Grid/next/FlexGrid.stories.js new file mode 100644 index 000000000000..3050fedb41e6 --- /dev/null +++ b/packages/react/src/components/Grid/next/FlexGrid.stories.js @@ -0,0 +1,291 @@ +import './FlexGrid.stories.scss'; +import React from 'react'; +import { FlexGrid, Row, Column } from '../'; +import mdx from './FlexGrid.mdx'; + +export default { + title: 'Components/FlexGrid', + component: FlexGrid, + subcomponents: { + Row, + Column, + }, + decorators: [(storyFn) =>
{storyFn()}
], + parameters: { + docs: { + page: mdx, + }, + }, +}; + +function DemoContent({ children }) { + return ( +
+
{children}
+
+ ); +} + +export const AutoColumns = () => ( + + + + Span 25% + + + Span 25% + + + Span 25% + + + Span 25% + + + +); + +export const ResponsiveGrid = () => ( + + + + +

Small: Span 2 of 4

+

Medium: Span 4 of 8

+

Large: Span 6 of 16

+
+
+ + +

Small: Span 2 of 4

+

Medium: Span 2 of 8

+

Large: Span 3 of 16

+
+
+ + +

Small: Span 0 of 4

+

Medium: Span 2 of 8

+

Large: Span 3 of 16

+
+
+
+
+); + +export const Offset = () => ( + + + + Small: offset 3 + + + Small: offset 2 + + + Small: offset 1 + + + Small: offset 0 + + + +); + +export const Condensed = () => ( + + + + 1/4 + + + 1/4 + + + 1/4 + + + 1/4 + + + +); + +export const CondensedColumns = () => ( + + + + 1/4 + + + 1/4 + + + 1/4 + + + 1/4 + + + + + 1/4 + + + 1/4 + + + 1/4 + + + 1/4 + + + + + 1/4 + + + 1/4 + + + 1/4 + + + 1/4 + + + +); + +export const Narrow = () => ( + + + + 1/4 + + + 1/4 + + + 1/4 + + + 1/4 + + + +); + +export const NarrowColumns = () => ( + + + + 1/4 + + + 1/4 + + + 1/4 + + + 1/4 + + + + + 1/4 + + + 1/4 + + + 1/4 + + + 1/4 + + + + + 1/4 + + + 1/4 + + + 1/4 + + + 1/4 + + + +); + +export const FullWidth = () => ( + + + + 1/4 + + + 1/4 + + + 1/4 + + + 1/4 + + + +); + +export const MixedGridModes = () => ( + + + + Wide + + + 1/4 + + + 1/4 + + + 1/4 + + + + + Narrow + + + 1/4 + + + 1/4 + + + 1/4 + + + + + Condensed + + + 1/4 + + + 1/4 + + + 1/4 + + + +); diff --git a/packages/react/src/components/Grid/next/FlexGrid.stories.scss b/packages/react/src/components/Grid/next/FlexGrid.stories.scss new file mode 100644 index 000000000000..8ff6d92d1335 --- /dev/null +++ b/packages/react/src/components/Grid/next/FlexGrid.stories.scss @@ -0,0 +1,87 @@ +@use '@carbon/styles/scss/colors' as *; + +// base of project work area +#root > div:first-child > div:first-child { + width: 100%; +} + +// grid styles +.cds--grid .outside { + min-height: 80px; + height: 100%; +} + +.cds--grid .inside { + min-height: 80px; + height: 100%; +} + +// hack to enable zoom feature to trigger +.cds--grid--full-width { + max-width: 100%; +} + +.default .cds--col code { + display: flex; + justify-content: center; +} + +// template hard-coded styles +#templates .inside { + background-color: $blue-10; +} + +#templates .cds--grid [class*='col'] { + background-color: $blue-20; + outline: 1px dashed $blue-40; +} + +#templates .cds--grid--condensed, +#templates .cds--row--condensed { + background-color: $warm-gray-100; + color: $gray-10; +} + +#templates .cds--grid--condensed [class*='col'], +#templates .cds--row--condensed [class*='col'] { + background: none; + outline: none; +} + +#templates .cds--grid--condensed .outside, +#templates .cds--row--condensed .outside { + background-color: $gray-80; + outline: none; +} + +#templates .cds--grid--condensed .inside, +#templates .cds--row--condensed .inside { + background: none; +} + +#templates .cds--grid--narrow .inside, +#templates .cds--row--narrow .inside { + background-color: $teal-10; +} + +#templates .cds--grid--narrow [class*='col'], +#templates .cds--row--narrow [class*='col'] { + background-color: $teal-20; + outline: 1px dashed $teal-40; +} + +// css grid +#templates > .cds--css-grid { + border: 1px dashed black; +} + +#templates .cds--css-grid .cds--subgrid [class*='col'] { + background-color: rgba(#ffe056, 0.25); + outline: 1px solid #ffe056; +} + +#templates .cds--css-grid [class*='col'] { + background-color: #edf4ff; + outline: 1px solid #a6c8ff; + min-height: 80px; +} diff --git a/packages/styles/scss/__tests__/__snapshots__/config-test.js.snap b/packages/styles/scss/__tests__/__snapshots__/config-test.js.snap index ab8542133525..303394cf3537 100644 --- a/packages/styles/scss/__tests__/__snapshots__/config-test.js.snap +++ b/packages/styles/scss/__tests__/__snapshots__/config-test.js.snap @@ -5,6 +5,7 @@ Object { "css--default-type": true, "css--font-face": true, "css--reset": true, + "flex-grid-columns": 16, "font-display": "swap", "font-path": "~@ibm/plex", "prefix": "cds", diff --git a/packages/styles/scss/__tests__/grid-test.js b/packages/styles/scss/__tests__/grid-test.js index 922b0c51b2ef..ce40d768483e 100644 --- a/packages/styles/scss/__tests__/grid-test.js +++ b/packages/styles/scss/__tests__/grid-test.js @@ -27,6 +27,7 @@ describe('@carbon/styles/scss/grid', () => { mixins: ( css-grid: meta.mixin-exists('css-grid'), subgrid: meta.mixin-exists('subgrid'), + flex-grid: meta.mixin-exists('flex-grid'), ), )); `); @@ -40,6 +41,7 @@ describe('@carbon/styles/scss/grid', () => { mixins: { 'css-grid': true, subgrid: true, + 'flex-grid': true, }, }); }); diff --git a/packages/styles/scss/_config.scss b/packages/styles/scss/_config.scss index b58928049541..6f999508f5ea 100644 --- a/packages/styles/scss/_config.scss +++ b/packages/styles/scss/_config.scss @@ -48,3 +48,9 @@ $use-google-fonts: false !default; /// @type String /// @group config $prefix: 'cds' !default; + +/// Total columns used in the flex grid +/// @type Number +/// @access public +/// @group @carbon/grid +$flex-grid-columns: 16 !default; diff --git a/packages/styles/scss/_grid.scss b/packages/styles/scss/_grid.scss index 20af0bccdeec..7149ecf3ee12 100644 --- a/packages/styles/scss/_grid.scss +++ b/packages/styles/scss/_grid.scss @@ -10,11 +10,13 @@ @forward '@carbon/grid' show css-grid, subgrid, + flex-grid, $grid-gutter, $grid-gutter-condensed, $grid-breakpoints with ( - $prefix: config.$prefix + $prefix: config.$prefix, + $flex-grid-columns: config.$flex-grid-columns, ); @use '@carbon/grid'; diff --git a/packages/styles/scss/components/_index.scss b/packages/styles/scss/components/_index.scss index cca88e0e5936..532d1dc0a40b 100644 --- a/packages/styles/scss/components/_index.scss +++ b/packages/styles/scss/components/_index.scss @@ -6,6 +6,7 @@ // @use 'accordion'; +@use 'aspect-ratio'; @use 'breadcrumb'; @use 'button'; @use 'checkbox'; diff --git a/packages/styles/scss/components/aspect-ratio/_aspect-ratio.scss b/packages/styles/scss/components/aspect-ratio/_aspect-ratio.scss new file mode 100644 index 000000000000..412322af5add --- /dev/null +++ b/packages/styles/scss/components/aspect-ratio/_aspect-ratio.scss @@ -0,0 +1,72 @@ +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@use 'sass:math'; +@use 'sass:meta'; +@use '../../config' as *; + +/// The aspect ratios that are used to generate corresponding aspect ratio +/// classes in code +/// @type List +/// @access public +/// @group @carbon/grid +$carbon--aspect-ratios: ( + (16, 9), + (9, 16), + (2, 1), + (1, 2), + (4, 3), + (3, 4), + (3, 2), + (2, 3), + (1, 1) +); + +/// Generates the CSS classname utilities for the aspect ratios +/// +/// CSS Tricks article on aspect ratios and all the different ways it can be done. +/// https://css-tricks.com/aspect-ratio-boxes/#article-header-id-6 +/// +/// That article references an earlier article on the topic. +/// https://keithjgrant.com/posts/2017/03/aspect-ratios/ +/// +/// @param {Number} $width width from an aspect ratio +/// @param {Number} $height height from an aspect ratio +/// @access private +/// @group @carbon/grid +@mixin aspect-ratio($aspect-ratios: $carbon--aspect-ratios) { + .#{$prefix}--aspect-ratio { + position: relative; + } + + .#{$prefix}--aspect-ratio::before { + width: 1px; + height: 0; + margin-left: -1px; + content: ''; + float: left; + } + + .#{$prefix}--aspect-ratio::after { + display: table; + clear: both; + content: ''; + } + + @each $aspect-ratio in $aspect-ratios { + $width: nth($aspect-ratio, 1); + $height: nth($aspect-ratio, 2); + + .#{$prefix}--aspect-ratio--#{$width}x#{$height}::before { + @if meta.function-exists('div', 'math') { + padding-top: percentage(math.div($height, $width)); + } @else { + padding-top: percentage(($height / $width)); + } + } + } +} diff --git a/packages/styles/scss/components/aspect-ratio/_index.scss b/packages/styles/scss/components/aspect-ratio/_index.scss new file mode 100644 index 000000000000..9c6160ee0034 --- /dev/null +++ b/packages/styles/scss/components/aspect-ratio/_index.scss @@ -0,0 +1,11 @@ +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward 'aspect-ratio'; +@use 'aspect-ratio'; + +@include aspect-ratio.aspect-ratio;