Skip to content

Commit

Permalink
Image: Add border block support for color, width, and style (#31366)
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronrobertshaw authored Jul 15, 2022
1 parent c5b4c11 commit c1d065f
Show file tree
Hide file tree
Showing 18 changed files with 258 additions and 48 deletions.
12 changes: 9 additions & 3 deletions packages/block-editor/src/components/image-editor/cropper.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default function ImageCropper( {
clientWidth,
naturalHeight,
naturalWidth,
borderProps,
} ) {
const {
isInProgress,
Expand All @@ -44,10 +45,15 @@ export default function ImageCropper( {

return (
<div
className={ classnames( 'wp-block-image__crop-area', {
'is-applying': isInProgress,
} ) }
className={ classnames(
'wp-block-image__crop-area',
borderProps?.className,
{
'is-applying': isInProgress,
}
) }
style={ {
...borderProps?.style,
width: width || clientWidth,
height: editedHeight,
} }
Expand Down
2 changes: 2 additions & 0 deletions packages/block-editor/src/components/image-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ export default function ImageEditor( {
clientWidth,
naturalHeight,
naturalWidth,
borderProps,
} ) {
return (
<>
<Cropper
borderProps={ borderProps }
url={ url }
width={ width }
height={ height }
Expand Down
11 changes: 10 additions & 1 deletion packages/block-library/src/gallery/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ figure.wp-block-gallery.has-nested-images {
position: relative;
flex-direction: column;
max-width: 100%;
// Prevents theme.json and global styles borders that apply to the outer
// wrapper from incorrectly enlarging gallery images to a point they
// result in a single column gallery.
box-sizing: border-box;

> div,
> a {
Expand Down Expand Up @@ -63,7 +67,12 @@ figure.wp-block-gallery.has-nested-images {
}
}

&.is-style-rounded {
&.has-custom-border img {
box-sizing: border-box;
}

&.is-style-rounded,
&.has-custom-border {
> div,
> a {
flex: 1 1 auto;
Expand Down
8 changes: 7 additions & 1 deletion packages/block-library/src/image/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,15 @@
"background": false
},
"__experimentalBorder": {
"color": true,
"radius": true,
"width": true,
"__experimentalSelector": "img, .wp-block-image__crop-area",
"__experimentalSkipSerialization": true,
"__experimentalDefaultControls": {
"radius": true
"color": true,
"radius": true,
"width": true
}
},
"__experimentalStyle": {
Expand Down
86 changes: 86 additions & 0 deletions packages/block-library/src/image/deprecated.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ const blockAttributes = {
source: 'html',
selector: 'figcaption',
},
title: {
type: 'string',
source: 'attribute',
selector: 'img',
attribute: 'title',
},
href: {
type: 'string',
source: 'attribute',
Expand Down Expand Up @@ -58,6 +64,9 @@ const blockAttributes = {
height: {
type: 'number',
},
sizeSlug: {
type: 'string',
},
linkDestination: {
type: 'string',
},
Expand Down Expand Up @@ -85,6 +94,83 @@ const blockSupports = {
};

const deprecated = [
// The following deprecation moves existing border radius styles onto the
// inner img element where new border block support styles must be applied.
// It will also add a new `.has-custom-border` class for existing blocks
// with border radii set. This class is required to improve caption position
// and styling when an image within a gallery has a custom border or
// rounded corners.
//
// See: https://github.com/WordPress/gutenberg/pull/31366/
{
attributes: blockAttributes,
supports: blockSupports,
save( { attributes } ) {
const {
url,
alt,
caption,
align,
href,
rel,
linkClass,
width,
height,
id,
linkTarget,
sizeSlug,
title,
} = attributes;

const newRel = isEmpty( rel ) ? undefined : rel;

const classes = classnames( {
[ `align${ align }` ]: align,
[ `size-${ sizeSlug }` ]: sizeSlug,
'is-resized': width || height,
} );

const image = (
<img
src={ url }
alt={ alt }
className={ id ? `wp-image-${ id }` : null }
width={ width }
height={ height }
title={ title }
/>
);

const figure = (
<>
{ href ? (
<a
className={ linkClass }
href={ href }
target={ linkTarget }
rel={ newRel }
>
{ image }
</a>
) : (
image
) }
{ ! RichText.isEmpty( caption ) && (
<RichText.Content
tagName="figcaption"
value={ caption }
/>
) }
</>
);

return (
<figure { ...useBlockProps.save( { className: classes } ) }>
{ figure }
</figure>
);
},
},
{
attributes: {
...blockAttributes,
Expand Down
7 changes: 6 additions & 1 deletion packages/block-library/src/image/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* External dependencies
*/
import classnames from 'classnames';
import { get, has, omit, pick } from 'lodash';
import { get, has, isEmpty, omit, pick } from 'lodash';

/**
* WordPress dependencies
Expand All @@ -17,6 +17,7 @@ import {
MediaPlaceholder,
useBlockProps,
store as blockEditorStore,
__experimentalUseBorderProps as useBorderProps,
} from '@wordpress/block-editor';
import { useEffect, useRef, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
Expand Down Expand Up @@ -296,10 +297,14 @@ export function ImageEdit( {
/>
);

const borderProps = useBorderProps( attributes );

const classes = classnames( className, {
'is-transient': temporaryURL,
'is-resized': !! width || !! height,
[ `size-${ sizeSlug }` ]: sizeSlug,
'has-custom-border':
!! borderProps.className || ! isEmpty( borderProps.style ),
} );

const blockProps = useBlockProps( {
Expand Down
13 changes: 9 additions & 4 deletions packages/block-library/src/image/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ figure.wp-block-image:not(.wp-block) {
margin-top: -9px;
margin-left: -9px;
}

&:not(.is-style-rounded) > div:not(.components-placeholder) {
border-radius: inherit;
}
}

// This is necessary for the editor resize handles to accurately work on a non-floated, non-resized, small image.
Expand Down Expand Up @@ -94,6 +90,15 @@ figure.wp-block-image:not(.wp-block) {
position: relative;
max-width: 100%;
width: 100%;
overflow: hidden;

// This removes the border from the img within the image cropper so it
// can be applied to the cropper itself. This then allows the image to be
// cropped within the visual border providing more accurate editing and
// smoother UX.
.reactEasyCrop_Container .reactEasyCrop_Image {
border: none;
}
}

.wp-block-image__crop-icon {
Expand Down
42 changes: 26 additions & 16 deletions packages/block-library/src/image/image.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { get, filter, map, pick, includes } from 'lodash';
import { get, filter, isEmpty, map, pick, includes } from 'lodash';

/**
* WordPress dependencies
Expand Down Expand Up @@ -30,6 +30,7 @@ import {
__experimentalImageEditor as ImageEditor,
__experimentalImageEditingProvider as ImageEditingProvider,
__experimentalGetElementClassName,
__experimentalUseBorderProps as useBorderProps,
} from '@wordpress/block-editor';
import { useEffect, useMemo, useState, useRef } from '@wordpress/element';
import { __, sprintf, isRTL } from '@wordpress/i18n';
Expand Down Expand Up @@ -57,7 +58,19 @@ import { MIN_SIZE, ALLOWED_MEDIA_TYPES } from './constants';

export default function Image( {
temporaryURL,
attributes: {
attributes,
setAttributes,
isSelected,
insertBlocksAfter,
onReplace,
onSelectImage,
onSelectURL,
onUploadError,
containerRef,
context,
clientId,
} ) {
const {
url = '',
alt,
caption,
Expand All @@ -72,18 +85,7 @@ export default function Image( {
height,
linkTarget,
sizeSlug,
},
setAttributes,
isSelected,
insertBlocksAfter,
onReplace,
onSelectImage,
onSelectURL,
onUploadError,
containerRef,
context,
clientId,
} ) {
} = attributes;
const imageRef = useRef();
const captionRef = useRef();
const prevUrl = usePrevious( url );
Expand Down Expand Up @@ -186,7 +188,7 @@ export default function Image( {

// Get naturalWidth and naturalHeight from image ref, and fall back to loaded natural
// width and height. This resolves an issue in Safari where the loaded natural
// witdth and height is otherwise lost when switching between alignments.
// width and height is otherwise lost when switching between alignments.
// See: https://github.com/WordPress/gutenberg/pull/37210.
const { naturalWidth, naturalHeight } = useMemo( () => {
return {
Expand Down Expand Up @@ -429,6 +431,11 @@ export default function Image( {
defaultedAlt = __( 'This image has an empty alt attribute' );
}

const borderProps = useBorderProps( attributes );
const isRounded = attributes.className?.includes( 'is-style-rounded' );
const hasCustomBorder =
!! borderProps.className || ! isEmpty( borderProps.style );

let img = (
// Disable reason: Image itself is not meant to be interactive, but
// should direct focus to block.
Expand All @@ -445,6 +452,8 @@ export default function Image( {
} );
} }
ref={ imageRef }
className={ borderProps.className }
style={ borderProps.style }
/>
{ temporaryURL && <Spinner /> }
</>
Expand All @@ -466,6 +475,7 @@ export default function Image( {
if ( canEditImage && isEditingImage ) {
img = (
<ImageEditor
borderProps={ isRounded ? undefined : borderProps }
url={ url }
width={ width }
height={ height }
Expand Down Expand Up @@ -530,7 +540,7 @@ export default function Image( {
<ResizableBox
size={ {
width: width ?? 'auto',
height: height ?? 'auto',
height: height && ! hasCustomBorder ? height : 'auto',
} }
showHandle={ isSelected }
minWidth={ minWidth }
Expand Down
11 changes: 10 additions & 1 deletion packages/block-library/src/image/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
RichText,
useBlockProps,
__experimentalGetElementClassName,
__experimentalGetBorderClassesAndStyles as getBorderClassesAndStyles,
} from '@wordpress/block-editor';

export default function save( { attributes } ) {
Expand All @@ -31,18 +32,26 @@ export default function save( { attributes } ) {
} = attributes;

const newRel = isEmpty( rel ) ? undefined : rel;
const borderProps = getBorderClassesAndStyles( attributes );

const classes = classnames( {
[ `align${ align }` ]: align,
[ `size-${ sizeSlug }` ]: sizeSlug,
'is-resized': width || height,
'has-custom-border':
!! borderProps.className || ! isEmpty( borderProps.style ),
} );

const imageClasses = classnames( borderProps.className, {
[ `wp-image-${ id }` ]: !! id,
} );

const image = (
<img
src={ url }
alt={ alt }
className={ id ? `wp-image-${ id }` : null }
className={ imageClasses || undefined }
style={ borderProps.style }
width={ width }
height={ height }
title={ title }
Expand Down
Loading

0 comments on commit c1d065f

Please sign in to comment.