Skip to content

Commit

Permalink
ZStack: fix component bounding box to match children (#51836)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
ciampo authored Jun 26, 2023
1 parent d767805 commit 12a9749
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 39 deletions.
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- `Button`: Remove unnecessary margin from dashicon ([#51395](https://github.com/WordPress/gutenberg/pull/51395)).
- `Autocomplete`: Announce how many results are available to screen readers when suggestions list first renders ([#51018](https://github.com/WordPress/gutenberg/pull/51018)).
- `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)).
- `ZStack`: ZStack: fix component bounding box to match children ([#51836](https://github.com/WordPress/gutenberg/pull/51836)).

### Internal

Expand Down
6 changes: 4 additions & 2 deletions packages/components/src/z-stack/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ function UnconnectedZStack(

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

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

return (
<ZStackChildView
isLayered={ isLayered }
offsetAmount={ offsetAmount }
zIndex={ zIndex }
key={ key }
Expand All @@ -55,6 +56,7 @@ function UnconnectedZStack(
<ZStackView
{ ...otherProps }
className={ className }
isLayered={ isLayered }
ref={ forwardedRef }
>
{ clonedChildren }
Expand Down
19 changes: 6 additions & 13 deletions packages/components/src/z-stack/stories/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type { ComponentMeta, ComponentStory } from '@storybook/react';
* Internal dependencies
*/
import { Elevation } from '../../elevation';
import { HStack } from '../../h-stack';
import { View } from '../../view';
import { ZStack } from '..';

Expand Down Expand Up @@ -55,18 +54,12 @@ const Avatar = ( {

const Template: ComponentStory< typeof ZStack > = ( args ) => {
return (
<View>
<HStack>
<View>
<ZStack { ...args }>
<Avatar backgroundColor="#444" />
<Avatar backgroundColor="#777" />
<Avatar backgroundColor="#aaa" />
<Avatar backgroundColor="#fff" />
</ZStack>
</View>
</HStack>
</View>
<ZStack { ...args }>
<Avatar backgroundColor="#444" />
<Avatar backgroundColor="#777" />
<Avatar backgroundColor="#aaa" />
<Avatar backgroundColor="#fff" />
</ZStack>
);
};

Expand Down
47 changes: 23 additions & 24 deletions packages/components/src/z-stack/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,35 @@
import { css } from '@emotion/react';
import styled from '@emotion/styled';

/**
* Internal dependencies
*/
import { rtl } from '../utils';

export const ZStackView = styled.div`
display: flex;
position: relative;
`;

export const ZStackChildView = styled.div< {
isLayered: boolean;
offsetAmount: number;
zIndex: number;
} >`
${ ( { isLayered, offsetAmount } ) =>
isLayered
? css( rtl( { marginLeft: offsetAmount } )() )
: css( rtl( { right: offsetAmount * -1 } )() ) }
&:not( :first-of-type ) {
${ ( { offsetAmount } ) =>
css( {
marginInlineStart: offsetAmount,
} ) };
}
${ ( { isLayered } ) =>
isLayered ? positionAbsolute : positionRelative }
${ ( { zIndex } ) => css( { zIndex } ) }
`;

const positionAbsolute = css`
position: absolute;
${ ( { zIndex } ) => css( { zIndex } ) };
`;

const positionRelative = css`
export const ZStackView = styled.div< {
isLayered: boolean;
} >`
display: inline-grid;
grid-auto-flow: column;
position: relative;
& > ${ ZStackChildView } {
position: relative;
justify-self: start;
${ ( { isLayered } ) =>
isLayered
? // When `isLayered` is true, all items overlap in the same grid cell
css( { gridRowStart: 1, gridColumnStart: 1 } )
: undefined };
}
`;

0 comments on commit 12a9749

Please sign in to comment.