Skip to content

Commit 4f0d57f

Browse files
ciampotellthemachines
authored andcommitted
ZStack: fix component bounding box to match children (#51836)
* ZStack: rewrite using CSS grid * Use first-of-type instead of fist-child * CHANGELOG * Improve comment * Apply styles once in the parent wrapper * Avoid each child view from expanding to all available space * Remove unnecessary wrapeprs in storybook exmaple
1 parent da17fa8 commit 4f0d57f

File tree

4 files changed

+34
-39
lines changed

4 files changed

+34
-39
lines changed

packages/components/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- `Button`: Remove unnecessary margin from dashicon ([#51395](https://github.com/WordPress/gutenberg/pull/51395)).
1717
- `Autocomplete`: Announce how many results are available to screen readers when suggestions list first renders ([#51018](https://github.com/WordPress/gutenberg/pull/51018)).
1818
- `ConfirmDialog`: Ensure onConfirm isn't called an extra time when submitting one of the buttons using the keyboard ([#51730](https://github.com/WordPress/gutenberg/pull/51730)).
19+
- `ZStack`: ZStack: fix component bounding box to match children ([#51836](https://github.com/WordPress/gutenberg/pull/51836)).
1920

2021
### Internal
2122

packages/components/src/z-stack/component.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@ function UnconnectedZStack(
3535

3636
const clonedChildren = validChildren.map( ( child, index ) => {
3737
const zIndex = isReversed ? childrenLastIndex - index : index;
38-
const offsetAmount = offset * index;
38+
// Only when the component is layered, the offset needs to be multiplied by
39+
// the item's index, so that items can correctly stack at the right distance
40+
const offsetAmount = isLayered ? offset * index : offset;
3941

4042
const key = isValidElement( child ) ? child.key : index;
4143

4244
return (
4345
<ZStackChildView
44-
isLayered={ isLayered }
4546
offsetAmount={ offsetAmount }
4647
zIndex={ zIndex }
4748
key={ key }
@@ -55,6 +56,7 @@ function UnconnectedZStack(
5556
<ZStackView
5657
{ ...otherProps }
5758
className={ className }
59+
isLayered={ isLayered }
5860
ref={ forwardedRef }
5961
>
6062
{ clonedChildren }

packages/components/src/z-stack/stories/index.tsx

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import type { ComponentMeta, ComponentStory } from '@storybook/react';
88
* Internal dependencies
99
*/
1010
import { Elevation } from '../../elevation';
11-
import { HStack } from '../../h-stack';
1211
import { View } from '../../view';
1312
import { ZStack } from '..';
1413

@@ -55,18 +54,12 @@ const Avatar = ( {
5554

5655
const Template: ComponentStory< typeof ZStack > = ( args ) => {
5756
return (
58-
<View>
59-
<HStack>
60-
<View>
61-
<ZStack { ...args }>
62-
<Avatar backgroundColor="#444" />
63-
<Avatar backgroundColor="#777" />
64-
<Avatar backgroundColor="#aaa" />
65-
<Avatar backgroundColor="#fff" />
66-
</ZStack>
67-
</View>
68-
</HStack>
69-
</View>
57+
<ZStack { ...args }>
58+
<Avatar backgroundColor="#444" />
59+
<Avatar backgroundColor="#777" />
60+
<Avatar backgroundColor="#aaa" />
61+
<Avatar backgroundColor="#fff" />
62+
</ZStack>
7063
);
7164
};
7265

packages/components/src/z-stack/styles.ts

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,35 @@
44
import { css } from '@emotion/react';
55
import styled from '@emotion/styled';
66

7-
/**
8-
* Internal dependencies
9-
*/
10-
import { rtl } from '../utils';
11-
12-
export const ZStackView = styled.div`
13-
display: flex;
14-
position: relative;
15-
`;
16-
177
export const ZStackChildView = styled.div< {
18-
isLayered: boolean;
198
offsetAmount: number;
209
zIndex: number;
2110
} >`
22-
${ ( { isLayered, offsetAmount } ) =>
23-
isLayered
24-
? css( rtl( { marginLeft: offsetAmount } )() )
25-
: css( rtl( { right: offsetAmount * -1 } )() ) }
11+
&:not( :first-of-type ) {
12+
${ ( { offsetAmount } ) =>
13+
css( {
14+
marginInlineStart: offsetAmount,
15+
} ) };
16+
}
2617
27-
${ ( { isLayered } ) =>
28-
isLayered ? positionAbsolute : positionRelative }
29-
30-
${ ( { zIndex } ) => css( { zIndex } ) }
31-
`;
32-
33-
const positionAbsolute = css`
34-
position: absolute;
18+
${ ( { zIndex } ) => css( { zIndex } ) };
3519
`;
3620

37-
const positionRelative = css`
21+
export const ZStackView = styled.div< {
22+
isLayered: boolean;
23+
} >`
24+
display: inline-grid;
25+
grid-auto-flow: column;
3826
position: relative;
27+
28+
& > ${ ZStackChildView } {
29+
position: relative;
30+
justify-self: start;
31+
32+
${ ( { isLayered } ) =>
33+
isLayered
34+
? // When `isLayered` is true, all items overlap in the same grid cell
35+
css( { gridRowStart: 1, gridColumnStart: 1 } )
36+
: undefined };
37+
}
3938
`;

0 commit comments

Comments
 (0)