diff --git a/.eslintrc b/.eslintrc index a4fc0a5f1..5f4b16604 100644 --- a/.eslintrc +++ b/.eslintrc @@ -25,7 +25,8 @@ "rules": { "react/jsx-filename-extension": [1, { "extensions": [".mdx"] }], "react/jsx-indent": "off", // Gives false positives in MDX files. - "semi": "off" // We don't want to clutter our MDX with semicolons. + "semi": "off", // We don't want to clutter our MDX with semicolons. + "sort-keys": "off" // This rule only needs to be turned off in a few places (eg. breakpoint lists), but weirdly enough, an inline comment alerts breaking of the `indent` rule. } } ] diff --git a/package-lock.json b/package-lock.json index 4e3228dd2..6d37e3aa0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8170,11 +8170,6 @@ "postcss-value-parser": "^4.1.0" }, "dependencies": { - "caniuse-lite": { - "version": "1.0.30001112", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001112.tgz", - "integrity": "sha512-J05RTQlqsatidif/38aN3PGULCLrg8OYQOlJUKbeYVzC2mGZkZLIztwRlB3MtrfLmawUmjFlNJvy/uhwniIe1Q==" - }, "postcss": { "version": "7.0.32", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", @@ -9734,9 +9729,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001058", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001058.tgz", - "integrity": "sha512-UiRZmBYd1HdVVdFKy7PuLVx9e2NS7SMyx7QpWvFjiklYrLJKpLd19cRnRNqlw4zYa7vVejS3c8JUVobX241zHQ==" + "version": "1.0.30001154", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001154.tgz", + "integrity": "sha512-y9DvdSti8NnYB9Be92ddMZQrcOe04kcQtcxtBx4NkB04+qZ+JUWotnXBJTmxlKudhxNTQ3RRknMwNU2YQl/Org==" }, "capitalize": { "version": "2.0.3", @@ -17097,11 +17092,6 @@ } } }, - "caniuse-lite": { - "version": "1.0.30001135", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001135.tgz", - "integrity": "sha512-ziNcheTGTHlu9g34EVoHQdIu5g4foc8EsxMGC7Xkokmvw0dqNtX8BS8RgCgFBaAiSp2IdjvBxNdh0ssib28eVQ==" - }, "chokidar": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", diff --git a/src/gatsby-theme-docz/wrapper.js b/src/gatsby-theme-docz/wrapper.js index 935a5cb5e..158c95b19 100644 --- a/src/gatsby-theme-docz/wrapper.js +++ b/src/gatsby-theme-docz/wrapper.js @@ -23,6 +23,15 @@ const Wrapper = ({ children }) => ( gtag('config', 'UA-173070814-1'); `} + {children} diff --git a/src/lib/components/layout/CTA/README.mdx b/src/lib/components/layout/CTA/README.mdx index 5ee07d174..66080351a 100644 --- a/src/lib/components/layout/CTA/README.mdx +++ b/src/lib/components/layout/CTA/README.mdx @@ -100,19 +100,19 @@ and bottom. -## CTAStart +### CTAStart The start element of the CTA layout. -## CTACenter +### CTACenter The center element of the CTA layout. -## CTAEnd +### CTAEnd The end element of the CTA layout. diff --git a/src/lib/components/layout/FormLayout/FormLayout.jsx b/src/lib/components/layout/FormLayout/FormLayout.jsx index 736fafafc..cd84623c7 100644 --- a/src/lib/components/layout/FormLayout/FormLayout.jsx +++ b/src/lib/components/layout/FormLayout/FormLayout.jsx @@ -55,6 +55,10 @@ export const FormLayout = (props) => { ].join(' ')} {...hasCustomLabelWidth ? { style: { '--rui-custom-label-width': labelWidth } } : {}} > + {/* + Flatten children to one-dimensional array so we get over React Fragments with the `map()` + function. + */} {flattenChildren(children).map((child) => { if (!React.isValidElement(child)) { return null; diff --git a/src/lib/components/layout/FormLayout/README.mdx b/src/lib/components/layout/FormLayout/README.mdx index d5f3750de..1ff8de089 100644 --- a/src/lib/components/layout/FormLayout/README.mdx +++ b/src/lib/components/layout/FormLayout/README.mdx @@ -367,7 +367,7 @@ This is a demo of all components supported by FormLayout. -## FormLayoutCustomField +### FormLayoutCustomField A place for custom content inside FormLayout. diff --git a/src/lib/components/layout/Grid/Grid.jsx b/src/lib/components/layout/Grid/Grid.jsx index c802fda38..b529f75d2 100644 --- a/src/lib/components/layout/Grid/Grid.jsx +++ b/src/lib/components/layout/Grid/Grid.jsx @@ -1,16 +1,19 @@ -import flattenChildren from 'react-keyed-flatten-children'; import PropTypes from 'prop-types'; import React from 'react'; +import { generateResponsiveCustomProperties } from './helpers/generateResponsiveCustomProperties'; import styles from './Grid.scss'; -export const Grid = (props) => { - const { - children, - id, - ...other - } = props; - - if (!props.children) { +export const Grid = ({ + autoFlow, + children, + columnGap, + columns, + id, + rowGap, + rows, + ...other +}) => { + if (!children) { return null; } @@ -18,33 +21,111 @@ export const Grid = (props) => {
- {flattenChildren(children).map((child) => { - if (!React.isValidElement(child)) { - return null; - } - - return React.cloneElement(child); - })} + {children}
); }; +/* Breakpoints are easier to work with when ordered according to their value, not name. */ +/* eslint-disable sort-keys */ + Grid.defaultProps = { children: null, + columnGap: undefined, + columns: undefined, + autoFlow: undefined, id: undefined, + rowGap: undefined, + rows: undefined, }; Grid.propTypes = { + /** + * Grid auto-flow algorithm to be used. Accepts any valid value of `grid-auto-flow` CSS property. + * See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow) for more. + */ + autoFlow: PropTypes.oneOf(['row', 'column', 'dense', 'row dense', 'column dense']), /** * Items to be aligned in the grid. */ children: PropTypes.node, + /** + * Gap between columns. Accepts any valid value of `grid-column-gap` CSS property. + * See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/column-gap) for more. + */ + columnGap: PropTypes.oneOf([ + PropTypes.string, + PropTypes.shape({ + xs: PropTypes.string, + sm: PropTypes.string, + md: PropTypes.string, + lg: PropTypes.string, + xl: PropTypes.string, + xxl: PropTypes.string, + xxxl: PropTypes.string, + }), + ]), + /** + * Grid columns. Accepts any valid value of `grid-template-columns` CSS property. + * See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns) for more. + */ + columns: PropTypes.oneOf([ + PropTypes.string, + PropTypes.shape({ + xs: PropTypes.string, + sm: PropTypes.string, + md: PropTypes.string, + lg: PropTypes.string, + xl: PropTypes.string, + xxl: PropTypes.string, + xxxl: PropTypes.string, + }), + ]), /** * ID of the root HTML element. */ id: PropTypes.string, + /** + * Gap between rows. Accepts any valid value of `grid-row-gap` CSS property. + * See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/row-gap) for more. + */ + rowGap: PropTypes.oneOf([ + PropTypes.string, + PropTypes.shape({ + xs: PropTypes.string, + sm: PropTypes.string, + md: PropTypes.string, + lg: PropTypes.string, + xl: PropTypes.string, + xxl: PropTypes.string, + xxxl: PropTypes.string, + }), + ]), + /** + * Grid rows. Accepts any valid value of `grid-template-rows` CSS property. + * See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows) for more. + */ + rows: PropTypes.oneOf([ + PropTypes.string, + PropTypes.shape({ + xs: PropTypes.string, + sm: PropTypes.string, + md: PropTypes.string, + lg: PropTypes.string, + xl: PropTypes.string, + xxl: PropTypes.string, + xxxl: PropTypes.string, + }), + ]), }; export default Grid; diff --git a/src/lib/components/layout/Grid/Grid.scss b/src/lib/components/layout/Grid/Grid.scss index 65e22001e..1b0caa025 100644 --- a/src/lib/components/layout/Grid/Grid.scss +++ b/src/lib/components/layout/Grid/Grid.scss @@ -1,17 +1,56 @@ +// 1. Read value of `--rui-local--` that might have been defined by +// JavaScript and assign it to `--rui-local-` used in 2. +// +// Fallback cascade containing fallbacks for all previous breakpoints recursively is included +// using CSS custom property fallback mechanism like this: +// +// Fallback for `xs` breakpoint: `` +// Fallback for `sm` breakpoint: `var(--rui-local--xs, )` +// Fallback for `md` breakpoint: `var(--rui-local--sm, var(--rui-local--xs, ))` +// +// … etc, up to the largest breakpoint. +// +// A media query is then created for each breakpoint (with exception of `xs` which doesn't need a +// media query) and a corresponding responsive custom property variant is assigned to +// `--rui-local-` that is used later in CSS, see 2. +// +// Example for `sm` breakpoint: +// +// `--rui-local-: var(--rui-local--sm, var(--rui-local--xs, ))` +// +// 2. Apply custom property value that is defined within current breakpoint, see 1. +// +// 3. Any valid auto-flow algorithm can be used. It's applied globally for all breakpoints. + @import '../../../styles/settings/layouts'; -@import '../../../styles/tools/breakpoints'; -@import './theme'; +@import 'mixins'; -/* autoprefixer grid: off */ .root { + $_properties: ( + columns: var(--rui-grid-columns), + column-gap: var(--rui-grid-column-gap), + rows: var(--rui-grid-rows), + row-gap: var(--rui-grid-row-gap), + ); + + @include assign-responsive-custom-properties($_properties); // 1. + display: grid; - grid-template-columns: 1fr; - grid-template-rows: auto; - grid-gap: $grid-gap; + grid-template-columns: var(--rui-local-columns); // 2. + grid-template-rows: var(--rui-local-rows); // 2. + grid-gap: var(--rui-local-row-gap) var(--rui-local-column-gap); // 2. + grid-auto-flow: var(--rui-local-auto-flow, var(--rui-grid-auto-flow)); // 3. margin-bottom: $layout-common-bottom-spacing; +} + +.span { + $_properties: ( + column-span: 1, + row-span: 1, + ); + + @include assign-responsive-custom-properties($_properties); // 1. - @include breakpoint-up(sm) { - grid-template-columns: repeat(auto-fit, minmax($grid-item-min-width, $grid-item-max-width)); - justify-content: start; - } + grid-column: span var(--rui-local-column-span, 1); // 2. + grid-row: span var(--rui-local-row-span, 1); // 2. } diff --git a/src/lib/components/layout/Grid/GridSpan.jsx b/src/lib/components/layout/Grid/GridSpan.jsx new file mode 100644 index 000000000..022368a7c --- /dev/null +++ b/src/lib/components/layout/Grid/GridSpan.jsx @@ -0,0 +1,83 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { generateResponsiveCustomProperties } from './helpers/generateResponsiveCustomProperties'; +import styles from './Grid.scss'; + +export const GridSpan = ({ + children, + columns, + id, + rows, + ...other +}) => { + if (!children) { + return null; + } + + return ( +
+ {children} +
+ ); +}; + +/* Breakpoints are easier to work with when ordered according to their value, not name. */ +/* eslint-disable sort-keys */ + +GridSpan.defaultProps = { + children: null, + columns: undefined, + id: undefined, + rows: undefined, +}; + +GridSpan.propTypes = { + /** + * Items to be aligned in the grid. + */ + children: PropTypes.node, + /** + * Number of columns to span. + */ + columns: PropTypes.oneOf([ + PropTypes.number, + PropTypes.shape({ + xs: PropTypes.number, + sm: PropTypes.number, + md: PropTypes.number, + lg: PropTypes.number, + xl: PropTypes.number, + xxl: PropTypes.number, + xxxl: PropTypes.number, + }), + ]), + /** + * ID of the root HTML element. + */ + id: PropTypes.string, + /** + * Number of rows to span. + */ + rows: PropTypes.oneOf([ + PropTypes.number, + PropTypes.shape({ + xs: PropTypes.number, + sm: PropTypes.number, + md: PropTypes.number, + lg: PropTypes.number, + xl: PropTypes.number, + xxl: PropTypes.number, + xxxl: PropTypes.number, + }), + ]), +}; + +export default GridSpan; diff --git a/src/lib/components/layout/Grid/README.mdx b/src/lib/components/layout/Grid/README.mdx index fca6dd7cc..989cf70d8 100644 --- a/src/lib/components/layout/Grid/README.mdx +++ b/src/lib/components/layout/Grid/README.mdx @@ -12,6 +12,7 @@ import { } from 'docz' import { Placeholder } from '../../../../docs/_components/Placeholder/Placeholder' import { Grid } from './Grid' +import { GridSpan } from './GridSpan' The responsive Grid layout aligns content into an organized grid. @@ -26,7 +27,9 @@ import { Grid } from '@react-ui-org/react-ui'; And use it: - + + Grid item + Grid item Grid item Grid item Grid item @@ -38,23 +41,183 @@ See [API](#api) for all available options. ## General Guidelines -- To align your items in the grid, **simply wrap** them with the Grid - component. Unlike other grid frameworks, **no additional markup** like - GridItem or Cell is necessary. This is possible thanks to the +- This component implements native [CSS grid layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout), - the right tool for two-dimensional layouts. + the right CSS tool for two-dimensional layouts. You may use any value accepted + by + [grid-template-columns](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns), + [grid-template-rows](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows), + [grid-column-gap](https://developer.mozilla.org/en-US/docs/Web/CSS/column-gap), + [grid-row-gap](https://developer.mozilla.org/en-US/docs/Web/CSS/row-gap), and + [grid-auto-flow](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow) + CSS properties in corresponding API options of the component. + +- To align your items in the grid, **simply wrap** them with the Grid + component. Unlike other grid frameworks and UI libraries, **no additional + markup** like GridItem or Cell is necessary for your items. But it's there + when you really need itβ€”see [Advanced Layouts](#advanced-layouts). + +- The Grid component is so powerful that it enables you to build even very + advanced layouts **without** having to write **a single line of custom CSS.** + See [Advanced Layouts](#advanced-layouts) for more. + +πŸ‘‰ The default layout has one column, auto-sized rows and gaps of +[size 4](/foundation/spacing). Defaults for all Grid API options can be +[customized](/customize/theming) with CSS custom properties. + +## Columns and Rows + +Use `columns` and `rows` to specify your grid layout. + + + + Grid item + Grid item + Grid item + Grid item + Grid item + Grid item + + + +You can use the +[`repeat()`](https://developer.mozilla.org/en-US/docs/Web/CSS/repeat) function +to specify a recurring pattern. + + + + Grid item + Grid item + Grid item + Grid item + Grid item + Grid item + + + +Combine `repeat()` with `auto-fit` and +[`minmax()`](https://developer.mozilla.org/en-US/docs/Web/CSS/minmax) to build +automatic responsive layouts. Resize the playground to see it in action. + + + + Grid item + Grid item + Grid item + Grid item + Grid item + Grid item + + + +πŸ‘‰ If you need your items to have **equal height** even with content of varying +length, it may be necessary to set `height: 100%` on them. + +## Gaps -- If you need your items to have **equal height** even with content of varying - length, it may be necessary to set `height: 100%` on them. +Both column and row gaps can be customized. -πŸ‘‰ The default column width algorithm is `repeat(auto-fit, minmax(300px, auto))` -and it can be [customized](/customize/theming) with CSS custom properties. -More layout options are [coming soon](https://github.com/react-ui-org/react-ui/issues/149)! + + + Grid item + Grid item + Grid item + Grid item + Grid item + Grid item + + + +## Media Queries + +If you need to build more complicated layouts, you have full control over the +grid definition. Just specify your grid layout for +[breakpoints](/foundation/breakpoints) where a change of layout is needed. +The Grid component is written with the mobile-first approach so values for small +breakpoints are used until they're overriden by a bigger breakpoint. If `xs` +settings are omitted, theme defaults are used. Resize your browser to see how it +works. + + + + Grid item + Grid item + Grid item + Grid item + Grid item + Grid item + + + +## Advanced Layouts + +Wrap your content with GridSpan component to span it over multiple columns or +rows. Use the `autoFlow` option to control the layout when combined with +responsive columns and rows. + + + + Grid item + Grid item + Grid item + Grid item + Grid item + + + Grid item spanning over two lines and two rows + + + Grid item + Grid item + Grid item + Grid item + Grid item + Grid item + Grid item + + + +πŸ‘‰ `autoFlow` implements the `grid-auto-flow` CSS property. See +[MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow) to fully +understand available options. ## API +### GridSpan + +Wrapper for content that should span multiple rows or columns. + + + --- Next: [List β†’](/components/layout/list) diff --git a/src/lib/components/layout/Grid/__tests__/Grid.test.jsx b/src/lib/components/layout/Grid/__tests__/Grid.test.jsx index a6a4ccd4f..c246e3b14 100644 --- a/src/lib/components/layout/Grid/__tests__/Grid.test.jsx +++ b/src/lib/components/layout/Grid/__tests__/Grid.test.jsx @@ -1,6 +1,5 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { Card } from '../../../ui/Card/Card'; import { Grid } from '../Grid'; describe('rendering', () => { @@ -15,7 +14,7 @@ describe('rendering', () => { it('renders correctly with a single child', () => { const tree = shallow(( - content +
content
)); @@ -25,9 +24,9 @@ describe('rendering', () => { it('renders correctly with multiple children', () => { const tree = shallow(( - content 1 - content 2 - content 3 +
content 1
+
content 2
+
content 3
)); diff --git a/src/lib/components/layout/Grid/__tests__/GridSpan.test.jsx b/src/lib/components/layout/Grid/__tests__/GridSpan.test.jsx new file mode 100644 index 000000000..1d9ec1ab6 --- /dev/null +++ b/src/lib/components/layout/Grid/__tests__/GridSpan.test.jsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import { GridSpan } from '../GridSpan'; + +describe('rendering', () => { + it('renders correctly with no children', () => { + const tree = shallow(( + + )); + + expect(tree).toMatchSnapshot(); + }); + + it('renders correctly with a single child', () => { + const tree = shallow(( + +
content
+
+ )); + + expect(tree).toMatchSnapshot(); + }); + + it('renders correctly with multiple children', () => { + const tree = shallow(( + +
content 1
+
content 2
+
content 3
+
+ )); + + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/lib/components/layout/Grid/__tests__/__snapshots__/Grid.test.jsx.snap b/src/lib/components/layout/Grid/__tests__/__snapshots__/Grid.test.jsx.snap index 5eb9e14e9..31fe5bbb9 100644 --- a/src/lib/components/layout/Grid/__tests__/__snapshots__/Grid.test.jsx.snap +++ b/src/lib/components/layout/Grid/__tests__/__snapshots__/Grid.test.jsx.snap @@ -3,54 +3,36 @@ exports[`rendering renders correctly with a single child 1`] = `
- +
content - +
`; exports[`rendering renders correctly with multiple children 1`] = `
- +
content 1 - - +
+
content 2 - - +
+
content 3 - +
`; diff --git a/src/lib/components/layout/Grid/__tests__/__snapshots__/GridSpan.test.jsx.snap b/src/lib/components/layout/Grid/__tests__/__snapshots__/GridSpan.test.jsx.snap new file mode 100644 index 000000000..f7ea3626a --- /dev/null +++ b/src/lib/components/layout/Grid/__tests__/__snapshots__/GridSpan.test.jsx.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`rendering renders correctly with a single child 1`] = ` +
+
+ content +
+
+`; + +exports[`rendering renders correctly with multiple children 1`] = ` +
+
+ content 1 +
+
+ content 2 +
+
+ content 3 +
+
+`; + +exports[`rendering renders correctly with no children 1`] = `""`; diff --git a/src/lib/components/layout/Grid/_mixins.scss b/src/lib/components/layout/Grid/_mixins.scss new file mode 100644 index 000000000..0a4cfb372 --- /dev/null +++ b/src/lib/components/layout/Grid/_mixins.scss @@ -0,0 +1,37 @@ +@import '../../../styles/settings/breakpoints'; +@import '../../../styles/tools/breakpoints'; + +// Generate fallback cascade using `var()` function fallbacks. +// +// $property-name: Custom property name +// $initial-fallback: Initial fallback value +// $current-breakpoint: Generate cascade for breakpoints smaller than this one +@function _generate-custom-property-fallback-cascade($property-name, $initial-fallback, $current-breakpoint) { + $fallback-cascade: $initial-fallback; + + @each $breakpoint in map-keys($breakpoint-values) { + @if $breakpoint == $current-breakpoint { + @return $fallback-cascade; + } + + $fallback-cascade: var(--rui-local-#{$property-name}-#{$breakpoint}, $fallback-cascade); + } +} + +// Read custom properties within a given breakpoint and assign them to expected output custom +// properties. Use a generated fallback cascade should the custom property be undefined. +// +// $properties: : > pairs> +@mixin assign-responsive-custom-properties($properties) { + @each $breakpoint in map-keys($breakpoint-values) { + @include breakpoint-up($breakpoint) { + @each $property-name, $initial-fallback in $properties { + --rui-local-#{$property-name}: + var( + --rui-local-#{$property-name}-#{$breakpoint}, + #{_generate-custom-property-fallback-cascade($property-name, $initial-fallback, $breakpoint)} + ); + } + } + } +} diff --git a/src/lib/components/layout/Grid/_theme.scss b/src/lib/components/layout/Grid/_theme.scss deleted file mode 100644 index d8d177f5c..000000000 --- a/src/lib/components/layout/Grid/_theme.scss +++ /dev/null @@ -1,3 +0,0 @@ -$grid-item-min-width: var(--rui-grid-item-min-width); -$grid-item-max-width: var(--rui-grid-item-max-width); -$grid-gap: var(--rui-grid-gap); diff --git a/src/lib/components/layout/Grid/helpers/__tests__/generateResponsiveCustomProperties.test.js b/src/lib/components/layout/Grid/helpers/__tests__/generateResponsiveCustomProperties.test.js new file mode 100644 index 000000000..0b64880cb --- /dev/null +++ b/src/lib/components/layout/Grid/helpers/__tests__/generateResponsiveCustomProperties.test.js @@ -0,0 +1,29 @@ +import { generateResponsiveCustomProperties } from '../generateResponsiveCustomProperties'; + +describe('generateResponsiveCustomProperties', () => { + test('with prop that is undefined', () => { + expect( + generateResponsiveCustomProperties(undefined, null), + ).toEqual(null); + }); + + test('with prop that is not an object', () => { + expect( + generateResponsiveCustomProperties('1fr 1fr', 'columns'), + ).toEqual({ '--rui-local-columns-xs': '1fr 1fr' }); + }); + + test('with prop that is an object', () => { + expect( + generateResponsiveCustomProperties({ + xs: '1fr', + md: '1fr 2fr', /* eslint-disable-line sort-keys */ + xl: '1fr 2fr 1fr', + }, 'columns'), + ).toEqual({ + '--rui-local-columns-xs': '1fr', + '--rui-local-columns-md': '1fr 2fr', /* eslint-disable-line sort-keys */ + '--rui-local-columns-xl': '1fr 2fr 1fr', + }); + }); +}); diff --git a/src/lib/components/layout/Grid/helpers/generateResponsiveCustomProperties.js b/src/lib/components/layout/Grid/helpers/generateResponsiveCustomProperties.js new file mode 100644 index 000000000..dbe7fa09a --- /dev/null +++ b/src/lib/components/layout/Grid/helpers/generateResponsiveCustomProperties.js @@ -0,0 +1,16 @@ +export const generateResponsiveCustomProperties = (prop, infix) => { + if (typeof prop === 'undefined') { + return null; + } + + if (typeof prop !== 'object') { + return { [`--rui-local-${infix}-xs`]: prop }; + } + + return Object.keys(prop).reduce((acc, breakpoint) => ({ + ...acc, + [`--rui-local-${infix}-${breakpoint}`]: prop[breakpoint], + }), {}); +}; + +export default generateResponsiveCustomProperties; diff --git a/src/lib/components/layout/Grid/index.js b/src/lib/components/layout/Grid/index.js index 3d919c9ac..038e29080 100644 --- a/src/lib/components/layout/Grid/index.js +++ b/src/lib/components/layout/Grid/index.js @@ -1 +1,2 @@ -export { default } from './Grid'; +export { default as Grid } from './Grid'; +export { default as GridSpan } from './GridSpan'; diff --git a/src/lib/components/layout/List/README.mdx b/src/lib/components/layout/List/README.mdx index 1af8b1000..d26b88241 100644 --- a/src/lib/components/layout/List/README.mdx +++ b/src/lib/components/layout/List/README.mdx @@ -101,7 +101,7 @@ put it inside a flex or grid layout). -## ListItem +### ListItem A wrapper for individual list items. diff --git a/src/lib/components/layout/Media/README.mdx b/src/lib/components/layout/Media/README.mdx index ce32e7183..63876970f 100644 --- a/src/lib/components/layout/Media/README.mdx +++ b/src/lib/components/layout/Media/README.mdx @@ -50,13 +50,13 @@ teasers, etc., ie. when you need a **fixed-sized object** (eg. an image) and an -## MediaBody +### MediaBody A place for the text content. -## MediaObject +### MediaObject A place for the media object. diff --git a/src/lib/components/layout/Toolbar/README.mdx b/src/lib/components/layout/Toolbar/README.mdx index 49a6f18c8..b3df2c3ca 100644 --- a/src/lib/components/layout/Toolbar/README.mdx +++ b/src/lib/components/layout/Toolbar/README.mdx @@ -285,13 +285,13 @@ Try resizing the playground below to see how it works. -## ToolbarGroup +### ToolbarGroup A wrapper for grouping ToolbarItems together. -## ToolbarItem +### ToolbarItem A wrapper for individual toolbar items. diff --git a/src/lib/components/ui/Card/README.mdx b/src/lib/components/ui/Card/README.mdx index 3c71090ca..2f1eaf10a 100644 --- a/src/lib/components/ui/Card/README.mdx +++ b/src/lib/components/ui/Card/README.mdx @@ -275,14 +275,14 @@ its interactive elements to disallow user's interaction. -## CardBody +### CardBody Space your content with CardBody. See [Card Composition](#card-composition) for all details. -## CardFooter +### CardFooter Separate your card actions with CardFooter. See [Card Composition](#card-composition) for all details. diff --git a/src/lib/index.js b/src/lib/index.js index 797636ce8..911c30934 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -10,7 +10,10 @@ export { FormLayout, FormLayoutCustomField, } from './components/layout/FormLayout'; -export { default as Grid } from './components/layout/Grid'; +export { + Grid, + GridSpan, +} from './components/layout/Grid'; export { List, ListItem, diff --git a/src/lib/styles/settings/_breakpoints.scss b/src/lib/styles/settings/_breakpoints.scss index 44b8fefbf..20d44c11a 100644 --- a/src/lib/styles/settings/_breakpoints.scss +++ b/src/lib/styles/settings/_breakpoints.scss @@ -1,3 +1,4 @@ +// ⚠️ Keep in sync with `src/lib/theme.scss`. $breakpoint-values: ( xs: 0, sm: 36em, diff --git a/src/lib/theme.scss b/src/lib/theme.scss index d94ee2041..7c668a427 100644 --- a/src/lib/theme.scss +++ b/src/lib/theme.scss @@ -73,6 +73,8 @@ // Breakpoints // Read-only, custom properties cannot be used within media queries as media query is not a property. // https://www.w3.org/TR/css-variables-1/#using-variables + // + // ⚠️ Keep in sync with `src/lib/styles/settings/_breakpoints.scss`. --rui-breakpoint-xs: #{map-get($breakpoint-values, xs)}; --rui-breakpoint-sm: #{map-get($breakpoint-values, sm)}; --rui-breakpoint-md: #{map-get($breakpoint-values, md)}; @@ -536,9 +538,11 @@ // Grid // ==== - --rui-grid-item-min-width: 300px; - --rui-grid-item-max-width: auto; - --rui-grid-gap: var(--rui-spacing-4); + --rui-grid-columns: 1fr; + --rui-grid-column-gap: var(--rui-spacing-4); + --rui-grid-rows: auto; + --rui-grid-row-gap: var(--rui-spacing-4); + --rui-grid-auto-flow: initial; // // Modal