Skip to content
Closed
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
9 changes: 7 additions & 2 deletions lib/block-supports/border.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,14 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {
}
}

// Border width support is enforced if border style support is opted into.
$has_border_style_support = gutenberg_has_border_feature_support( $block_type, 'style' );
$has_border_width_support = $has_border_style_support ||
gutenberg_has_border_feature_support( $block_type, 'width' );

// Border style.
if (
gutenberg_has_border_feature_support( $block_type, 'style' ) &&
$has_border_style_support &&
isset( $block_attributes['style']['border']['style'] )
) {
$border_style = $block_attributes['style']['border']['style'];
Expand All @@ -86,7 +91,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {

// Border width.
if (
gutenberg_has_border_feature_support( $block_type, 'width' ) &&
$has_border_width_support &&
isset( $block_attributes['style']['border']['width'] )
) {
$border_width = $block_attributes['style']['border']['width'];
Expand Down
130 changes: 95 additions & 35 deletions packages/block-editor/src/hooks/border.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
* WordPress dependencies
*/
import { getBlockSupport } from '@wordpress/blocks';
import { __experimentalToolsPanelItem as ToolsPanelItem } from '@wordpress/components';
import {
__experimentalGrid as Grid,
__experimentalToolsPanelItem as ToolsPanelItem,
} from '@wordpress/components';
import { Platform } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

Expand Down Expand Up @@ -35,23 +38,23 @@ import { cleanEmptyObject } from './utils';

export const BORDER_SUPPORT_KEY = '__experimentalBorder';

const useHasBorderFeatureSupport = ( blockName, feature ) => {
return (
useSetting( `border.${ feature }` ) &&
hasBorderSupport( blockName, feature )
);
};

export function BorderPanel( props ) {
const { clientId } = props;
const { clientId, name: blockName } = props;
const isDisabled = useIsBorderDisabled( props );
const isSupported = hasBorderSupport( props.name );

const isColorSupported =
useSetting( 'border.color' ) && hasBorderSupport( props.name, 'color' );

const isRadiusSupported =
useSetting( 'border.radius' ) &&
hasBorderSupport( props.name, 'radius' );

const isStyleSupported =
useSetting( 'border.style' ) && hasBorderSupport( props.name, 'style' );
const isSupported = hasBorderSupport( blockName );

const isColorSupported = useHasBorderFeatureSupport( blockName, 'color' );
const isRadiusSupported = useHasBorderFeatureSupport( blockName, 'radius' );
const isStyleSupported = useHasBorderFeatureSupport( blockName, 'style' );
const isWidthSupported =
useSetting( 'border.width' ) && hasBorderSupport( props.name, 'width' );
useHasBorderFeatureSupport( blockName, 'width' ) || isStyleSupported;

if ( isDisabled || ! isSupported ) {
return null;
Expand All @@ -77,32 +80,68 @@ export function BorderPanel( props ) {
},
} );

const getWidthAndStyleFilter = () => {
if ( isWidthSupported && isStyleSupported ) {
return ( newAttributes ) => ( {
...newAttributes,
style: {
...newAttributes.style,
border: {
...newAttributes.style?.border,
width: undefined,
style: undefined,
},
},
} );
}

return isWidthSupported
? createResetAllFilter( 'width' )
: createResetAllFilter( 'style' );
};

const hasWidthAndStyleValue = () => {
if ( isStyleSupported ) {
return hasBorderWidthValue( props ) || hasBorderStyleValue( props );
}

return hasBorderWidthValue( props );
};

const isWidthAndStyleDefault =
defaultBorderControls?.widthAndStyle ||
( isWidthSupported && defaultBorderControls?.width ) ||
( isStyleSupported && defaultBorderControls?.style );

const widthAndStyleLabel = ! isStyleSupported
? __( 'Width' )
: __( 'Width & Style' );

const createResetWidthAndStyle = () => () => {
if ( isWidthSupported && isStyleSupported ) {
return resetBorderWidthAndStyle( props );
}

return isWidthSupported
? resetBorderWidth( props )
: resetBorderStyle( props );
};

return (
<InspectorControls __experimentalGroup="border">
{ isWidthSupported && (
{ isWidthSupported && ( // Style cannot be supported without width.
<ToolsPanelItem
className="single-column"
hasValue={ () => hasBorderWidthValue( props ) }
label={ __( 'Width' ) }
onDeselect={ () => resetBorderWidth( props ) }
isShownByDefault={ defaultBorderControls?.width }
resetAllFilter={ createResetAllFilter( 'width' ) }
hasValue={ () => hasWidthAndStyleValue() }
label={ widthAndStyleLabel }
onDeselect={ createResetWidthAndStyle() }
isShownByDefault={ isWidthAndStyleDefault }
resetAllFilter={ getWidthAndStyleFilter() }
panelId={ clientId }
>
<BorderWidthEdit { ...props } />
</ToolsPanelItem>
) }
{ isStyleSupported && (
<ToolsPanelItem
className="single-column"
hasValue={ () => hasBorderStyleValue( props ) }
label={ __( 'Style' ) }
onDeselect={ () => resetBorderStyle( props ) }
isShownByDefault={ defaultBorderControls?.style }
resetAllFilter={ createResetAllFilter( 'style' ) }
panelId={ clientId }
>
<BorderStyleEdit { ...props } />
<Grid gap="4">
<BorderWidthEdit { ...props } />
{ isStyleSupported && <BorderStyleEdit { ...props } /> }
</Grid>
</ToolsPanelItem>
) }
{ isColorSupported && (
Expand Down Expand Up @@ -213,3 +252,24 @@ export function removeBorderAttribute( style, attribute ) {
},
} );
}

/**
* Resets both the border width and style block support attributes
*
* @param {Object} props Block props.
* @param {Object} props.attributes Block's attributes.
* @param {Object} props.setAttributes Function to set block's attributes.
*/
export function resetBorderWidthAndStyle( { attributes = {}, setAttributes } ) {
const { style } = attributes;
setAttributes( {
style: cleanEmptyObject( {
...style,
border: {
...style?.border,
width: undefined,
style: undefined,
},
} ),
} );
}
75 changes: 46 additions & 29 deletions packages/edit-site/src/components/global-styles/border-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
__experimentalColorGradientControl as ColorGradientControl,
} from '@wordpress/block-editor';
import {
__experimentalGrid as Grid,
__experimentalToolsPanel as ToolsPanel,
__experimentalToolsPanelItem as ToolsPanelItem,
__experimentalUnitControl as UnitControl,
Expand Down Expand Up @@ -62,10 +63,15 @@ function useHasBorderStyleControl( name ) {

function useHasBorderWidthControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
return (
const hasStyleControl =
useSetting( 'border.style', name )[ 0 ] &&
supports.includes( 'borderStyle' );
const hasWidthControl =
useSetting( 'border.width', name )[ 0 ] &&
supports.includes( 'borderWidth' )
);
supports.includes( 'borderWidth' );

// Width control/support is enforced if border style supported.
return hasWidthControl || hasStyleControl;
}

export default function BorderPanel( { name } ) {
Expand Down Expand Up @@ -138,37 +144,48 @@ export default function BorderPanel( { name } ) {
setStyle( value || undefined );
};

const widthAndStyleLabel = ! showBorderStyle
? __( 'Width' )
: __( 'Width & Style' );

return (
<ToolsPanel label={ __( 'Border' ) } resetAll={ resetAll }>
{ showBorderWidth && (
{ showBorderWidth && ( // Style cannot be supported without width.
<ToolsPanelItem
className="single-column"
hasValue={ createHasValueCallback( 'width' ) }
label={ __( 'Width' ) }
onDeselect={ createResetCallback( setBorderWidth ) }
hasValue={ () => {
if ( showBorderStyle ) {
return (
!! userBorderStyles?.width ||
!! userBorderStyles?.style
);
}

return !! userBorderStyles?.width;
} }
label={ widthAndStyleLabel }
onDeselect={ () => {
setBorderWidth( undefined );
setBorderStyle( undefined );
} }
isShownByDefault={ true }
>
<UnitControl
value={ borderWidthValue }
label={ __( 'Width' ) }
min={ MIN_BORDER_WIDTH }
onChange={ handleOnChangeWithStyle( setBorderWidth ) }
units={ units }
/>
</ToolsPanelItem>
) }
{ showBorderStyle && (
<ToolsPanelItem
className="single-column"
hasValue={ createHasValueCallback( 'style' ) }
label={ __( 'Style' ) }
onDeselect={ createResetCallback( setBorderStyle ) }
isShownByDefault={ true }
>
<BorderStyleControl
value={ borderStyle }
onChange={ handleOnChange( setBorderStyle ) }
/>
<Grid gap="4">
<UnitControl
value={ borderWidthValue }
label={ __( 'Width' ) }
min={ MIN_BORDER_WIDTH }
onChange={ handleOnChangeWithStyle(
setBorderWidth
) }
units={ units }
/>
{ showBorderStyle && (
<BorderStyleControl
value={ borderStyle }
onChange={ handleOnChange( setBorderStyle ) }
/>
) }
</Grid>
</ToolsPanelItem>
) }
{ showBorderColor && (
Expand Down