From 9015c8765ea01664687383d4dfae815a8b78f152 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 13 Sep 2021 17:48:10 +1000 Subject: [PATCH 01/14] Move creation of ToolsPanel to within fills Creating the ToolsPanel for block supports around the slot resulted in the slot adding an extra div within the ToolsPanel breaking its layout. This div is needed for the slot's ref to be applied allowing virtual bubbling. This change effectively moves the ToolsPanel inside that. It also avoids needing to retrieve ToolsPanelContext and recreating the context provider. --- .../block-support-slot-container.js | 10 ------- .../src/components/inspector-controls/fill.js | 28 ++++++++----------- .../src/components/inspector-controls/slot.js | 17 ++++++----- 3 files changed, 20 insertions(+), 35 deletions(-) delete mode 100644 packages/block-editor/src/components/inspector-controls/block-support-slot-container.js diff --git a/packages/block-editor/src/components/inspector-controls/block-support-slot-container.js b/packages/block-editor/src/components/inspector-controls/block-support-slot-container.js deleted file mode 100644 index e450ab8b0d407..0000000000000 --- a/packages/block-editor/src/components/inspector-controls/block-support-slot-container.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * WordPress dependencies - */ -import { __experimentalToolsPanelContext as ToolsPanelContext } from '@wordpress/components'; -import { useContext } from '@wordpress/element'; - -export default function BlockSupportSlotContainer( { Slot, ...props } ) { - const toolsPanelContext = useContext( ToolsPanelContext ); - return ; -} diff --git a/packages/block-editor/src/components/inspector-controls/fill.js b/packages/block-editor/src/components/inspector-controls/fill.js index af3478252de6d..f8fc6fb2ba2de 100644 --- a/packages/block-editor/src/components/inspector-controls/fill.js +++ b/packages/block-editor/src/components/inspector-controls/fill.js @@ -1,20 +1,13 @@ -/** - * External dependencies - */ -import { isEmpty } from 'lodash'; - /** * WordPress dependencies */ -import { - __experimentalStyleProvider as StyleProvider, - __experimentalToolsPanelContext as ToolsPanelContext, -} from '@wordpress/components'; +import { __experimentalStyleProvider as StyleProvider } from '@wordpress/components'; import warning from '@wordpress/warning'; /** * Internal dependencies */ +import BlockSupportToolsPanel from './block-support-tools-panel'; import useDisplayBlockControls from '../use-display-block-controls'; import groups from './groups'; @@ -36,15 +29,18 @@ export default function InspectorControlsFill( { { ( fillProps ) => { - // Children passed to InspectorControlsFill will not have - // access to any React Context whose Provider is part of - // the InspectorControlsSlot tree. So we re-create the - // Provider in this subtree. - const value = ! isEmpty( fillProps ) ? fillProps : null; + // Check if the fills here represent the contents of a + // block support panel and require a wrapping ToolsPanel. + const { label } = fillProps; + + if ( ! label ) { + return children; + } + return ( - + { children } - + ); } } diff --git a/packages/block-editor/src/components/inspector-controls/slot.js b/packages/block-editor/src/components/inspector-controls/slot.js index c9da21817103d..58a02c72e687f 100644 --- a/packages/block-editor/src/components/inspector-controls/slot.js +++ b/packages/block-editor/src/components/inspector-controls/slot.js @@ -7,8 +7,6 @@ import warning from '@wordpress/warning'; /** * Internal dependencies */ -import BlockSupportToolsPanel from './block-support-tools-panel'; -import BlockSupportSlotContainer from './block-support-slot-container'; import groups from './groups'; export default function InspectorControlsSlot( { @@ -30,14 +28,15 @@ export default function InspectorControlsSlot( { } if ( label ) { + // Slots for block support panels will include a label for the panel + // header. This is passed through the fillProps to indicate when the + // fills require a wrapping ToolsPanel. return ( - - - + ); } From ed7538ba59b6eb2951f75cfc59b049a28cdaef43 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 13 Sep 2021 21:45:19 +1000 Subject: [PATCH 02/14] Revert "Move creation of ToolsPanel to within fills" This reverts commit 94f444c15c809d1932d04adc35d7d0e130bc3dbb. --- .../block-support-slot-container.js | 10 +++++++ .../block-support-tools-panel.js | 3 +- .../src/components/inspector-controls/fill.js | 28 +++++++++++-------- .../src/components/inspector-controls/slot.js | 17 +++++------ 4 files changed, 37 insertions(+), 21 deletions(-) create mode 100644 packages/block-editor/src/components/inspector-controls/block-support-slot-container.js diff --git a/packages/block-editor/src/components/inspector-controls/block-support-slot-container.js b/packages/block-editor/src/components/inspector-controls/block-support-slot-container.js new file mode 100644 index 0000000000000..e450ab8b0d407 --- /dev/null +++ b/packages/block-editor/src/components/inspector-controls/block-support-slot-container.js @@ -0,0 +1,10 @@ +/** + * WordPress dependencies + */ +import { __experimentalToolsPanelContext as ToolsPanelContext } from '@wordpress/components'; +import { useContext } from '@wordpress/element'; + +export default function BlockSupportSlotContainer( { Slot, ...props } ) { + const toolsPanelContext = useContext( ToolsPanelContext ); + return ; +} diff --git a/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js b/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js index 92479384b5bcb..bda1d7f7ff6f9 100644 --- a/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js +++ b/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js @@ -10,7 +10,7 @@ import { useDispatch, useSelect } from '@wordpress/data'; import { store as blockEditorStore } from '../../store'; import { cleanEmptyObject } from '../../hooks/utils'; -export default function BlockSupportToolsPanel( { children, group, label } ) { +export default function BlockSupportToolsPanel( { children, group, label, header } ) { const { clientId, attributes } = useSelect( ( select ) => { const { getBlockAttributes, getSelectedBlockClientId } = select( blockEditorStore @@ -48,6 +48,7 @@ export default function BlockSupportToolsPanel( { children, group, label } ) { { ( fillProps ) => { - // Check if the fills here represent the contents of a - // block support panel and require a wrapping ToolsPanel. - const { label } = fillProps; - - if ( ! label ) { - return children; - } - + // Children passed to InspectorControlsFill will not have + // access to any React Context whose Provider is part of + // the InspectorControlsSlot tree. So we re-create the + // Provider in this subtree. + const value = ! isEmpty( fillProps ) ? fillProps : null; return ( - + { children } - + ); } } diff --git a/packages/block-editor/src/components/inspector-controls/slot.js b/packages/block-editor/src/components/inspector-controls/slot.js index 58a02c72e687f..c9da21817103d 100644 --- a/packages/block-editor/src/components/inspector-controls/slot.js +++ b/packages/block-editor/src/components/inspector-controls/slot.js @@ -7,6 +7,8 @@ import warning from '@wordpress/warning'; /** * Internal dependencies */ +import BlockSupportToolsPanel from './block-support-tools-panel'; +import BlockSupportSlotContainer from './block-support-slot-container'; import groups from './groups'; export default function InspectorControlsSlot( { @@ -28,15 +30,14 @@ export default function InspectorControlsSlot( { } if ( label ) { - // Slots for block support panels will include a label for the panel - // header. This is passed through the fillProps to indicate when the - // fills require a wrapping ToolsPanel. return ( - + + + ); } From c4d0a447ca77cdc91a059c7323051a9597ed6f4c Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 13 Sep 2021 21:48:42 +1000 Subject: [PATCH 03/14] Remove unused header prop --- .../components/inspector-controls/block-support-tools-panel.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js b/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js index bda1d7f7ff6f9..92479384b5bcb 100644 --- a/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js +++ b/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js @@ -10,7 +10,7 @@ import { useDispatch, useSelect } from '@wordpress/data'; import { store as blockEditorStore } from '../../store'; import { cleanEmptyObject } from '../../hooks/utils'; -export default function BlockSupportToolsPanel( { children, group, label, header } ) { +export default function BlockSupportToolsPanel( { children, group, label } ) { const { clientId, attributes } = useSelect( ( select ) => { const { getBlockAttributes, getSelectedBlockClientId } = select( blockEditorStore @@ -48,7 +48,6 @@ export default function BlockSupportToolsPanel( { children, group, label, header Date: Tue, 14 Sep 2021 11:33:13 +1000 Subject: [PATCH 04/14] Fix layout when slot injects wrapping div inside tools panel --- packages/block-editor/src/components/inspector-controls/slot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/inspector-controls/slot.js b/packages/block-editor/src/components/inspector-controls/slot.js index c9da21817103d..e4714d1287a40 100644 --- a/packages/block-editor/src/components/inspector-controls/slot.js +++ b/packages/block-editor/src/components/inspector-controls/slot.js @@ -34,6 +34,7 @@ export default function InspectorControlsSlot( { From aa817c9b7a6c7997a7e30e1631d13bce3239f1ed Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:06:54 +1000 Subject: [PATCH 05/14] Update hooks with new utils for progressive display --- .../block-editor/src/hooks/border-color.js | 39 ++++++++++++++++++- .../block-editor/src/hooks/border-radius.js | 32 +++++++++++++++ .../block-editor/src/hooks/border-style.js | 26 +++++++++++++ .../block-editor/src/hooks/border-width.js | 26 +++++++++++++ 4 files changed, 122 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/border-color.js b/packages/block-editor/src/hooks/border-color.js index 3b206c90df7e1..0649a0f984c24 100644 --- a/packages/block-editor/src/hooks/border-color.js +++ b/packages/block-editor/src/hooks/border-color.js @@ -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 @@ -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, 'radius' ), + } ); +} + /** * Filters registered block settings, extending attributes to include * `borderColor` if needed. diff --git a/packages/block-editor/src/hooks/border-radius.js b/packages/block-editor/src/hooks/border-radius.js index fe734f05144f8..fa61bafa9238b 100644 --- a/packages/block-editor/src/hooks/border-radius.js +++ b/packages/block-editor/src/hooks/border-radius.js @@ -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. @@ -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' ) } ); +} diff --git a/packages/block-editor/src/hooks/border-style.js b/packages/block-editor/src/hooks/border-style.js index feaac4c694389..1a3a5f923383c 100644 --- a/packages/block-editor/src/hooks/border-style.js +++ b/packages/block-editor/src/hooks/border-style.js @@ -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. @@ -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' ) } ); +} diff --git a/packages/block-editor/src/hooks/border-width.js b/packages/block-editor/src/hooks/border-width.js index 4a08e240cef60..29c4ddbda28fc 100644 --- a/packages/block-editor/src/hooks/border-width.js +++ b/packages/block-editor/src/hooks/border-width.js @@ -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; @@ -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' ) } ); +} From d6c2faacf77abb9eaba6af8e0636dc121cf84797 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:07:22 +1000 Subject: [PATCH 06/14] Update border support to use ToolsPanel Update border support to display via progressive disclosure panel Updating border support UI styling for grid layout Update border global styles panel Fix border global style hasValue checks --- .../border-style-control/style.scss | 1 - packages/block-editor/src/hooks/border.js | 122 ++++++++++++++--- packages/block-editor/src/hooks/border.scss | 22 +--- .../components/global-styles/border-panel.js | 124 +++++++++++++----- .../src/components/sidebar/style.scss | 14 -- 5 files changed, 201 insertions(+), 82 deletions(-) diff --git a/packages/block-editor/src/components/border-style-control/style.scss b/packages/block-editor/src/components/border-style-control/style.scss index d8232bd40bb55..0a094490210fc 100644 --- a/packages/block-editor/src/components/border-style-control/style.scss +++ b/packages/block-editor/src/components/border-style-control/style.scss @@ -6,7 +6,6 @@ .components-border-style-control__buttons { display: inline-flex; - margin-bottom: $grid-unit-30; .components-button.has-icon { min-width: 30px; diff --git a/packages/block-editor/src/hooks/border.js b/packages/block-editor/src/hooks/border.js index 761c04200a531..94b24ec161dfb 100644 --- a/packages/block-editor/src/hooks/border.js +++ b/packages/block-editor/src/hooks/border.js @@ -2,19 +2,39 @@ * WordPress dependencies */ import { getBlockSupport } from '@wordpress/blocks'; -import { PanelBody } from '@wordpress/components'; +import { + __experimentalToolsPanel as ToolsPanel, + __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'; @@ -39,22 +59,73 @@ export function BorderPanel( props ) { return null; } + const defaultBorderControls = getBlockSupport( props.name, [ + BORDER_SUPPORT_KEY, + '__experimentalDefaultControls', + ] ); + + // Callback to reset all block support attributes controlled via this panel. + const resetAll = () => { + const { style } = props.attributes; + const newStyle = cleanEmptyObject( { + ...style, + border: undefined, + } ); + + props.setAttributes( { style: newStyle } ); + }; + return ( - - { ( isWidthSupported || isStyleSupported ) && ( -
- { isWidthSupported && } - { isStyleSupported && } -
+ { isWidthSupported && ( + hasBorderWidthValue( props ) } + label={ __( 'Width' ) } + onDeselect={ () => resetBorderWidth( props ) } + isShownByDefault={ defaultBorderControls?.width } + > + + + ) } + { isStyleSupported && ( + hasBorderStyleValue( props ) } + label={ __( 'Style' ) } + onDeselect={ () => resetBorderStyle( props ) } + isShownByDefault={ defaultBorderControls?.style } + > + + + ) } + { isColorSupported && ( + hasBorderColorValue( props ) } + label={ __( 'Color' ) } + onDeselect={ () => resetBorderColor( props ) } + isShownByDefault={ defaultBorderControls?.color } + > + + + ) } + { isRadiusSupported && ( + hasBorderRadiusValue( props ) } + label={ __( 'Radius' ) } + onDeselect={ () => resetBorderRadius( props ) } + isShownByDefault={ defaultBorderControls?.radius } + > + + ) } - { isColorSupported && } - { isRadiusSupported && } -
+
); } @@ -118,3 +189,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, + }, + } ); +} diff --git a/packages/block-editor/src/hooks/border.scss b/packages/block-editor/src/hooks/border.scss index 6c859252afc34..cef7fc84e8998 100644 --- a/packages/block-editor/src/hooks/border.scss +++ b/packages/block-editor/src/hooks/border.scss @@ -1,19 +1,11 @@ -.block-editor-hooks__border-controls { - .block-editor-hooks__border-controls-row { - display: flex; - justify-content: space-between; - - > * { - width: calc(50% - #{ $grid-unit-10 }); - } +.block-editor-block-inspector .block-editor-hooks__border-controls, +.edit-site .components-progressive-disclosure-panel { + .components-unit-control-wrapper, + .components-border-style-control { + grid-column: span 1; } - .components-unit-control-wrapper { - margin-bottom: $grid-unit-30; - - &:last-child { - margin-bottom: $grid-unit-10; - } + .components-base-control__field { + margin-bottom: 0; } } - diff --git a/packages/edit-site/src/components/global-styles/border-panel.js b/packages/edit-site/src/components/global-styles/border-panel.js index 14ce8e798cdc7..f765488766860 100644 --- a/packages/edit-site/src/components/global-styles/border-panel.js +++ b/packages/edit-site/src/components/global-styles/border-panel.js @@ -7,7 +7,8 @@ import { __experimentalColorGradientControl as ColorGradientControl, } from '@wordpress/block-editor'; import { - PanelBody, + __experimentalToolsPanel as ToolsPanel, + __experimentalToolsPanelItem as ToolsPanelItem, __experimentalUnitControl as UnitControl, __experimentalUseCustomUnits as useCustomUnits, } from '@wordpress/components'; @@ -68,6 +69,19 @@ function useHasBorderWidthControl( name ) { } export default function BorderPanel( { name } ) { + // To better reflect if the user has customized a value we need to + // ensure the style value being checked is from the `user` origin. + const [ userBorderStyles ] = useStyle( 'border', name, 'user' ); + const createHasValueCallback = ( feature ) => () => + !! userBorderStyles?.[ feature ]; + + const createResetCallback = ( setStyle ) => () => + setStyle( undefined ); + + const handleOnChange = ( setStyle ) => ( value ) => { + setStyle( value || undefined ); + }; + const units = useCustomUnits( { availableUnits: useSetting( 'spacing.units' )[ 0 ] || [ 'px', @@ -77,70 +91,108 @@ export default function BorderPanel( { name } ) { } ); // Border width. - const hasBorderWidth = useHasBorderWidthControl( name ); + const showBorderWidth = useHasBorderWidthControl( name ); const [ borderWidthValue, setBorderWidth ] = useStyle( 'border.width', name ); // Border style. - const hasBorderStyle = useHasBorderStyleControl( name ); + const showBorderStyle = useHasBorderStyleControl( name ); const [ borderStyle, setBorderStyle ] = useStyle( 'border.style', name ); // Border color. + const showBorderColor = useHasBorderColorControl( name ); + const [ borderColor, setBorderColor ] = useStyle( 'border.color', name ); const [ colors = EMPTY_ARRAY ] = useSetting( 'color.palette' ); const disableCustomColors = ! useSetting( 'color.custom' )[ 0 ]; const disableCustomGradients = ! useSetting( 'color.customGradient' )[ 0 ]; - const hasBorderColor = useHasBorderColorControl( name ); - const [ borderColor, setBorderColor ] = useStyle( 'border.color', name ); // Border radius. - const hasBorderRadius = useHasBorderRadiusControl( name ); + const showBorderRadius = useHasBorderRadiusControl( name ); const [ borderRadiusValues, setBorderRadius ] = useStyle( 'border.radius', name ); + const hasBorderRadius = () => { + const borderValues = userBorderStyles?.[ 'radius' ]; + if ( typeof borderValues === 'object' ) { + return Object.entries( borderValues ).some( Boolean ); + } + return !! borderValues; + } + + const resetAll = () => { + setBorderColor( undefined ); + setBorderRadius( undefined ); + setBorderStyle( undefined ); + setBorderWidth( undefined ); + } return ( - - { ( hasBorderWidth || hasBorderStyle ) && ( -
- { hasBorderWidth && ( + + { showBorderWidth && ( + { - setBorderWidth( value || undefined ); - } } + onChange={ handleOnChange( setBorderWidth ) } units={ units } /> - ) } - { hasBorderStyle && ( - - ) } -
+ + )} + { showBorderStyle && ( + + + ) } - { hasBorderColor && ( - + onDeselect={ createResetCallback( setBorderColor ) } + isShownByDefault={ true } + > + + ) } - { hasBorderRadius && ( - + { showBorderRadius && ( + + + ) } -
+
); } diff --git a/packages/edit-site/src/components/sidebar/style.scss b/packages/edit-site/src/components/sidebar/style.scss index 9744b269a073e..36a0155a28118 100644 --- a/packages/edit-site/src/components/sidebar/style.scss +++ b/packages/edit-site/src/components/sidebar/style.scss @@ -25,20 +25,6 @@ margin-left: auto; } -.edit-site-global-styles-sidebar__border-controls-row { - display: flex; - justify-content: space-between; - margin-bottom: $grid-unit-15; - - > * { - width: calc(50% - #{ $grid-unit-10 }); - } - - .components-border-style-control__buttons { - margin-bottom: 0; - } -} - .edit-site-global-styles-sidebar .components-navigation__menu-title-heading { font-size: $default-font-size * 1.2; font-weight: 500; From 821d08a06dd5372bf627aea6c99732e68e8c93cf Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 17 Aug 2021 15:11:11 +1000 Subject: [PATCH 07/14] Fix typo in border color reset --- packages/block-editor/src/hooks/border-color.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/border-color.js b/packages/block-editor/src/hooks/border-color.js index 0649a0f984c24..6c7e00a08c597 100644 --- a/packages/block-editor/src/hooks/border-color.js +++ b/packages/block-editor/src/hooks/border-color.js @@ -130,7 +130,7 @@ export function resetBorderColor( { attributes = {}, setAttributes } ) { setAttributes( { borderColor: undefined, - style: removeBorderAttribute( style, 'radius' ), + style: removeBorderAttribute( style, 'color' ), } ); } From 9414eebd2aa95a0643df93e4cd823c527e9160f1 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 17 Aug 2021 15:18:17 +1000 Subject: [PATCH 08/14] Incorporate color control styles for ToolsPanel and remove border styles --- packages/block-editor/src/hooks/border.scss | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 packages/block-editor/src/hooks/border.scss diff --git a/packages/block-editor/src/hooks/border.scss b/packages/block-editor/src/hooks/border.scss deleted file mode 100644 index cef7fc84e8998..0000000000000 --- a/packages/block-editor/src/hooks/border.scss +++ /dev/null @@ -1,11 +0,0 @@ -.block-editor-block-inspector .block-editor-hooks__border-controls, -.edit-site .components-progressive-disclosure-panel { - .components-unit-control-wrapper, - .components-border-style-control { - grid-column: span 1; - } - - .components-base-control__field { - margin-bottom: 0; - } -} From 8414e9d3a1e6ca2a192d61ebf5556a816b2f5d9a Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 17 Aug 2021 16:01:27 +1000 Subject: [PATCH 09/14] Add missing reset of borderColor attribute to resetAll --- packages/block-editor/src/hooks/border.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/border.js b/packages/block-editor/src/hooks/border.js index 94b24ec161dfb..979cab0924111 100644 --- a/packages/block-editor/src/hooks/border.js +++ b/packages/block-editor/src/hooks/border.js @@ -72,7 +72,7 @@ export function BorderPanel( props ) { border: undefined, } ); - props.setAttributes( { style: newStyle } ); + props.setAttributes( { style: newStyle, borderColor: undefined } ); }; return ( From 315720b740e5b327872f288f3e53804419c95389 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:03:35 +1000 Subject: [PATCH 10/14] Update border support use of ToolsPanel These changes include adding a new border group to the inspector controls slots and updating the border tools panel to match the latest changes to that component. --- .../src/components/block-inspector/index.js | 5 + .../components/inspector-controls/groups.js | 2 + packages/block-editor/src/hooks/border.js | 133 +++++++++--------- 3 files changed, 76 insertions(+), 64 deletions(-) diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 425b527e96eac..46bcd7baba523 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -138,6 +138,11 @@ const BlockInspectorSingleBlock = ( { bubblesVirtually={ bubblesVirtually } label={ __( 'Typography' ) } /> + { - const { style } = props.attributes; - const newStyle = cleanEmptyObject( { - ...style, - border: undefined, - } ); - - props.setAttributes( { style: newStyle, borderColor: undefined } ); - }; + const createResetAllFilter = ( + borderAttribute, + topLevelAttributes = {} + ) => ( newAttributes ) => ( { + ...newAttributes, + ...topLevelAttributes, + style: { + ...newAttributes.style, + border: { + ...newAttributes.style?.border, + [ borderAttribute ]: undefined, + }, + }, + } ); return ( - - - { isWidthSupported && ( - hasBorderWidthValue( props ) } - label={ __( 'Width' ) } - onDeselect={ () => resetBorderWidth( props ) } - isShownByDefault={ defaultBorderControls?.width } - > - - - ) } - { isStyleSupported && ( - hasBorderStyleValue( props ) } - label={ __( 'Style' ) } - onDeselect={ () => resetBorderStyle( props ) } - isShownByDefault={ defaultBorderControls?.style } - > - - - ) } - { isColorSupported && ( - hasBorderColorValue( props ) } - label={ __( 'Color' ) } - onDeselect={ () => resetBorderColor( props ) } - isShownByDefault={ defaultBorderControls?.color } - > - - - ) } - { isRadiusSupported && ( - hasBorderRadiusValue( props ) } - label={ __( 'Radius' ) } - onDeselect={ () => resetBorderRadius( props ) } - isShownByDefault={ defaultBorderControls?.radius } - > - - - ) } - + + { isWidthSupported && ( + hasBorderWidthValue( props ) } + label={ __( 'Width' ) } + onDeselect={ () => resetBorderWidth( props ) } + isShownByDefault={ defaultBorderControls?.width } + resetAllFilter={ createResetAllFilter( 'width' ) } + panelId={ clientId } + > + + + ) } + { isStyleSupported && ( + hasBorderStyleValue( props ) } + label={ __( 'Style' ) } + onDeselect={ () => resetBorderStyle( props ) } + isShownByDefault={ defaultBorderControls?.style } + resetAllFilter={ createResetAllFilter( 'style' ) } + panelId={ clientId } + > + + + ) } + { isColorSupported && ( + hasBorderColorValue( props ) } + label={ __( 'Color' ) } + onDeselect={ () => resetBorderColor( props ) } + isShownByDefault={ defaultBorderControls?.color } + resetAllFilter={ createResetAllFilter( 'color', { + borderColor: undefined, + } ) } + panelId={ clientId } + > + + + ) } + { isRadiusSupported && ( + hasBorderRadiusValue( props ) } + label={ __( 'Radius' ) } + onDeselect={ () => resetBorderRadius( props ) } + isShownByDefault={ defaultBorderControls?.radius } + resetAllFilter={ createResetAllFilter( 'radius' ) } + panelId={ clientId } + > + + + ) } ); } From 56a6ac3382cebb025a7905903d6286fc92aaf6a5 Mon Sep 17 00:00:00 2001 From: Staci Cooper Date: Mon, 18 Oct 2021 14:32:24 -0700 Subject: [PATCH 11/14] Linting --- .../components/global-styles/border-panel.js | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/border-panel.js b/packages/edit-site/src/components/global-styles/border-panel.js index f765488766860..23cdaa88b7b0e 100644 --- a/packages/edit-site/src/components/global-styles/border-panel.js +++ b/packages/edit-site/src/components/global-styles/border-panel.js @@ -72,11 +72,10 @@ export default function BorderPanel( { name } ) { // To better reflect if the user has customized a value we need to // ensure the style value being checked is from the `user` origin. const [ userBorderStyles ] = useStyle( 'border', name, 'user' ); - const createHasValueCallback = ( feature ) => () => + const createHasValueCallback = ( feature ) => () => !! userBorderStyles?.[ feature ]; - const createResetCallback = ( setStyle ) => () => - setStyle( undefined ); + const createResetCallback = ( setStyle ) => () => setStyle( undefined ); const handleOnChange = ( setStyle ) => ( value ) => { setStyle( value || undefined ); @@ -115,19 +114,19 @@ export default function BorderPanel( { name } ) { name ); const hasBorderRadius = () => { - const borderValues = userBorderStyles?.[ 'radius' ]; + const borderValues = userBorderStyles?.radius; if ( typeof borderValues === 'object' ) { return Object.entries( borderValues ).some( Boolean ); } return !! borderValues; - } + }; const resetAll = () => { setBorderColor( undefined ); setBorderRadius( undefined ); setBorderStyle( undefined ); setBorderWidth( undefined ); - } + }; return ( @@ -138,16 +137,16 @@ export default function BorderPanel( { name } ) { label={ __( 'Width' ) } onDeselect={ createResetCallback( setBorderWidth ) } isShownByDefault={ true } - > - - - )} + > + + + ) } { showBorderStyle && ( Date: Tue, 16 Nov 2021 09:07:33 +1000 Subject: [PATCH 12/14] Remove unneeded classname from slot container --- packages/block-editor/src/components/inspector-controls/slot.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/inspector-controls/slot.js b/packages/block-editor/src/components/inspector-controls/slot.js index e4714d1287a40..c9da21817103d 100644 --- a/packages/block-editor/src/components/inspector-controls/slot.js +++ b/packages/block-editor/src/components/inspector-controls/slot.js @@ -34,7 +34,6 @@ export default function InspectorControlsSlot( { From 02335dc99ee55c3e4587dbe9ce1242b4d501f0f6 Mon Sep 17 00:00:00 2001 From: Staci Cooper <63313398+stacimc@users.noreply.github.com> Date: Tue, 16 Nov 2021 16:21:38 -0800 Subject: [PATCH 13/14] Border panel: Update panel layout (#35938) * Restore single-column styling for appropriate controls * Remove clear button from Color picker in ToolsPanel --- packages/block-editor/src/hooks/border.scss | 5 +++++ .../edit-site/src/components/global-styles/border-panel.js | 1 + packages/edit-site/src/components/sidebar/style.scss | 4 ++++ 3 files changed, 10 insertions(+) create mode 100644 packages/block-editor/src/hooks/border.scss diff --git a/packages/block-editor/src/hooks/border.scss b/packages/block-editor/src/hooks/border.scss new file mode 100644 index 0000000000000..c86c046309d88 --- /dev/null +++ b/packages/block-editor/src/hooks/border.scss @@ -0,0 +1,5 @@ +.border-block-support-panel { + .single-column { + grid-column: span 1; + } +} diff --git a/packages/edit-site/src/components/global-styles/border-panel.js b/packages/edit-site/src/components/global-styles/border-panel.js index 23cdaa88b7b0e..f39d9d99b8367 100644 --- a/packages/edit-site/src/components/global-styles/border-panel.js +++ b/packages/edit-site/src/components/global-styles/border-panel.js @@ -176,6 +176,7 @@ export default function BorderPanel( { name } ) { disableCustomColors={ disableCustomColors } disableCustomGradients={ disableCustomGradients } onColorChange={ handleOnChange( setBorderColor ) } + clearable={ false } /> ) } diff --git a/packages/edit-site/src/components/sidebar/style.scss b/packages/edit-site/src/components/sidebar/style.scss index 36a0155a28118..b6189e4d91441 100644 --- a/packages/edit-site/src/components/sidebar/style.scss +++ b/packages/edit-site/src/components/sidebar/style.scss @@ -39,6 +39,10 @@ border: 0; } +.edit-site-global-styles-sidebar .components-tools-panel-item.single-column { + grid-column: span 1; +} + .edit-site-global-styles-sidebar__blocks-group { padding-top: $grid-unit-30; border-top: $border-width solid $gray-200; From 3a8e7483ec9d1e2cf2e6822f1ac2a1077c035a24 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 24 Nov 2021 16:32:17 +1000 Subject: [PATCH 14/14] Try adding some default fallbacks When a user first sets a border width or color their may not be a border style set. These changes aim to provide a fallback for that (in the frontend/block editor) or apply a border style by default in the site editor for Global Styles. --- packages/block-library/src/common.scss | 19 +++++++++++++++++++ .../components/global-styles/border-panel.js | 16 ++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/common.scss b/packages/block-library/src/common.scss index b76682ccf6b34..4111181e55113 100644 --- a/packages/block-library/src/common.scss +++ b/packages/block-library/src/common.scss @@ -89,3 +89,22 @@ width: auto; z-index: 100000; } + +/** + * The following provide a simple means of applying a default border style when + * a user first makes a selection in the border block support panel. + * This prevents issues such as where the user could set a border width + * and see no border due there being no border style set. + * + * This is intended to be removed once intelligent defaults can be set while + * making border selections via the block support. + * + * See: https://github.com/WordPress/gutenberg/pull/33743 + */ +html :where(.has-border-color) { + border-style: solid; +} + +html :where([style*="border-width"]) { + border-style: solid; +} diff --git a/packages/edit-site/src/components/global-styles/border-panel.js b/packages/edit-site/src/components/global-styles/border-panel.js index f39d9d99b8367..f8dafd5584368 100644 --- a/packages/edit-site/src/components/global-styles/border-panel.js +++ b/packages/edit-site/src/components/global-styles/border-panel.js @@ -128,6 +128,16 @@ export default function BorderPanel( { name } ) { setBorderWidth( undefined ); }; + // When we set a border color or width ensure we have a style so the user + // can see a visible border. + const handleOnChangeWithStyle = ( setStyle ) => ( value ) => { + if ( !! value && ! borderStyle ) { + setBorderStyle( 'solid' ); + } + + setStyle( value || undefined ); + }; + return ( { showBorderWidth && ( @@ -142,7 +152,7 @@ export default function BorderPanel( { name } ) { value={ borderWidthValue } label={ __( 'Width' ) } min={ MIN_BORDER_WIDTH } - onChange={ handleOnChange( setBorderWidth ) } + onChange={ handleOnChangeWithStyle( setBorderWidth ) } units={ units } /> @@ -175,7 +185,9 @@ export default function BorderPanel( { name } ) { gradients={ undefined } disableCustomColors={ disableCustomColors } disableCustomGradients={ disableCustomGradients } - onColorChange={ handleOnChange( setBorderColor ) } + onColorChange={ handleOnChangeWithStyle( + setBorderColor + ) } clearable={ false } />