From 36d59e339779ed43ffa112594bb7c3b339c8ca2e Mon Sep 17 00:00:00 2001 From: Angel Duran Date: Tue, 21 Dec 2021 21:31:20 -0800 Subject: [PATCH] Fixing React.Fragment wrapping StackItems inside a Stack. (#21090) Co-authored-by: Angel Duran --- ...-6185695e-90a7-4334-a2c0-b2f29e60efc6.json | 7 ++ .../Separator.Basic.Example.tsx.shot | 8 +- .../react/src/components/Stack/Stack.test.tsx | 26 ++++ packages/react/src/components/Stack/Stack.tsx | 43 ++++--- .../Stack/__snapshots__/Stack.test.tsx.snap | 114 ++++++++++++++++++ 5 files changed, 176 insertions(+), 22 deletions(-) create mode 100644 change/@fluentui-react-6185695e-90a7-4334-a2c0-b2f29e60efc6.json diff --git a/change/@fluentui-react-6185695e-90a7-4334-a2c0-b2f29e60efc6.json b/change/@fluentui-react-6185695e-90a7-4334-a2c0-b2f29e60efc6.json new file mode 100644 index 0000000000000..0692f085589c0 --- /dev/null +++ b/change/@fluentui-react-6185695e-90a7-4334-a2c0-b2f29e60efc6.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fixing Stack behavior when a React.Fragment wraps StackItems, it should be ignored.", + "packageName": "@fluentui/react", + "email": "aduran@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-examples/src/react/__snapshots__/Separator.Basic.Example.tsx.shot b/packages/react-examples/src/react/__snapshots__/Separator.Basic.Example.tsx.shot index 207bcbaf30408..c3a2b350872d0 100644 --- a/packages/react-examples/src/react/__snapshots__/Separator.Basic.Example.tsx.shot +++ b/packages/react-examples/src/react/__snapshots__/Separator.Basic.Example.tsx.shot @@ -443,7 +443,7 @@ exports[`Component Examples renders Separator.Basic.Example.tsx correctly 1`] = { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; - flex-shrink: 0; + flex-shrink: 1; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Roboto', 'Helvetica Neue', sans-serif; font-size: 14px; font-weight: 400; @@ -552,7 +552,7 @@ exports[`Component Examples renders Separator.Basic.Example.tsx correctly 1`] = { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; - flex-shrink: 0; + flex-shrink: 1; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Roboto', 'Helvetica Neue', sans-serif; font-size: 14px; font-weight: 400; @@ -661,7 +661,7 @@ exports[`Component Examples renders Separator.Basic.Example.tsx correctly 1`] = { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; - flex-shrink: 0; + flex-shrink: 1; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Roboto', 'Helvetica Neue', sans-serif; font-size: 14px; font-weight: 400; @@ -770,7 +770,7 @@ exports[`Component Examples renders Separator.Basic.Example.tsx correctly 1`] = { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; - flex-shrink: 0; + flex-shrink: 1; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Roboto', 'Helvetica Neue', sans-serif; font-size: 14px; font-weight: 400; diff --git a/packages/react/src/components/Stack/Stack.test.tsx b/packages/react/src/components/Stack/Stack.test.tsx index 4488ed67226fd..7c1422ff8b765 100644 --- a/packages/react/src/components/Stack/Stack.test.tsx +++ b/packages/react/src/components/Stack/Stack.test.tsx @@ -224,6 +224,19 @@ describe('Stack', () => { expect(tree).toMatchSnapshot(); }); + it('renders vertical Stack with StackItems inside a React.Fragment correctly', () => { + const component = renderer.create( + + <> + Item 1 + Item 2 + + , + ); + const tree = component.toJSON(); + expect(tree).toMatchSnapshot(); + }); + it('renders horizontal Stack with shrinking StackItems correctly', () => { const component = renderer.create( @@ -235,6 +248,19 @@ describe('Stack', () => { expect(tree).toMatchSnapshot(); }); + it('renders horizontal Stack with StackItems inside a React.Fragment correctly', () => { + const component = renderer.create( + + <> + Item 1 + Item 2 + + , + ); + const tree = component.toJSON(); + expect(tree).toMatchSnapshot(); + }); + it('renders vertical Stack with shrinking StackItems correctly', () => { const component = renderer.create( diff --git a/packages/react/src/components/Stack/Stack.tsx b/packages/react/src/components/Stack/Stack.tsx index 14ce564f03d3f..557901b936ea8 100644 --- a/packages/react/src/components/Stack/Stack.tsx +++ b/packages/react/src/components/Stack/Stack.tsx @@ -18,27 +18,34 @@ const StackView: IStackComponent['view'] = props => { padding: 'tokens.padding', }); - const stackChildren: (React.ReactChild | null)[] | null | undefined = React.Children.map( - props.children, - (child: React.ReactElement, index: number) => { - if (!child) { - return null; - } + // React.Fragment needs to be ignored before checking for Stack's children + let stackChildren = React.Children.toArray(props.children); + if ( + stackChildren.length === 1 && + React.isValidElement(stackChildren[0]) && + stackChildren[0].type === React.Fragment + ) { + stackChildren = stackChildren[0].props.children; + } - if (_isStackItem(child)) { - const defaultItemProps: IStackItemProps = { - shrink: !disableShrink, - }; + stackChildren = React.Children.map(stackChildren, (child: React.ReactElement, index: number) => { + if (!child) { + return null; + } - return React.cloneElement(child, { - ...defaultItemProps, - ...child.props, - }); - } + if (_isStackItem(child)) { + const defaultItemProps: IStackItemProps = { + shrink: !disableShrink, + }; - return child; - }, - ); + return React.cloneElement(child, { + ...defaultItemProps, + ...child.props, + }); + } + + return child; + }); const nativeProps = getNativeProps>(rest, htmlElementProperties); diff --git a/packages/react/src/components/Stack/__snapshots__/Stack.test.tsx.snap b/packages/react/src/components/Stack/__snapshots__/Stack.test.tsx.snap index e241d5d2cb855..f5afdc583fa9d 100644 --- a/packages/react/src/components/Stack/__snapshots__/Stack.test.tsx.snap +++ b/packages/react/src/components/Stack/__snapshots__/Stack.test.tsx.snap @@ -297,6 +297,63 @@ exports[`Stack renders horizontal Stack with StackItems correctly 1`] = ` `; +exports[`Stack renders horizontal Stack with StackItems inside a React.Fragment correctly 1`] = ` +
* { + text-overflow: ellipsis; + } + & > *:not(:first-child) { + margin-left: 0px; + } + & > *:not(.ms-StackItem) { + flex-shrink: 1; + } +> +
+ Item 1 +
+
+ Item 2 +
+
+`; + exports[`Stack renders horizontal Stack with a gap correctly 1`] = `
`; +exports[`Stack renders vertical Stack with StackItems inside a React.Fragment correctly 1`] = ` +
* { + text-overflow: ellipsis; + } + & > *:not(:first-child) { + margin-top: 0px; + } + & > *:not(.ms-StackItem) { + flex-shrink: 1; + } +> +
+ Item 1 +
+
+ Item 2 +
+
+`; + exports[`Stack renders vertical Stack with a gap correctly 1`] = `