-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adapt flex child controls for Spacer. #49362
Changes from 6 commits
b833bff
c709721
e3d1364
7d751d2
de0f39b
adcc4f8
f64baf7
8f1c8f9
1a3623c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,13 +92,20 @@ const SpacerEdit = ( { | |
} ); | ||
const { orientation } = context; | ||
const { orientation: parentOrientation, type } = parentLayout || {}; | ||
// Check if the spacer is inside a flex container. | ||
const isFlexLayout = type === 'flex'; | ||
// If the spacer is inside a flex container, it should either inherit the orientation | ||
// of the parent or use the flex default orientation. | ||
const inheritedOrientation = | ||
! parentOrientation && type === 'flex' | ||
! parentOrientation && isFlexLayout | ||
? 'horizontal' | ||
: parentOrientation || orientation; | ||
const { height, width } = attributes; | ||
const { height, width, style: blockStyle = {} } = attributes; | ||
|
||
const { layout = {} } = blockStyle; | ||
const { selfStretch, flexSize } = layout; | ||
|
||
const hasFlexSize = !! flexSize; | ||
|
||
const [ isResizing, setIsResizing ] = useState( false ); | ||
const [ temporaryHeight, setTemporaryHeight ] = useState( null ); | ||
|
@@ -110,32 +117,84 @@ const SpacerEdit = ( { | |
const handleOnVerticalResizeStop = ( newHeight ) => { | ||
onResizeStop(); | ||
|
||
if ( isFlexLayout || hasFlexSize ) { | ||
setAttributes( { | ||
style: { | ||
...blockStyle, | ||
layout: { | ||
...layout, | ||
flexSize: newHeight, | ||
selfStretch: 'fixed', | ||
}, | ||
}, | ||
} ); | ||
} | ||
|
||
setAttributes( { height: newHeight } ); | ||
setTemporaryHeight( null ); | ||
}; | ||
|
||
const handleOnHorizontalResizeStop = ( newWidth ) => { | ||
onResizeStop(); | ||
|
||
if ( isFlexLayout || hasFlexSize ) { | ||
setAttributes( { | ||
style: { | ||
...blockStyle, | ||
layout: { | ||
...layout, | ||
flexSize: newWidth, | ||
selfStretch: 'fixed', | ||
}, | ||
}, | ||
} ); | ||
} | ||
|
||
setAttributes( { width: newWidth } ); | ||
setTemporaryWidth( null ); | ||
}; | ||
|
||
const getHeightForVerticalBlocks = () => { | ||
if ( isFlexLayout && selfStretch === 'fit' ) { | ||
return undefined; | ||
} else if ( isFlexLayout && flexSize ) { | ||
return temporaryHeight || flexSize; | ||
} | ||
return temporaryHeight || getSpacingPresetCssVar( height ) || undefined; | ||
}; | ||
|
||
const getWidthForHorizontalBlocks = () => { | ||
if ( isFlexLayout && selfStretch === 'fit' ) { | ||
return undefined; | ||
} else if ( isFlexLayout && flexSize ) { | ||
return temporaryWidth || flexSize; | ||
} | ||
return temporaryWidth || getSpacingPresetCssVar( width ) || undefined; | ||
}; | ||
|
||
const sizeConditionalOnOrientation = | ||
inheritedOrientation === 'horizontal' | ||
? getWidthForHorizontalBlocks() | ||
: getHeightForVerticalBlocks(); | ||
|
||
const style = { | ||
height: | ||
inheritedOrientation === 'horizontal' | ||
? 24 | ||
: temporaryHeight || | ||
getSpacingPresetCssVar( height ) || | ||
undefined, | ||
: getHeightForVerticalBlocks(), | ||
width: | ||
inheritedOrientation === 'horizontal' | ||
? temporaryWidth || getSpacingPresetCssVar( width ) || undefined | ||
? getWidthForHorizontalBlocks() | ||
: undefined, | ||
// In vertical flex containers, the spacer shrinks to nothing without a minimum width. | ||
minWidth: | ||
inheritedOrientation === 'vertical' && type === 'flex' | ||
inheritedOrientation === 'vertical' && isFlexLayout | ||
? 48 | ||
: undefined, | ||
// Add flex-basis so temporary sizes are respected. | ||
flexBasis: isFlexLayout ? sizeConditionalOnOrientation : undefined, | ||
// Remove flex-grow when resizing. | ||
flexGrow: isFlexLayout && isResizing ? 0 : undefined, | ||
}; | ||
|
||
const resizableBoxWithOrientation = ( blockOrientation ) => { | ||
|
@@ -197,7 +256,51 @@ const SpacerEdit = ( { | |
width: '72px', | ||
} ); | ||
} | ||
}, [] ); | ||
if ( | ||
isFlexLayout && | ||
selfStretch !== 'fill' && | ||
selfStretch !== 'fit' && | ||
! flexSize | ||
) { | ||
const newSize = | ||
inheritedOrientation === 'horizontal' | ||
? getSpacingPresetCssVar( width ) || '72px' | ||
: getSpacingPresetCssVar( height ) || '100px'; | ||
setAttributes( { | ||
style: { | ||
...blockStyle, | ||
layout: { | ||
...layout, | ||
flexSize: newSize, | ||
selfStretch: 'fixed', | ||
}, | ||
}, | ||
} ); | ||
} else if ( | ||
isFlexLayout && | ||
( selfStretch === 'fill' || selfStretch === 'fit' ) | ||
) { | ||
if ( inheritedOrientation === 'horizontal' ) { | ||
setAttributes( { | ||
width: '0px', | ||
} ); | ||
} else { | ||
setAttributes( { | ||
height: '0px', | ||
} ); | ||
} | ||
} | ||
}, [ | ||
blockStyle, | ||
flexSize, | ||
height, | ||
inheritedOrientation, | ||
isFlexLayout, | ||
layout, | ||
selfStretch, | ||
setAttributes, | ||
width, | ||
] ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean that the logic here will be called more frequently now? And if so, is that a safe change? From a quick skim it sounds like it's intentional for it to be called more frequently, but I wasn't sure if there's a potential state it could get in where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that's a good point, I'm not 100% sure there won't be nefarious side effects. I mainly added the dependencies in because the linter was complaining about it 😅 and it didn't seem to do any harm, but negative perf impacts often don't show immediately. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update: I tried removing them and ended up re-adding as the effect wasn't running when a Spacer changed to "fit" or "fill" and the old width/height value was still showing up when dragging outside of the flex container. It doesn't seem to hugely increase the times the effect runs though I might easily be missing some edge case situations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In practice, I don't think I've encountered any issues with this list of dependencies so far. It might just be something for us to keep an eye on if anyone runs into any issues with the spacer? |
||
|
||
return ( | ||
<> | ||
|
@@ -211,13 +314,15 @@ const SpacerEdit = ( { | |
> | ||
{ resizableBoxWithOrientation( inheritedOrientation ) } | ||
</View> | ||
<SpacerControls | ||
setAttributes={ setAttributes } | ||
height={ temporaryHeight || height } | ||
width={ temporaryWidth || width } | ||
orientation={ inheritedOrientation } | ||
isResizing={ isResizing } | ||
/> | ||
{ ! isFlexLayout && ( | ||
<SpacerControls | ||
setAttributes={ setAttributes } | ||
height={ temporaryHeight || height } | ||
width={ temporaryWidth || width } | ||
orientation={ inheritedOrientation } | ||
isResizing={ isResizing } | ||
/> | ||
) } | ||
</> | ||
); | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be working a bit better now, but it looks like there's still a couple of issues when dragging a Spacer block in and out of a flex container. Here's a quick gif:
I'm not too sure what's happening, unfortunately I've found it a little hard to figure out, but my observations so far are:
px
value doesn't appear to populate the Fixed input fieldThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not converting, so the input doesn't understand the value of the preset. Perhaps we should make it possible to set preset sizes in the child layout controls; I'm sure it would be useful outside of this scenario?
Oooh well spotted! We're alternately setting
height
andflexSize
and not changing either of them when setting the other, so the block attributes end up something like:{"height":"var:preset|spacing|40","style":{"layout":{"flexSize":"130px","selfStretch":"fixed"}}}
. I'll look into it!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I think I'm following along now. I like the idea of adding support for presets for the child layout controls, but I wonder if we'd ultimately want a different scale for size presets than spacing, given that width and height values will often need to be much bigger than spacing between things?
For now, what do you think about potentially using
getCustomValueFromPreset
instead ofgetSpacingPresetCssVar
so that when dragging from outside a Row / Stack block into one of them, we switch to using the real pixel value?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's a great point! I'll convert to px for now.