Skip to content
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

Adds Aspect ratio control on Image blocks in Grids #62891

Merged
merged 6 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 97 additions & 89 deletions packages/block-editor/src/components/dimensions-tool/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ function DimensionsTool( {
scaleOptions, // Default options handled by ScaleTool.
defaultScale = 'fill', // Match CSS default value for object-fit.
unitsOptions, // Default options handled by UnitControl.
tools = [ 'aspectRatio', 'widthHeight', 'scale' ],
} ) {
// Coerce undefined and CSS default values to be null.
const width =
Expand Down Expand Up @@ -92,95 +93,102 @@ function DimensionsTool( {

return (
<>
<AspectRatioTool
panelId={ panelId }
options={ aspectRatioOptions }
defaultValue={ defaultAspectRatio }
value={ aspectRatioValue }
onChange={ ( nextAspectRatio ) => {
const nextValue = { ...value };

// 'auto' is CSS default, so it gets treated as null.
nextAspectRatio =
nextAspectRatio === 'auto' ? null : nextAspectRatio;

setLastAspectRatio( nextAspectRatio );

// Update aspectRatio.
if ( ! nextAspectRatio ) {
delete nextValue.aspectRatio;
} else {
nextValue.aspectRatio = nextAspectRatio;
}

// Auto-update scale.
if ( ! nextAspectRatio ) {
delete nextValue.scale;
} else if ( lastScale ) {
nextValue.scale = lastScale;
} else {
nextValue.scale = defaultScale;
setLastScale( defaultScale );
}

// Auto-update width and height.
if ( 'custom' !== nextAspectRatio && width && height ) {
delete nextValue.height;
}

onChange( nextValue );
} }
/>
<WidthHeightTool
panelId={ panelId }
units={ unitsOptions }
value={ { width, height } }
onChange={ ( { width: nextWidth, height: nextHeight } ) => {
const nextValue = { ...value };

// 'auto' is CSS default, so it gets treated as null.
nextWidth = nextWidth === 'auto' ? null : nextWidth;
nextHeight = nextHeight === 'auto' ? null : nextHeight;

// Update width.
if ( ! nextWidth ) {
delete nextValue.width;
} else {
nextValue.width = nextWidth;
}

// Update height.
if ( ! nextHeight ) {
delete nextValue.height;
} else {
nextValue.height = nextHeight;
}

// Auto-update aspectRatio.
if ( nextWidth && nextHeight ) {
delete nextValue.aspectRatio;
} else if ( lastAspectRatio ) {
nextValue.aspectRatio = lastAspectRatio;
} else {
// No setting defaultAspectRatio here, because
// aspectRatio is optional in this scenario,
// unlike scale.
}

// Auto-update scale.
if ( ! lastAspectRatio && !! nextWidth !== !! nextHeight ) {
delete nextValue.scale;
} else if ( lastScale ) {
nextValue.scale = lastScale;
} else {
nextValue.scale = defaultScale;
setLastScale( defaultScale );
}

onChange( nextValue );
} }
/>
{ showScaleControl && (
{ tools.includes( 'aspectRatio' ) && (
<AspectRatioTool
panelId={ panelId }
options={ aspectRatioOptions }
defaultValue={ defaultAspectRatio }
value={ aspectRatioValue }
onChange={ ( nextAspectRatio ) => {
const nextValue = { ...value };

// 'auto' is CSS default, so it gets treated as null.
nextAspectRatio =
nextAspectRatio === 'auto' ? null : nextAspectRatio;

setLastAspectRatio( nextAspectRatio );

// Update aspectRatio.
if ( ! nextAspectRatio ) {
delete nextValue.aspectRatio;
} else {
nextValue.aspectRatio = nextAspectRatio;
}

// Auto-update scale.
if ( ! nextAspectRatio ) {
delete nextValue.scale;
} else if ( lastScale ) {
nextValue.scale = lastScale;
} else {
nextValue.scale = defaultScale;
setLastScale( defaultScale );
}

// Auto-update width and height.
if ( 'custom' !== nextAspectRatio && width && height ) {
delete nextValue.height;
}

onChange( nextValue );
} }
/>
) }
{ tools.includes( 'widthHeight' ) && (
<WidthHeightTool
panelId={ panelId }
units={ unitsOptions }
value={ { width, height } }
onChange={ ( { width: nextWidth, height: nextHeight } ) => {
const nextValue = { ...value };

// 'auto' is CSS default, so it gets treated as null.
nextWidth = nextWidth === 'auto' ? null : nextWidth;
nextHeight = nextHeight === 'auto' ? null : nextHeight;

// Update width.
if ( ! nextWidth ) {
delete nextValue.width;
} else {
nextValue.width = nextWidth;
}

// Update height.
if ( ! nextHeight ) {
delete nextValue.height;
} else {
nextValue.height = nextHeight;
}

// Auto-update aspectRatio.
if ( nextWidth && nextHeight ) {
delete nextValue.aspectRatio;
} else if ( lastAspectRatio ) {
nextValue.aspectRatio = lastAspectRatio;
} else {
// No setting defaultAspectRatio here, because
// aspectRatio is optional in this scenario,
// unlike scale.
}

// Auto-update scale.
if (
! lastAspectRatio &&
!! nextWidth !== !! nextHeight
) {
delete nextValue.scale;
} else if ( lastScale ) {
nextValue.scale = lastScale;
} else {
nextValue.scale = defaultScale;
setLastScale( defaultScale );
}

onChange( nextValue );
} }
/>
) }
{ tools.includes( 'scale' ) && showScaleControl && (
<ScaleTool
panelId={ panelId }
options={ scaleOptions }
Expand Down
29 changes: 24 additions & 5 deletions packages/block-library/src/image/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,7 @@ export default function Image( {
allowResize &&
hasNonContentControls &&
! isWideAligned &&
isLargeViewport &&
parentLayoutType !== 'grid';
isLargeViewport;
const imageSizeOptions = imageSizes
.filter(
( { slug } ) => image?.media_details?.sizes?.[ slug ]?.source_url
Expand Down Expand Up @@ -405,6 +404,20 @@ export default function Image( {
/>
);

const aspectRatioControl = (
<DimensionsTool
value={ { aspectRatio } }
onChange={ ( { aspectRatio: newAspectRatio } ) => {
setAttributes( {
aspectRatio: newAspectRatio,
scale: 'cover',
} );
} }
defaultAspectRatio="auto"
tools={ [ 'aspectRatio' ] }
/>
);

const resetAll = () => {
setAttributes( {
alt: undefined,
Expand All @@ -423,7 +436,10 @@ export default function Image( {
resetAll={ resetAll }
dropdownMenuProps={ dropdownMenuProps }
>
{ isResizable && dimensionsControl }
{ isResizable &&
( parentLayoutType === 'grid'
? aspectRatioControl
: dimensionsControl ) }
</ToolsPanel>
</InspectorControls>
);
Expand Down Expand Up @@ -738,7 +754,10 @@ export default function Image( {
/>
</ToolsPanelItem>
) }
{ isResizable && dimensionsControl }
{ isResizable &&
( parentLayoutType === 'grid'
? aspectRatioControl
: dimensionsControl ) }
{ !! imageSizeOptions.length && (
<ResolutionTool
value={ sizeSlug }
Expand Down Expand Up @@ -848,7 +867,7 @@ export default function Image( {
/>
</ImageWrapper>
);
} else if ( ! isResizable ) {
} else if ( ! isResizable || parentLayoutType === 'grid' ) {
img = (
<div style={ { width, height, aspectRatio } }>
<ImageWrapper href={ href }>{ img }</ImageWrapper>
Expand Down
Loading