From d2062d1538e0489cf7a7e55b97665f011291f367 Mon Sep 17 00:00:00 2001 From: Katie McFaul Date: Mon, 15 May 2023 16:32:19 -0400 Subject: [PATCH 1/3] feat(Flex): add gap support --- packages/react-core/src/layouts/Flex/Flex.tsx | 141 ++++++++++ .../src/layouts/Flex/__tests__/Flex.test.tsx | 40 ++- .../src/layouts/Flex/examples/Flex.md | 243 +++++++++++++----- 3 files changed, 351 insertions(+), 73 deletions(-) diff --git a/packages/react-core/src/layouts/Flex/Flex.tsx b/packages/react-core/src/layouts/Flex/Flex.tsx index 0e964da5bc1..5c8b06b1460 100644 --- a/packages/react-core/src/layouts/Flex/Flex.tsx +++ b/packages/react-core/src/layouts/Flex/Flex.tsx @@ -136,6 +136,141 @@ export interface FlexProps extends React.HTMLProps { | 'spaceItems3xl' | 'spaceItems4xl'; }; + /** Whether to add a gap at various breakpoints. This will override spacers for the main axis. */ + gap?: { + default?: 'gapNone' | 'gapXs' | 'gapSm' | 'gapMd' | 'gapLg' | 'gapXl' | 'gap2xl' | 'gap3xl' | 'gap4xl'; + sm?: 'gapNone' | 'gapXs' | 'gapSm' | 'gapMd' | 'gapLg' | 'gapXl' | 'gap2xl' | 'gap3xl' | 'gap4xl'; + md?: 'gapNone' | 'gapXs' | 'gapSm' | 'gapMd' | 'gapLg' | 'gapXl' | 'gap2xl' | 'gap3xl' | 'gap4xl'; + lg?: 'gapNone' | 'gapXs' | 'gapSm' | 'gapMd' | 'gapLg' | 'gapXl' | 'gap2xl' | 'gap3xl' | 'gap4xl'; + xl?: 'gapNone' | 'gapXs' | 'gapSm' | 'gapMd' | 'gapLg' | 'gapXl' | 'gap2xl' | 'gap3xl' | 'gap4xl'; + '2xl'?: 'gapNone' | 'gapXs' | 'gapSm' | 'gapMd' | 'gapLg' | 'gapXl' | 'gap2xl' | 'gap3xl' | 'gap4xl'; + }; + /** Whether to add a gap at various breakpoints. This will override spacers for the main axis. */ + rowGap?: { + default?: + | 'rowGapNone' + | 'rowGapXs' + | 'rowGapSm' + | 'rowGapMd' + | 'rowGapLg' + | 'rowGapXl' + | 'rowGap2xl' + | 'rowGap3xl' + | 'rowGap4xl'; + sm?: + | 'rowGapNone' + | 'rowGapXs' + | 'rowGapSm' + | 'rowGapMd' + | 'rowGapLg' + | 'rowGapXl' + | 'rowGap2xl' + | 'rowGap3xl' + | 'rowGap4xl'; + md?: + | 'rowGapNone' + | 'rowGapXs' + | 'rowGapSm' + | 'rowGapMd' + | 'rowGapLg' + | 'rowGapXl' + | 'rowGap2xl' + | 'rowGap3xl' + | 'rowGap4xl'; + lg?: + | 'rowGapNone' + | 'rowGapXs' + | 'rowGapSm' + | 'rowGapMd' + | 'rowGapLg' + | 'rowGapXl' + | 'rowGap2xl' + | 'rowGap3xl' + | 'rowGap4xl'; + xl?: + | 'rowGapNone' + | 'rowGapXs' + | 'rowGapSm' + | 'rowGapMd' + | 'rowGapLg' + | 'rowGapXl' + | 'rowGap2xl' + | 'rowGap3xl' + | 'rowGap4xl'; + '2xl'?: + | 'rowGapNone' + | 'rowGapXs' + | 'rowGapSm' + | 'rowGapMd' + | 'rowGapLg' + | 'rowGapXl' + | 'rowGap2xl' + | 'rowGap3xl' + | 'rowGap4xl'; + }; + /** Whether to add a gap at various breakpoints. This will override spacers for the main axis. */ + columnGap?: { + default?: + | 'columnGapNone' + | 'columnGapXs' + | 'columnGapSm' + | 'columnGapMd' + | 'columnGapLg' + | 'columnGapXl' + | 'columnGap2xl' + | 'columnGap3xl' + | 'columnGap4xl'; + sm?: + | 'columnGapNone' + | 'columnGapXs' + | 'columnGapSm' + | 'columnGapMd' + | 'columnGapLg' + | 'columnGapXl' + | 'columnGap2xl' + | 'columnGap3xl' + | 'columnGap4xl'; + md?: + | 'columnGapNone' + | 'columnGapXs' + | 'columnGapSm' + | 'columnGapMd' + | 'columnGapLg' + | 'columnGapXl' + | 'columnGap2xl' + | 'columnGap3xl' + | 'columnGap4xl'; + lg?: + | 'columnGapNone' + | 'columnGapXs' + | 'columnGapSm' + | 'columnGapMd' + | 'columnGapLg' + | 'columnGapXl' + | 'columnGap2xl' + | 'columnGap3xl' + | 'columnGap4xl'; + xl?: + | 'columnGapNone' + | 'columnGapXs' + | 'columnGapSm' + | 'columnGapMd' + | 'columnGapLg' + | 'columnGapXl' + | 'columnGap2xl' + | 'columnGap3xl' + | 'columnGap4xl'; + '2xl'?: + | 'columnGapNone' + | 'columnGapXs' + | 'columnGapSm' + | 'columnGapMd' + | 'columnGapLg' + | 'columnGapXl' + | 'columnGap2xl' + | 'columnGap3xl' + | 'columnGap4xl'; + }; /** Whether to add flex: grow at various breakpoints */ grow?: { default?: 'grow'; @@ -344,6 +479,9 @@ export const Flex: React.FunctionComponent = ({ component = 'div', spacer, spaceItems, + gap, + rowGap, + columnGap, grow, shrink, flex, @@ -380,6 +518,9 @@ export const Flex: React.FunctionComponent = ({ formatBreakpointMods(display, styles), formatBreakpointMods(fullWidth, styles), formatBreakpointMods(flexWrap, styles), + formatBreakpointMods(gap, styles), + formatBreakpointMods(rowGap, styles), + formatBreakpointMods(columnGap, styles), className )} style={ diff --git a/packages/react-core/src/layouts/Flex/__tests__/Flex.test.tsx b/packages/react-core/src/layouts/Flex/__tests__/Flex.test.tsx index 2eeb21a12fe..26249dfbffb 100644 --- a/packages/react-core/src/layouts/Flex/__tests__/Flex.test.tsx +++ b/packages/react-core/src/layouts/Flex/__tests__/Flex.test.tsx @@ -85,16 +85,40 @@ describe('Flex', () => { ], display: ['inlineFlex'], fullWidth: ['fullWidth'], - flexWrap: ['wrap', 'wrapReverse', 'nowrap'] + flexWrap: ['wrap', 'wrapReverse', 'nowrap'], + gap: ['gapNone', 'gapXs', 'gapSm', 'gapMd', 'gapLg', 'gapXl', 'gap2xl', 'gap3xl', 'gap4xl'], + rowGap: [ + 'rowGapNone', + 'rowGapXs', + 'rowGapSm', + 'rowGapMd', + 'rowGapLg', + 'rowGapXl', + 'rowGap2xl', + 'rowGap3xl', + 'rowGap4xl' + ], + columnGap: [ + 'columnGapNone', + 'columnGapXs', + 'columnGapSm', + 'columnGapMd', + 'columnGapLg', + 'columnGapXl', + 'columnGap2xl', + 'columnGap3xl', + 'columnGap4xl' + ] }; describe('flex modifiers', () => { Object.entries(flexModifiers) .map(([mod, values]) => - values.map(value => ({ + values.map((value) => ({ [mod]: { default: value, sm: value, + md: value, lg: value, xl: value, '2xl': value @@ -102,7 +126,7 @@ describe('Flex', () => { })) ) .reduce((acc, val) => acc.concat(val), []) - .forEach(props => + .forEach((props) => test(`${JSON.stringify(props)} add valid classes to Flex`, () => { render( @@ -110,11 +134,7 @@ describe('Flex', () => { ); - const className = screen - .getByTestId('test-id') - .className.replace('pf-l-flex', '') - .trim(); - + const className = screen.getByTestId('test-id').className.replace('pf-l-flex', '').trim(); expect(className).not.toBe("''"); expect(className).not.toBe(''); }) @@ -134,7 +154,7 @@ describe('Flex', () => { describe('flexItem modifiers', () => { Object.entries(flexItemModifiers) .map(([mod, values]) => - values.map(value => ({ + values.map((value) => ({ [mod]: { default: value, sm: value, @@ -145,7 +165,7 @@ describe('Flex', () => { })) ) .reduce((acc, val) => acc.concat(val), []) - .forEach(props => + .forEach((props) => test(`${JSON.stringify(props)} add valid classes to FlexItem`, () => { render( diff --git a/packages/react-core/src/layouts/Flex/examples/Flex.md b/packages/react-core/src/layouts/Flex/examples/Flex.md index a50b35ff04a..950502c0816 100644 --- a/packages/react-core/src/layouts/Flex/examples/Flex.md +++ b/packages/react-core/src/layouts/Flex/examples/Flex.md @@ -8,7 +8,9 @@ propComponents: ['Flex', 'FlexItem'] import './flex.css'; ## Flex Basics + ### Basic + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -19,10 +21,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item Flex item - +; ``` ### Nesting + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -37,10 +40,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ### Nested with items + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -55,11 +59,13 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item - +; ``` ### Flex Spacing + ### Individually spaced + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -73,10 +79,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Item - xl Item - 2xl Item - 3xl - +; ``` ### Spacing xl + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -87,10 +94,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item Flex item - +; ``` ### Spacing none + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -101,11 +109,75 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item Flex item - +; +``` + +### Flex Gap + +### Row gap + +```js +import React from 'react'; +import { Flex, FlexItem } from '@patternfly/react-core'; + + + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item +; +``` + +### Column gap + +```js +import React from 'react'; +import { Flex, FlexItem } from '@patternfly/react-core'; + + + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item +; +``` + +### Gap + +```js +import React from 'react'; +import { Flex, FlexItem } from '@patternfly/react-core'; + + + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item + Flex item +; ``` ### Flex layout modifiers + ### Default layout + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -116,10 +188,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item Flex item - +; ``` ### Inline + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -130,10 +203,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item Flex item - +; ``` ### Using canGrow + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -151,10 +225,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item - +; ``` ### Adjusting width + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -172,10 +247,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ### Specifying column widths + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -193,12 +269,13 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ## Column layout modifiers ### Column layout + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -207,10 +284,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item Flex item - +; ``` ### Stacking elements + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -228,10 +306,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item - +; ``` ### Nesting elements in columns + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -246,12 +325,13 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ## Responsive layout modifiers ### Switching between direction column and row + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -267,10 +347,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ### Controlling width of text + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -278,18 +359,22 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item - Lorem ipsum dolor sit amet consectetur adipisicing elit. Est animi modi temporibus, alias qui obcaecati ullam dolor nam, nulla magni iste rem praesentium numquam provident amet ut nesciunt harum accusamus. + + Lorem ipsum dolor sit amet consectetur adipisicing elit. Est animi modi temporibus, alias qui obcaecati ullam + dolor nam, nulla magni iste rem praesentium numquam provident amet ut nesciunt harum accusamus. + Flex item Flex item - +; ``` ## Flex alignment ### Aligning right + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -300,10 +385,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item Flex item - +; ``` ### Align right on single item + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -311,10 +397,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ### Align right on multiple groups + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -332,10 +419,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ### Align adjacent content + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -351,10 +439,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ### Align self flex end + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -369,10 +458,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ### Align self center + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -387,10 +477,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ### Align self baseline + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -405,10 +496,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ### Align self stretch + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -423,12 +515,13 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item - +; ``` ## Flex justification ### Justify content flex end + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -438,22 +531,24 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item Flex item - +; ``` ### Justify content space between + ```js import React from 'react'; -import { Flex, FlexItem } from '@patternfly/react-core'; +import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item Flex item - +; ``` ### Justify content flex start + ```js import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; @@ -462,7 +557,7 @@ import { Flex, FlexItem } from '@patternfly/react-core'; Flex item Flex item Flex item - +; ``` ## Flex item order @@ -474,10 +569,14 @@ import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; - Item A + + Item A + Item B - Item C - + + Item C + +; ``` ### Responsive first last ordering @@ -487,10 +586,16 @@ import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; - Item A - Item B - Item C - + + Item A + + + Item B + + + Item C + +; ``` ### Ordering @@ -500,19 +605,25 @@ import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; - - Set 1, Item A - Set 1, Item B - Set 1, Item C - Set 1, Item D - - - Set 2, Item A - Set 2, Item B + + Set 1, Item A + Set 1, Item B + Set 1, Item C + + Set 1, Item D + + + + + Set 2, Item A + + Set 2, Item B Set 2, Item C - Set 2, Item D + + Set 2, Item D + - +; ``` ### Responsive ordering @@ -522,20 +633,26 @@ import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; - - Set 1, Item A - Set 1, Item B + + + Set 1, Item A + + Set 1, Item B Set 1, Item C - Set 1, Item D + Set 1, Item D - - Set 2, Item A - Set 2, Item B + + + Set 2, Item A + + Set 2, Item B Set 2, Item C - Set 2, Item D + + Set 2, Item D + - +; ``` ### Alternative components @@ -544,11 +661,11 @@ import { Flex, FlexItem } from '@patternfly/react-core'; import React from 'react'; import { Flex, FlexItem } from '@patternfly/react-core'; - - Flex item - Flex item - Flex item - Flex item - Flex item - + + Flex item + Flex item + Flex item + Flex item + Flex item +; ``` From 0d64a7a4b584cc5b33cf7466d5912d3bebec6e23 Mon Sep 17 00:00:00 2001 From: Katie McFaul Date: Tue, 16 May 2023 10:39:15 -0400 Subject: [PATCH 2/3] update docs, prop desc --- packages/react-core/src/layouts/Flex/Flex.tsx | 6 +++--- packages/react-core/src/layouts/Flex/examples/Flex.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/react-core/src/layouts/Flex/Flex.tsx b/packages/react-core/src/layouts/Flex/Flex.tsx index 5c8b06b1460..c5ae24928ce 100644 --- a/packages/react-core/src/layouts/Flex/Flex.tsx +++ b/packages/react-core/src/layouts/Flex/Flex.tsx @@ -136,7 +136,7 @@ export interface FlexProps extends React.HTMLProps { | 'spaceItems3xl' | 'spaceItems4xl'; }; - /** Whether to add a gap at various breakpoints. This will override spacers for the main axis. */ + /** Gap between items at various breakpoints. This will override spacers for the main axis. */ gap?: { default?: 'gapNone' | 'gapXs' | 'gapSm' | 'gapMd' | 'gapLg' | 'gapXl' | 'gap2xl' | 'gap3xl' | 'gap4xl'; sm?: 'gapNone' | 'gapXs' | 'gapSm' | 'gapMd' | 'gapLg' | 'gapXl' | 'gap2xl' | 'gap3xl' | 'gap4xl'; @@ -145,7 +145,7 @@ export interface FlexProps extends React.HTMLProps { xl?: 'gapNone' | 'gapXs' | 'gapSm' | 'gapMd' | 'gapLg' | 'gapXl' | 'gap2xl' | 'gap3xl' | 'gap4xl'; '2xl'?: 'gapNone' | 'gapXs' | 'gapSm' | 'gapMd' | 'gapLg' | 'gapXl' | 'gap2xl' | 'gap3xl' | 'gap4xl'; }; - /** Whether to add a gap at various breakpoints. This will override spacers for the main axis. */ + /** Gap between rows at various breakpoints. This will override spacers for the main axis. */ rowGap?: { default?: | 'rowGapNone' @@ -208,7 +208,7 @@ export interface FlexProps extends React.HTMLProps { | 'rowGap3xl' | 'rowGap4xl'; }; - /** Whether to add a gap at various breakpoints. This will override spacers for the main axis. */ + /** Gap beween columns at various breakpoints. This will override spacers for the main axis. */ columnGap?: { default?: | 'columnGapNone' diff --git a/packages/react-core/src/layouts/Flex/examples/Flex.md b/packages/react-core/src/layouts/Flex/examples/Flex.md index 950502c0816..332b087f90f 100644 --- a/packages/react-core/src/layouts/Flex/examples/Flex.md +++ b/packages/react-core/src/layouts/Flex/examples/Flex.md @@ -7,7 +7,7 @@ propComponents: ['Flex', 'FlexItem'] import './flex.css'; -## Flex Basics +## Flex basics ### Basic @@ -62,7 +62,7 @@ import { Flex, FlexItem } from '@patternfly/react-core'; ; ``` -### Flex Spacing +### Flex spacing ### Individually spaced @@ -112,7 +112,7 @@ import { Flex, FlexItem } from '@patternfly/react-core'; ; ``` -### Flex Gap +### Flex gap spacing ### Row gap From 64dcdf92c0e18244445994bde040208dd1582cf4 Mon Sep 17 00:00:00 2001 From: Katie McFaul Date: Tue, 16 May 2023 17:27:57 -0400 Subject: [PATCH 3/3] add blurb --- packages/react-core/src/layouts/Flex/examples/Flex.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/react-core/src/layouts/Flex/examples/Flex.md b/packages/react-core/src/layouts/Flex/examples/Flex.md index 332b087f90f..2f138383403 100644 --- a/packages/react-core/src/layouts/Flex/examples/Flex.md +++ b/packages/react-core/src/layouts/Flex/examples/Flex.md @@ -62,6 +62,16 @@ import { Flex, FlexItem } from '@patternfly/react-core'; ; ``` +### Spacing + +The flex layout provides two ways of spacing its direct children. + +- [Spacing system](#flex-spacing) + - The spacing system applies a margin between the flex layout's direct children to create space between items along the main axis only. The benefit of the spacing system is that it allows for variable spacing between direct children. Use the spacing system when individual flex items along the main axis require a different spacer than sibling items. +- [Gap spacing](#flex-gap-spacing) + - Gap spacing uses flex `gap` to space the flex layout's direct children, and can be applied to space rows (`row-gap`), columns (`column-gap`), or both (`gap`). The benefit of gap spacing is that item wrapping is improved and improved item spacing that works better with CSS flex's logical layout properties. E.g., spacing in RTL layouts that rely on logical properties is improved. Use the gap system when all direct children should use the same spacer for rows, columns, or both. + - **Note** using `gap` along the main axis will override any other spacing applied using the spacing system. + ### Flex spacing ### Individually spaced