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

Borders: Switch to ToolsPanel for displaying UI #33743

Merged
merged 14 commits into from Nov 29, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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,
},
},
} );
aaronrobertshaw marked this conversation as resolved.
Show resolved Hide resolved

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"
aaronrobertshaw marked this conversation as resolved.
Show resolved Hide resolved
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;
}
}