Skip to content

Commit

Permalink
Borders: Switch to ToolsPanel for displaying UI (#33743)
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronrobertshaw committed Nov 29, 2021
1 parent 812fa1b commit 3475693
Show file tree
Hide file tree
Showing 12 changed files with 376 additions and 95 deletions.
5 changes: 5 additions & 0 deletions packages/block-editor/src/components/block-inspector/index.js
Expand Up @@ -138,6 +138,11 @@ const BlockInspectorSingleBlock = ( {
bubblesVirtually={ bubblesVirtually }
label={ __( 'Typography' ) }
/>
<InspectorControls.Slot
__experimentalGroup="border"
bubblesVirtually={ bubblesVirtually }
label={ __( 'Border' ) }
/>
<InspectorControls.Slot
__experimentalGroup="dimensions"
bubblesVirtually={ bubblesVirtually }
Expand Down
Expand Up @@ -6,7 +6,6 @@

.components-border-style-control__buttons {
display: inline-flex;
margin-bottom: $grid-unit-30;

.components-button.has-icon {
min-width: 30px;
Expand Down
Expand Up @@ -5,6 +5,7 @@ import { createSlotFill } from '@wordpress/components';

const InspectorControlsDefault = createSlotFill( 'InspectorControls' );
const InspectorControlsAdvanced = createSlotFill( 'InspectorAdvancedControls' );
const InspectorControlsBorder = createSlotFill( 'InspectorControlsBorder' );
const InspectorControlsDimensions = createSlotFill(
'InspectorControlsDimensions'
);
Expand All @@ -15,6 +16,7 @@ const InspectorControlsTypography = createSlotFill(
const groups = {
default: InspectorControlsDefault,
advanced: InspectorControlsAdvanced,
border: InspectorControlsBorder,
dimensions: InspectorControlsDimensions,
typography: InspectorControlsTypography,
};
Expand Down
39 changes: 38 additions & 1 deletion packages/block-editor/src/hooks/border-color.js
Expand Up @@ -22,7 +22,11 @@ import {
getColorObjectByAttributeValues,
} from '../components/colors';
import useSetting from '../components/use-setting';
import { hasBorderSupport, shouldSkipSerialization } from './border';
import {
hasBorderSupport,
removeBorderAttribute,
shouldSkipSerialization,
} from './border';
import { cleanEmptyObject } from './utils';

// Defining empty array here instead of inline avoids unnecessary re-renders of
Expand Down Expand Up @@ -97,6 +101,39 @@ export function BorderColorEdit( props ) {
);
}

/**
* Checks if there is a current value in the border color block support
* attributes.
*
* @param {Object} props Block props.
* @return {boolean} Whether or not the block has a border color value set.
*/
export function hasBorderColorValue( props ) {
const {
attributes: { borderColor, style },
} = props;

return !! borderColor || !! style?.border?.color;
}

/**
* Resets the border color block support attributes. This can be used when
* disabling the border color support controls for a block via a progressive
* discovery panel.
*
* @param {Object} props Block props.
* @param {Object} props.attributes Block's attributes.
* @param {Object} props.setAttributes Function to set block's attributes.
*/
export function resetBorderColor( { attributes = {}, setAttributes } ) {
const { style } = attributes;

setAttributes( {
borderColor: undefined,
style: removeBorderAttribute( style, 'color' ),
} );
}

/**
* Filters registered block settings, extending attributes to include
* `borderColor` if needed.
Expand Down
32 changes: 32 additions & 0 deletions packages/block-editor/src/hooks/border-radius.js
Expand Up @@ -3,6 +3,7 @@
*/
import BorderRadiusControl from '../components/border-radius-control';
import { cleanEmptyObject } from './utils';
import { removeBorderAttribute } from './border';

/**
* Inspector control panel containing the border radius related configuration.
Expand Down Expand Up @@ -40,3 +41,34 @@ export function BorderRadiusEdit( props ) {
/>
);
}

/**
* Checks if there is a current value in the border radius block support
* attributes.
*
* @param {Object} props Block props.
* @return {boolean} Whether or not the block has a border radius value set.
*/
export function hasBorderRadiusValue( props ) {
const borderRadius = props.attributes.style?.border?.radius;

if ( typeof borderRadius === 'object' ) {
return Object.entries( borderRadius ).some( Boolean );
}

return !! borderRadius;
}

/**
* Resets the border radius block support attributes. This can be used when
* disabling the border radius support controls for a block via a progressive
* discovery panel.
*
* @param {Object} props Block props.
* @param {Object} props.attributes Block's attributes.
* @param {Object} props.setAttributes Function to set block's attributes.
*/
export function resetBorderRadius( { attributes = {}, setAttributes } ) {
const { style } = attributes;
setAttributes( { style: removeBorderAttribute( style, 'radius' ) } );
}
26 changes: 26 additions & 0 deletions packages/block-editor/src/hooks/border-style.js
Expand Up @@ -3,6 +3,7 @@
*/
import BorderStyleControl from '../components/border-style-control';
import { cleanEmptyObject } from './utils';
import { removeBorderAttribute } from './border';

/**
* Inspector control for configuring border style property.
Expand Down Expand Up @@ -36,3 +37,28 @@ export const BorderStyleEdit = ( props ) => {
/>
);
};

/**
* Checks if there is a current value in the border style block support
* attributes.
*
* @param {Object} props Block props.
* @return {boolean} Whether or not the block has a border style value set.
*/
export function hasBorderStyleValue( props ) {
return !! props.attributes.style?.border?.style;
}

/**
* Resets the border style block support attribute. This can be used when
* disabling the border style support control for a block via a progressive
* discovery panel.
*
* @param {Object} props Block props.
* @param {Object} props.attributes Block's attributes.
* @param {Object} props.setAttributes Function to set block's attributes.
*/
export function resetBorderStyle( { attributes = {}, setAttributes } ) {
const { style } = attributes;
setAttributes( { style: removeBorderAttribute( style, 'style' ) } );
}
26 changes: 26 additions & 0 deletions packages/block-editor/src/hooks/border-width.js
Expand Up @@ -12,6 +12,7 @@ import { __ } from '@wordpress/i18n';
* Internal dependencies
*/
import { cleanEmptyObject } from './utils';
import { removeBorderAttribute } from './border';
import useSetting from '../components/use-setting';

const MIN_BORDER_WIDTH = 0;
Expand Down Expand Up @@ -113,3 +114,28 @@ export const BorderWidthEdit = ( props ) => {
/>
);
};

/**
* Checks if there is a current value in the border width block support
* attributes.
*
* @param {Object} props Block props.
* @return {boolean} Whether or not the block has a border width value set.
*/
export function hasBorderWidthValue( props ) {
return !! props.attributes.style?.border?.width;
}

/**
* Resets the border width block support attribute. This can be used when
* disabling the border width support control for a block via a progressive
* discovery panel.
*
* @param {Object} props Block props.
* @param {Object} props.attributes Block's attributes.
* @param {Object} props.setAttributes Function to set block's attributes.
*/
export function resetBorderWidth( { attributes = {}, setAttributes } ) {
const { style } = attributes;
setAttributes( { style: removeBorderAttribute( style, 'width' ) } );
}
135 changes: 115 additions & 20 deletions packages/block-editor/src/hooks/border.js
Expand Up @@ -2,23 +2,41 @@
* WordPress dependencies
*/
import { getBlockSupport } from '@wordpress/blocks';
import { PanelBody } from '@wordpress/components';
import { __experimentalToolsPanelItem as ToolsPanelItem } from '@wordpress/components';
import { Platform } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import {
BorderColorEdit,
hasBorderColorValue,
resetBorderColor,
} from './border-color';
import {
BorderRadiusEdit,
hasBorderRadiusValue,
resetBorderRadius,
} from './border-radius';
import {
BorderStyleEdit,
hasBorderStyleValue,
resetBorderStyle,
} from './border-style';
import {
BorderWidthEdit,
hasBorderWidthValue,
resetBorderWidth,
} from './border-width';
import InspectorControls from '../components/inspector-controls';
import useSetting from '../components/use-setting';
import { BorderColorEdit } from './border-color';
import { BorderRadiusEdit } from './border-radius';
import { BorderStyleEdit } from './border-style';
import { BorderWidthEdit } from './border-width';
import { cleanEmptyObject } from './utils';

export const BORDER_SUPPORT_KEY = '__experimentalBorder';

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

Expand All @@ -39,22 +57,80 @@ export function BorderPanel( props ) {
return null;
}

const defaultBorderControls = getBlockSupport( props.name, [
BORDER_SUPPORT_KEY,
'__experimentalDefaultControls',
] );

const createResetAllFilter = (
borderAttribute,
topLevelAttributes = {}
) => ( newAttributes ) => ( {
...newAttributes,
...topLevelAttributes,
style: {
...newAttributes.style,
border: {
...newAttributes.style?.border,
[ borderAttribute ]: undefined,
},
},
} );

return (
<InspectorControls>
<PanelBody
className="block-editor-hooks__border-controls"
title={ __( 'Border' ) }
initialOpen={ false }
>
{ ( isWidthSupported || isStyleSupported ) && (
<div className="block-editor-hooks__border-controls-row">
{ isWidthSupported && <BorderWidthEdit { ...props } /> }
{ isStyleSupported && <BorderStyleEdit { ...props } /> }
</div>
) }
{ isColorSupported && <BorderColorEdit { ...props } /> }
{ isRadiusSupported && <BorderRadiusEdit { ...props } /> }
</PanelBody>
<InspectorControls __experimentalGroup="border">
{ isWidthSupported && (
<ToolsPanelItem
className="single-column"
hasValue={ () => hasBorderWidthValue( props ) }
label={ __( 'Width' ) }
onDeselect={ () => resetBorderWidth( props ) }
isShownByDefault={ defaultBorderControls?.width }
resetAllFilter={ createResetAllFilter( 'width' ) }
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 } />
</ToolsPanelItem>
) }
{ isColorSupported && (
<ToolsPanelItem
hasValue={ () => hasBorderColorValue( props ) }
label={ __( 'Color' ) }
onDeselect={ () => resetBorderColor( props ) }
isShownByDefault={ defaultBorderControls?.color }
resetAllFilter={ createResetAllFilter( 'color', {
borderColor: undefined,
} ) }
panelId={ clientId }
>
<BorderColorEdit { ...props } />
</ToolsPanelItem>
) }
{ isRadiusSupported && (
<ToolsPanelItem
hasValue={ () => hasBorderRadiusValue( props ) }
label={ __( 'Radius' ) }
onDeselect={ () => resetBorderRadius( props ) }
isShownByDefault={ defaultBorderControls?.radius }
resetAllFilter={ createResetAllFilter( 'radius' ) }
panelId={ clientId }
>
<BorderRadiusEdit { ...props } />
</ToolsPanelItem>
) }
</InspectorControls>
);
}
Expand Down Expand Up @@ -118,3 +194,22 @@ const useIsBorderDisabled = () => {

return configs.every( Boolean );
};

/**
* Returns a new style object where the specified border attribute has been
* removed.
*
* @param {Object} style Styles from block attributes.
* @param {string} attribute The border style attribute to clear.
*
* @return {Object} Style object with the specified attribute removed.
*/
export function removeBorderAttribute( style, attribute ) {
return cleanEmptyObject( {
...style,
border: {
...style?.border,
[ attribute ]: undefined,
},
} );
}
20 changes: 3 additions & 17 deletions packages/block-editor/src/hooks/border.scss
@@ -1,19 +1,5 @@
.block-editor-hooks__border-controls {
.block-editor-hooks__border-controls-row {
display: flex;
justify-content: space-between;

> * {
width: calc(50% - #{ $grid-unit-10 });
}
}

.components-unit-control-wrapper {
margin-bottom: $grid-unit-30;

&:last-child {
margin-bottom: $grid-unit-10;
}
.border-block-support-panel {
.single-column {
grid-column: span 1;
}
}

0 comments on commit 3475693

Please sign in to comment.