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

Block Support: Update border support to allow non-pixel units #31483

Merged
merged 8 commits into from
Jun 7, 2021
20 changes: 16 additions & 4 deletions lib/block-supports/border.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,14 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {
gutenberg_has_border_feature_support( $block_type, 'radius' ) &&
isset( $block_attributes['style']['border']['radius'] )
) {
$border_radius = (int) $block_attributes['style']['border']['radius'];
$styles[] = sprintf( 'border-radius: %dpx;', $border_radius );
$border_radius = $block_attributes['style']['border']['radius'];

// This check handles original unitless implementation.
if ( is_numeric( $border_radius ) ) {
$border_radius .= 'px';
}

$styles[] = sprintf( 'border-radius: %s;', $border_radius );
}

// Border style.
Expand All @@ -74,8 +80,14 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {
gutenberg_has_border_feature_support( $block_type, 'width' ) &&
isset( $block_attributes['style']['border']['width'] )
) {
$border_width = intval( $block_attributes['style']['border']['width'] );
$styles[] = sprintf( 'border-width: %dpx;', $border_width );
$border_width = $block_attributes['style']['border']['width'];

// This check handles original unitless implementation.
if ( is_numeric( $border_width ) ) {
$border_width .= 'px';
}

$styles[] = sprintf( 'border-width: %s;', $border_width );
}

// Border color.
Expand Down
24 changes: 17 additions & 7 deletions packages/block-editor/src/hooks/border-radius.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
/**
* WordPress dependencies
*/
import { RangeControl } from '@wordpress/components';
import { __experimentalUnitControl as UnitControl } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { CSS_UNITS, parseUnit } from './border';
import { cleanEmptyObject } from './utils';

const MIN_BORDER_RADIUS_VALUE = 0;
const MAX_BORDER_RADIUS_VALUE = 50;

/**
* Inspector control panel containing the border radius related configuration.
Expand All @@ -24,6 +25,15 @@ export function BorderRadiusEdit( props ) {
setAttributes,
} = props;

// Step value is maintained in state so step is appropriate for current unit
// even when current radius value is undefined.
const initialStep = parseUnit( style?.border?.radius ) === 'px' ? 1 : 0.25;
const [ step, setStep ] = useState( initialStep );

const onUnitChange = ( newUnit ) => {
setStep( newUnit === 'px' ? 1 : 0.25 );
};

const onChange = ( newRadius ) => {
let newStyle = {
...style,
Expand All @@ -33,22 +43,22 @@ export function BorderRadiusEdit( props ) {
},
};

if ( newRadius === undefined ) {
if ( newRadius === undefined || newRadius === '' ) {
newStyle = cleanEmptyObject( newStyle );
}

setAttributes( { style: newStyle } );
};

return (
<RangeControl
<UnitControl
value={ style?.border?.radius }
label={ __( 'Border radius' ) }
min={ MIN_BORDER_RADIUS_VALUE }
max={ MAX_BORDER_RADIUS_VALUE }
initialPosition={ 0 }
allowReset
onChange={ onChange }
onUnitChange={ onUnitChange }
step={ step }
units={ CSS_UNITS }
/>
);
}
30 changes: 22 additions & 8 deletions packages/block-editor/src/hooks/border-width.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
/**
* WordPress dependencies
*/
import { RangeControl } from '@wordpress/components';
import { __experimentalUnitControl as UnitControl } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { CSS_UNITS, parseUnit } from './border';
import { cleanEmptyObject } from './utils';

const MIN_BORDER_WIDTH = 0;
const MAX_BORDER_WIDTH = 50;
aaronrobertshaw marked this conversation as resolved.
Show resolved Hide resolved

/**
* Inspector control for configuring border width property.
Expand All @@ -24,27 +25,40 @@ export const BorderWidthEdit = ( props ) => {
setAttributes,
} = props;

// Step value is maintained in state so step is appropriate for current unit
// even when current radius value is undefined.
const initialStep = parseUnit( style?.border?.width ) === 'px' ? 1 : 0.25;
const [ step, setStep ] = useState( initialStep );

const onUnitChange = ( newUnit ) => {
setStep( newUnit === 'px' ? 1 : 0.25 );
};

const onChange = ( newWidth ) => {
const newStyle = {
let newStyle = {
...style,
border: {
...style?.border,
width: newWidth,
},
};

setAttributes( { style: cleanEmptyObject( newStyle ) } );
if ( newWidth === undefined || newWidth === '' ) {
aaronrobertshaw marked this conversation as resolved.
Show resolved Hide resolved
newStyle = cleanEmptyObject( newStyle );
}

setAttributes( { style: newStyle } );
};

return (
<RangeControl
<UnitControl
value={ style?.border?.width }
label={ __( 'Border width' ) }
min={ MIN_BORDER_WIDTH }
max={ MAX_BORDER_WIDTH }
initialPosition={ 0 }
allowReset
onChange={ onChange }
onUnitChange={ onUnitChange }
step={ step }
units={ CSS_UNITS }
/>
);
};
43 changes: 42 additions & 1 deletion packages/block-editor/src/hooks/border.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,44 @@ import { BorderRadiusEdit } from './border-radius';
import { BorderStyleEdit } from './border-style';
import { BorderWidthEdit } from './border-width';

const isWeb = Platform.OS === 'web';

export const BORDER_SUPPORT_KEY = '__experimentalBorder';
export const CSS_UNITS = [
aaronrobertshaw marked this conversation as resolved.
Show resolved Hide resolved
{
value: 'px',
label: isWeb ? 'px' : __( 'Pixels (px)' ),
default: '',
a11yLabel: __( 'Pixels (px)' ),
},
{
value: 'em',
label: isWeb ? 'em' : __( 'Relative to parent font size (em)' ),
default: '',
a11yLabel: __( 'Relative to parent font size (em)' ),
},
{
value: 'rem',
label: isWeb ? 'rem' : __( 'Relative to root font size (rem)' ),
default: '',
a11yLabel: __( 'Relative to root font size (rem)' ),
},
aaronrobertshaw marked this conversation as resolved.
Show resolved Hide resolved
];

/**
* Parses a CSS unit from a border CSS value.
*
* @param {string} cssValue CSS value to parse e.g. `10px` or `1.5em`.
* @return {string} CSS unit from provided value or default 'px'.
*/
export function parseUnit( cssValue ) {
const value = String( cssValue ).trim();
const unitMatch = value.match( /[\d.\-\+]*\s*(.*)/ )[ 1 ];
const unit = unitMatch !== undefined ? unitMatch.toLowerCase() : '';
const currentUnit = CSS_UNITS.find( ( item ) => item.value === unit );

return currentUnit?.value || 'px';
}

export function BorderPanel( props ) {
const isDisabled = useIsBorderDisabled( props );
Expand Down Expand Up @@ -44,7 +81,11 @@ export function BorderPanel( props ) {

return (
<InspectorControls>
<PanelBody title={ __( 'Border settings' ) } initialOpen={ false }>
<PanelBody
className="block-editor-hooks__border-controls"
title={ __( 'Border settings' ) }
initialOpen={ false }
>
{ isStyleSupported && <BorderStyleEdit { ...props } /> }
{ isWidthSupported && <BorderWidthEdit { ...props } /> }
{ isRadiusSupported && <BorderRadiusEdit { ...props } /> }
Expand Down
10 changes: 10 additions & 0 deletions packages/block-editor/src/hooks/border.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.block-editor-hooks__border-controls {
.components-unit-control-wrapper {
margin-bottom: $grid-unit-30;

&:last-child {
margin-bottom: $grid-unit-10;
}
}
}

8 changes: 4 additions & 4 deletions packages/block-editor/src/hooks/test/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ describe( 'getInlineStyles', () => {
color: { text: 'red', background: 'black' },
typography: { lineHeight: 1.5, fontSize: 10 },
border: {
radius: 10,
width: 3,
radius: '10px',
width: '1em',
style: 'dotted',
color: '#21759b',
},
Expand All @@ -31,9 +31,9 @@ describe( 'getInlineStyles', () => {
).toEqual( {
backgroundColor: 'black',
borderColor: '#21759b',
borderRadius: 10,
borderRadius: '10px',
borderStyle: 'dotted',
borderWidth: 3,
borderWidth: '1em',
color: 'red',
lineHeight: 1.5,
fontSize: 10,
Expand Down
1 change: 1 addition & 0 deletions packages/block-editor/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
@import "./components/warning/style.scss";
@import "./hooks/anchor.scss";
@import "./hooks/layout.scss";
@import "./hooks/border.scss";

// This tag marks the end of the styles that apply to editing canvas contents and need to be manipulated when we resize the editor.
#end-resizable-editor-section {
Expand Down
4 changes: 1 addition & 3 deletions packages/block-library/src/button/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,7 @@ function ButtonEdit( props ) {
}
) }
style={ {
borderRadius: borderRadius
? borderRadius + 'px'
: undefined,
borderRadius: borderRadius ? borderRadius : undefined,
...colorProps.style,
} }
onSplit={ ( value ) =>
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/button/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default function save( { attributes, className } ) {
}
);
const buttonStyle = {
borderRadius: borderRadius ? borderRadius + 'px' : undefined,
borderRadius: borderRadius ? borderRadius : undefined,
...colorProps.style,
};

Expand Down
14 changes: 10 additions & 4 deletions packages/block-library/src/search/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {

// Used to calculate border radius adjustment to avoid "fat" corners when
// button is placed inside wrapper.
const DEFAULT_INNER_PADDING = 4;
const DEFAULT_INNER_PADDING = '4px';

export default function SearchEdit( {
className,
Expand Down Expand Up @@ -323,10 +323,16 @@ export default function SearchEdit( {
if ( 'button-inside' === buttonPosition && style?.border?.radius ) {
// We have button inside wrapper and a border radius value to apply.
// Add default padding so we don't get "fat" corners.
const outerRadius =
parseInt( style?.border?.radius, 10 ) + DEFAULT_INNER_PADDING;
//
// CSS calc() is used here to support non-pixel units. The inline
// style using calc() will only apply if both values have units.
const radius = Number.isInteger( borderRadius )
? `${ borderRadius }px`
: borderRadius;

return { borderRadius: `${ outerRadius }px` };
return {
borderRadius: `calc(${ radius } + ${ DEFAULT_INNER_PADDING })`,
};
}

return undefined;
Expand Down
14 changes: 9 additions & 5 deletions packages/block-library/src/search/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ function styles_for_block_core_search( $attributes ) {
if ( $has_border_radius ) {
// Shared style for button and input radius values.
$border_radius = $attributes['style']['border']['radius'];
$shared_styles[] = sprintf( 'border-radius: %spx;', esc_attr( $border_radius ) );
$border_radius = is_numeric( $border_radius ) ? $border_radius . 'px' : $border_radius;
$shared_styles[] = sprintf( 'border-radius: %s;', esc_attr( $border_radius ) );

// Apply wrapper border radius if button placed inside.
$button_inside = ! empty( $attributes['buttonPosition'] ) &&
Expand All @@ -199,10 +200,13 @@ function styles_for_block_core_search( $attributes ) {
if ( $button_inside ) {
// We adjust the border radius value for the outer wrapper element
// to make it visually consistent with the radius applied to inner
// elements.
$default_padding = 4;
$adjusted_radius = $border_radius + $default_padding;
$wrapper_styles[] = sprintf( 'border-radius: %dpx;', esc_attr( $adjusted_radius ) );
// elements. calc() is used to support non-pixel CSS units.
$default_padding = '4px';
$wrapper_styles[] = sprintf(
'border-radius: calc(%s + %s);',
esc_attr( $border_radius ),
esc_attr( $default_padding )
);
}
}

Expand Down