diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index da0ba4d1b3ff32..01db98978c1088 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -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 diff --git a/packages/components/src/z-stack/component.tsx b/packages/components/src/z-stack/component.tsx index 1cbcac56e4fb70..e087f8536e3401 100644 --- a/packages/components/src/z-stack/component.tsx +++ b/packages/components/src/z-stack/component.tsx @@ -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 ( { clonedChildren } diff --git a/packages/components/src/z-stack/stories/index.tsx b/packages/components/src/z-stack/stories/index.tsx index b04e19962aed15..9b0b0803780339 100644 --- a/packages/components/src/z-stack/stories/index.tsx +++ b/packages/components/src/z-stack/stories/index.tsx @@ -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 '..'; @@ -55,18 +54,12 @@ const Avatar = ( { const Template: ComponentStory< typeof ZStack > = ( args ) => { return ( - - - - - - - - - - - - + + + + + + ); }; diff --git a/packages/components/src/z-stack/styles.ts b/packages/components/src/z-stack/styles.ts index d0bf20d38b1f4c..186f268e643663 100644 --- a/packages/components/src/z-stack/styles.ts +++ b/packages/components/src/z-stack/styles.ts @@ -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 }; + } `;