From 4bdc58146245014f58526922fb1b024a3c49ce50 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 29 May 2023 13:50:52 +1000 Subject: [PATCH] Spacing: Optimize & condense unlinked spacing controls (#50660) --- .../global-styles/dimensions-panel.js | 4 +- .../all-input-control.js | 44 ---- .../hooks/use-spacing-sizes.js | 26 ++ .../components/spacing-sizes-control/index.js | 156 ++++++------ .../axial.js} | 27 +- .../separated.js} | 29 +-- .../input-controls/single.js | 40 +++ .../spacing-input-control.js | 135 ++++------ .../spacing-sizes-control/linked-button.js | 24 -- .../sides-dropdown/index.js | 91 +++++++ .../spacing-sizes-control/style.scss | 128 +++------- .../spacing-sizes-control/test/utils.js | 237 +++++++++++++++++- .../components/spacing-sizes-control/utils.js | 223 ++++++++++++++-- packages/block-library/src/spacer/controls.js | 1 + packages/icons/src/index.js | 8 + packages/icons/src/library/sides-all.js | 15 ++ packages/icons/src/library/sides-axial.js | 19 ++ packages/icons/src/library/sides-bottom.js | 16 ++ .../icons/src/library/sides-horizontal.js | 19 ++ packages/icons/src/library/sides-left.js | 16 ++ packages/icons/src/library/sides-right.js | 16 ++ packages/icons/src/library/sides-top.js | 16 ++ packages/icons/src/library/sides-vertical.js | 19 ++ 23 files changed, 936 insertions(+), 373 deletions(-) delete mode 100644 packages/block-editor/src/components/spacing-sizes-control/all-input-control.js create mode 100644 packages/block-editor/src/components/spacing-sizes-control/hooks/use-spacing-sizes.js rename packages/block-editor/src/components/spacing-sizes-control/{axial-input-controls.js => input-controls/axial.js} (89%) rename packages/block-editor/src/components/spacing-sizes-control/{input-controls.js => input-controls/separated.js} (88%) create mode 100644 packages/block-editor/src/components/spacing-sizes-control/input-controls/single.js rename packages/block-editor/src/components/spacing-sizes-control/{ => input-controls}/spacing-input-control.js (80%) delete mode 100644 packages/block-editor/src/components/spacing-sizes-control/linked-button.js create mode 100644 packages/block-editor/src/components/spacing-sizes-control/sides-dropdown/index.js create mode 100644 packages/icons/src/library/sides-all.js create mode 100644 packages/icons/src/library/sides-axial.js create mode 100644 packages/icons/src/library/sides-bottom.js create mode 100644 packages/icons/src/library/sides-horizontal.js create mode 100644 packages/icons/src/library/sides-left.js create mode 100644 packages/icons/src/library/sides-right.js create mode 100644 packages/icons/src/library/sides-top.js create mode 100644 packages/icons/src/library/sides-vertical.js diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index 3a4a2b3230fa9..9b36ee4e2cd4a 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -499,7 +499,6 @@ export default function DimensionsPanel( { sides={ paddingSides } units={ units } allowReset={ false } - splitOnAxis={ isAxialPadding } onMouseOver={ onMouseOverPadding } onMouseOut={ onMouseLeaveControls } /> @@ -540,7 +539,6 @@ export default function DimensionsPanel( { sides={ marginSides } units={ units } allowReset={ false } - splitOnAxis={ isAxialMargin } onMouseOver={ onMouseOverMargin } onMouseOut={ onMouseLeaveControls } /> @@ -587,10 +585,10 @@ export default function DimensionsPanel( { label={ __( 'Block spacing' ) } min={ 0 } onChange={ setGapValues } + showSideInLabel={ false } sides={ isAxialGap ? gapSides : [ 'top' ] } // Use 'top' as the shorthand property in non-axial configurations. values={ gapValues } allowReset={ false } - splitOnAxis={ isAxialGap } /> ) } diff --git a/packages/block-editor/src/components/spacing-sizes-control/all-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/all-input-control.js deleted file mode 100644 index f7f9686daee33..0000000000000 --- a/packages/block-editor/src/components/spacing-sizes-control/all-input-control.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * WordPress dependencies - */ -import { __experimentalApplyValueToSides as applyValueToSides } from '@wordpress/components'; - -/** - * Internal dependencies - */ -import SpacingInputControl from './spacing-input-control'; -import { getAllRawValue, isValuesMixed, isValuesDefined } from './utils'; - -export default function AllInputControl( { - onChange, - values, - sides, - spacingSizes, - type, - minimumCustomValue, - onMouseOver, - onMouseOut, -} ) { - const allValue = getAllRawValue( values ); - const hasValues = isValuesDefined( values ); - const isMixed = hasValues && isValuesMixed( values, sides ); - - const handleOnChange = ( next ) => { - const nextValues = applyValueToSides( values, next, sides ); - onChange( nextValues ); - }; - - return ( - - ); -} diff --git a/packages/block-editor/src/components/spacing-sizes-control/hooks/use-spacing-sizes.js b/packages/block-editor/src/components/spacing-sizes-control/hooks/use-spacing-sizes.js new file mode 100644 index 0000000000000..7fc96caa7fd47 --- /dev/null +++ b/packages/block-editor/src/components/spacing-sizes-control/hooks/use-spacing-sizes.js @@ -0,0 +1,26 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import useSetting from '../../use-setting'; + +export default function useSpacingSizes() { + const spacingSizes = [ + { name: 0, slug: '0', side: 0 }, + ...( useSetting( 'spacing.spacingSizes' ) || [] ), + ]; + + if ( spacingSizes.length > 8 ) { + spacingSizes.unshift( { + name: __( 'Default' ), + slug: 'default', + size: undefined, + } ); + } + + return spacingSizes; +} diff --git a/packages/block-editor/src/components/spacing-sizes-control/index.js b/packages/block-editor/src/components/spacing-sizes-control/index.js index 4ec1285db52bb..5c26305331dd2 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/index.js +++ b/packages/block-editor/src/components/spacing-sizes-control/index.js @@ -1,61 +1,50 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - /** * WordPress dependencies */ +import { + BaseControl, + __experimentalHStack as HStack, +} from '@wordpress/components'; import { useState } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; -import { BaseControl } from '@wordpress/components'; +import { __, _x, sprintf } from '@wordpress/i18n'; /** * Internal dependencies */ -import AllInputControl from './all-input-control'; -import InputControls from './input-controls'; -import AxialInputControls from './axial-input-controls'; -import LinkedButton from './linked-button'; -import { DEFAULT_VALUES, isValuesMixed, isValuesDefined } from './utils'; -import useSetting from '../use-setting'; +import AxialInputControls from './input-controls/axial'; +import SeparatedInputControls from './input-controls/separated'; +import SingleInputControl from './input-controls/single'; +import SidesDropdown from './sides-dropdown'; +import useSpacingSizes from './hooks/use-spacing-sizes'; +import { + ALL_SIDES, + DEFAULT_VALUES, + LABELS, + VIEWS, + getInitialView, +} from './utils'; export default function SpacingSizesControl( { inputProps, - onChange, - label = __( 'Spacing Control' ), - values, - sides, - splitOnAxis = false, - useSelect, + label: labelProp, minimumCustomValue = 0, - onMouseOver, + onChange, onMouseOut, + onMouseOver, + showSideInLabel = true, + sides = ALL_SIDES, + useSelect, + values, } ) { - const spacingSizes = [ - { name: 0, slug: '0', size: 0 }, - ...( useSetting( 'spacing.spacingSizes' ) || [] ), - ]; - - if ( spacingSizes.length > 8 ) { - spacingSizes.unshift( { - name: __( 'Default' ), - slug: 'default', - size: undefined, - } ); - } - + const spacingSizes = useSpacingSizes(); const inputValues = values || DEFAULT_VALUES; - const hasInitialValue = isValuesDefined( values ); const hasOneSide = sides?.length === 1; + const hasOnlyAxialSides = + sides?.includes( 'horizontal' ) && + sides?.includes( 'vertical' ) && + sides?.length === 2; - const [ isLinked, setIsLinked ] = useState( - ! hasInitialValue || ! isValuesMixed( inputValues, sides ) || hasOneSide - ); - - const toggleLinked = () => { - setIsLinked( ! isLinked ); - }; + const [ view, setView ] = useState( getInitialView( inputValues, sides ) ); const handleOnChange = ( nextValue ) => { const newValues = { ...values, ...nextValue }; @@ -64,43 +53,68 @@ export default function SpacingSizesControl( { const inputControlProps = { ...inputProps, + minimumCustomValue, onChange: handleOnChange, - isLinked, + onMouseOut, + onMouseOver, sides, - values: inputValues, spacingSizes, + type: labelProp, useSelect, - type: label, - minimumCustomValue, - onMouseOver, - onMouseOut, + values: inputValues, }; - return ( -
- - { label } - - { ! hasOneSide && ( - - ) } - { isLinked && ( - - ) } + const renderControls = () => { + if ( view === VIEWS.axial ) { + return ; + } + if ( view === VIEWS.custom ) { + return ; + } + return ( + + ); + }; + + const sideLabel = + ALL_SIDES.includes( view ) && showSideInLabel ? LABELS[ view ] : ''; + + const label = sprintf( + // translators: 2. Type of spacing being modified (Padding, margin, etc). 1: The side of the block being modified (top, bottom, left etc.). + __( '%1$s %2$s' ), + labelProp, + sideLabel + ).trim(); - { ! isLinked && splitOnAxis && ( - - ) } - { ! isLinked && ! splitOnAxis && ( - - ) } + const dropdownLabelText = sprintf( + // translators: %s: The current spacing property e.g. "Padding", "Margin". + _x( '%s options', 'Button label to reveal side configuration options' ), + labelProp + ); + + return ( +
+ + + { label } + + { ! hasOneSide && ! hasOnlyAxialSides && ( + + ) } + + { renderControls() }
); } diff --git a/packages/block-editor/src/components/spacing-sizes-control/axial-input-controls.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/axial.js similarity index 89% rename from packages/block-editor/src/components/spacing-sizes-control/axial-input-controls.js rename to packages/block-editor/src/components/spacing-sizes-control/input-controls/axial.js index 3551e20ede759..3ca76d9c8f482 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/axial-input-controls.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/axial.js @@ -2,19 +2,19 @@ * Internal dependencies */ import SpacingInputControl from './spacing-input-control'; -import { LABELS } from './utils'; +import { LABELS, ICONS, hasAxisSupport } from '../utils'; const groupedSides = [ 'vertical', 'horizontal' ]; export default function AxialInputControls( { + minimumCustomValue, onChange, - values, + onMouseOut, + onMouseOver, sides, spacingSizes, type, - minimumCustomValue, - onMouseOver, - onMouseOut, + values, } ) { const createHandleOnChange = ( side ) => ( next ) => { if ( ! onChange ) { @@ -37,7 +37,7 @@ export default function AxialInputControls( { // Filter sides if custom configuration provided, maintaining default order. const filteredSides = sides?.length - ? groupedSides.filter( ( side ) => sides.includes( side ) ) + ? groupedSides.filter( ( side ) => hasAxisSupport( sides, side ) ) : groupedSides; return ( @@ -47,17 +47,18 @@ export default function AxialInputControls( { side === 'vertical' ? values.top : values.left; return ( ); } ) } diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/separated.js similarity index 88% rename from packages/block-editor/src/components/spacing-sizes-control/input-controls.js rename to packages/block-editor/src/components/spacing-sizes-control/input-controls/separated.js index 412dbad2030c9..ddfa3ebca8e99 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/separated.js @@ -2,17 +2,17 @@ * Internal dependencies */ import SpacingInputControl from './spacing-input-control'; -import { ALL_SIDES, LABELS } from './utils'; +import { ALL_SIDES, LABELS, ICONS } from '../utils'; -export default function BoxInputControls( { - values, - sides, +export default function SeparatedInputControls( { + minimumCustomValue, onChange, + onMouseOut, + onMouseOver, + sides, spacingSizes, type, - minimumCustomValue, - onMouseOver, - onMouseOut, + values, } ) { // Filter sides if custom configuration provided, maintaining default order. const filteredSides = sides?.length @@ -31,17 +31,18 @@ export default function BoxInputControls( { { filteredSides.map( ( side ) => { return ( ); } ) } diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls/single.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/single.js new file mode 100644 index 0000000000000..2bb0a409da0dd --- /dev/null +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/single.js @@ -0,0 +1,40 @@ +/** + * Internal dependencies + */ +import SpacingInputControl from './spacing-input-control'; +import { LABELS } from '../utils'; + +export default function SingleInputControl( { + minimumCustomValue, + onChange, + onMouseOut, + onMouseOver, + showSideInLabel, + side, + spacingSizes, + type, + values, +} ) { + const createHandleOnChange = ( currentSide ) => ( next ) => { + const nextValues = { ...values }; + nextValues[ currentSide ] = next; + + onChange( nextValues ); + }; + + return ( + + ); +} diff --git a/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js similarity index 80% rename from packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js rename to packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js index 8831b06b1eebc..f423596daaa4a 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js @@ -1,39 +1,35 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - /** * WordPress dependencies */ -import { useState, useMemo } from '@wordpress/element'; -import { useSelect } from '@wordpress/data'; import { - BaseControl, Button, - RangeControl, CustomSelectControl, - __experimentalUnitControl as UnitControl, + Icon, + RangeControl, __experimentalHStack as HStack, + __experimentalUnitControl as UnitControl, __experimentalUseCustomUnits as useCustomUnits, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { useState, useMemo } from '@wordpress/element'; +import { usePrevious } from '@wordpress/compose'; import { __, sprintf } from '@wordpress/i18n'; import { settings } from '@wordpress/icons'; -import { usePrevious } from '@wordpress/compose'; /** * Internal dependencies */ -import useSetting from '../use-setting'; -import { store as blockEditorStore } from '../../store'; +import useSetting from '../../use-setting'; +import { store as blockEditorStore } from '../../../store'; import { + ALL_SIDES, LABELS, getSliderValueFromPreset, getCustomValueFromPreset, getPresetValueFromCustomValue, isValueSpacingPreset, -} from './utils'; +} from '../utils'; const CUSTOM_VALUE_SETTINGS = { px: { max: 300, steps: 1 }, @@ -45,15 +41,17 @@ const CUSTOM_VALUE_SETTINGS = { }; export default function SpacingInputControl( { - spacingSizes, - value, - side, - onChange, + icon, isMixed = false, - type, minimumCustomValue, - onMouseOver, + onChange, onMouseOut, + onMouseOver, + showSideInLabel = true, + side, + spacingSizes, + type, + value, } ) { // Treat value as a preset value if the passed in value matches the value of one of the spacingSizes. value = getPresetValueFromCustomValue( value, spacingSizes ); @@ -159,73 +157,34 @@ export default function SpacingInputControl( { const allPlaceholder = isMixed ? __( 'Mixed' ) : null; - const currentValueHint = ! isMixed - ? customTooltipContent( currentValue ) - : __( 'Mixed' ); - const options = selectListSizes.map( ( size, index ) => ( { key: index, name: size.name, } ) ); - const marks = spacingSizes.map( ( newValue, index ) => ( { + const marks = spacingSizes.map( ( _newValue, index ) => ( { value: index, label: undefined, } ) ); + const sideLabel = + ALL_SIDES.includes( side ) && showSideInLabel ? LABELS[ side ] : ''; + const typeLabel = showSideInLabel ? type?.toLowerCase() : type; + const ariaLabel = sprintf( - // translators: 1: The side of the block being modified (top, bottom, left, etc.). 2. Type of spacing being modified (Padding, margin, etc) + // translators: 1: The side of the block being modified (top, bottom, left, All sides etc.). 2. Type of spacing being modified (Padding, margin, etc) __( '%1$s %2$s' ), - LABELS[ side ], - type?.toLowerCase() - ); - - const showHint = - showRangeControl && - ! showCustomValueControl && - currentValueHint !== undefined; + sideLabel, + typeLabel + ).trim(); return ( - <> - { side !== 'all' && ( - - - { LABELS[ side ] } - - - { showHint && ( - - { currentValueHint } - - ) } - - ) } - { side === 'all' && showHint && ( - - { currentValueHint } - - ) } - - { ! disableCustomSpacingSizes && ( -