diff --git a/packages/block-editor/src/components/colors-gradients/dropdown.js b/packages/block-editor/src/components/colors-gradients/dropdown.js index 299995d3eb6cc6..0f48945a7bd4ed 100644 --- a/packages/block-editor/src/components/colors-gradients/dropdown.js +++ b/packages/block-editor/src/components/colors-gradients/dropdown.js @@ -12,8 +12,6 @@ import { Dropdown, FlexItem, __experimentalHStack as HStack, - __experimentalItem as Item, - __experimentalItemGroup as ItemGroup, __experimentalToolsPanelItem as ToolsPanelItem, } from '@wordpress/components'; @@ -22,46 +20,34 @@ import { */ import ColorGradientControl from './control'; -// Conditionally wraps the `ColorGradientSettingsDropdown` color controls in an -// `ItemGroup` allowing for a standalone group of controls to be -// rendered semantically. -const WithItemGroup = ( { __experimentalIsItemGroup, children } ) => { - if ( ! __experimentalIsItemGroup ) { - return children; - } - - return ( - - { children } - - ); -}; - // When the `ColorGradientSettingsDropdown` controls are being rendered to a // `ToolsPanel` they must be wrapped in a `ToolsPanelItem`. -const WithToolsPanelItem = ( { - __experimentalIsItemGroup, - settings, - children, - ...props -} ) => { - if ( __experimentalIsItemGroup ) { - return children; - } - +const WithToolsPanelItem = ( { setting, children, panelId, ...props } ) => { + const clearValue = () => { + if ( setting.colorValue ) { + setting.onColorChange(); + } else if ( setting.gradientValue ) { + setting.onGradientChange(); + } + }; return ( { + return !! setting.colorValue || !! setting.gradientValue; + } } + label={ setting.label } + onDeselect={ clearValue } + isShownByDefault={ + setting.isShownByDefault !== undefined + ? setting.isShownByDefault + : true + } { ...props } className="block-editor-tools-panel-color-gradient-settings__item" + panelId={ panelId } + // Pass resetAllFilter if supplied due to rendering via SlotFill + // into parent ToolsPanel. + resetAllFilter={ setting.resetAllFilter } > { children } @@ -82,23 +68,21 @@ const LabeledColorIndicator = ( { colorValue, label } ) => ( // or as a `Button` if it isn't e.g. the controls are being rendered in // a `ToolsPanel`. const renderToggle = ( settings ) => ( { onToggle, isOpen } ) => { - const { __experimentalIsItemGroup, colorValue, label } = settings; + const { colorValue, label } = settings; - // Determine component, `Item` or `Button`, to wrap color indicator with. - const ToggleComponent = __experimentalIsItemGroup ? Item : Button; - const toggleClassName = __experimentalIsItemGroup - ? 'block-editor-panel-color-gradient-settings__item' - : 'block-editor-panel-color-gradient-settings__dropdown'; const toggleProps = { onClick: onToggle, - className: classnames( toggleClassName, { 'is-open': isOpen } ), - 'aria-expanded': __experimentalIsItemGroup ? undefined : isOpen, + className: classnames( + 'block-editor-panel-color-gradient-settings__dropdown', + { 'is-open': isOpen } + ), + 'aria-expanded': isOpen, }; return ( - + ); }; @@ -115,15 +99,11 @@ export default function ColorGradientSettingsDropdown( { disableCustomGradients, enableAlpha, gradients, - __experimentalIsItemGroup = true, settings, __experimentalHasMultipleOrigins, __experimentalIsRenderedInSidebar, ...props } ) { - const dropdownClassName = __experimentalIsItemGroup - ? 'block-editor-panel-color-gradient-settings__dropdown' - : 'block-editor-tools-panel-color-gradient-settings__dropdown'; let popoverProps; if ( __experimentalIsRenderedInSidebar ) { popoverProps = { @@ -133,12 +113,10 @@ export default function ColorGradientSettingsDropdown( { } return ( - // Only wrap with `ItemGroup` if these controls are being rendered - // semantically. - + <> { settings.map( ( setting, index ) => { const controlProps = { - clearable: __experimentalIsItemGroup ? undefined : false, + clearable: false, colorValue: setting.colorValue, colors, disableCustomColors, @@ -156,7 +134,6 @@ export default function ColorGradientSettingsDropdown( { }; const toggleSettings = { colorValue: setting.gradientValue ?? setting.colorValue, - __experimentalIsItemGroup, label: setting.label, }; @@ -166,15 +143,12 @@ export default function ColorGradientSettingsDropdown( { // `ToolsPanelItem` ( @@ -185,6 +159,6 @@ export default function ColorGradientSettingsDropdown( { ) ); } ) } - + ); } diff --git a/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.js b/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.js index ab40dbc010e578..797a6c9463697d 100644 --- a/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.js +++ b/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.js @@ -9,27 +9,19 @@ import { every, isEmpty } from 'lodash'; */ import { __experimentalSpacer as Spacer, - ColorIndicator, - PanelBody, + __experimentalToolsPanel as ToolsPanel, } from '@wordpress/components'; -import { sprintf, __ } from '@wordpress/i18n'; +import { useRegistry } from '@wordpress/data'; +import { useInstanceId } from '@wordpress/compose'; /** * Internal dependencies */ import ColorGradientSettingsDropdown from './dropdown'; -import { getColorObjectByColorValue } from '../colors'; -import { __experimentalGetGradientObjectByGradientValue } from '../gradients'; import useSetting from '../use-setting'; import useCommonSingleMultipleSelects from './use-common-single-multiple-selects'; import useMultipleOriginColorsAndGradients from './use-multiple-origin-colors-and-gradients'; -// translators: first %s: The type of color or gradient (e.g. background, overlay...), second %s: the color name or value (e.g. red or #ff0000) -const colorIndicatorAriaLabel = __( '(%s: color %s)' ); - -// translators: first %s: The type of color or gradient (e.g. background, overlay...), second %s: the color name or value (e.g. red or #ff0000) -const gradientIndicatorAriaLabel = __( '(%s: gradient %s)' ); - const colorsAndGradientKeys = [ 'colors', 'disableCustomColors', @@ -37,55 +29,6 @@ const colorsAndGradientKeys = [ 'disableCustomGradients', ]; -const Indicators = ( { colors, gradients, settings } ) => { - return settings.map( - ( - { - colorValue, - gradientValue, - label, - colors: availableColors, - gradients: availableGradients, - }, - index - ) => { - if ( ! colorValue && ! gradientValue ) { - return null; - } - let ariaLabel; - if ( colorValue ) { - const colorObject = getColorObjectByColorValue( - availableColors || colors, - colorValue - ); - ariaLabel = sprintf( - colorIndicatorAriaLabel, - label.toLowerCase(), - ( colorObject && colorObject.name ) || colorValue - ); - } else { - const gradientObject = __experimentalGetGradientObjectByGradientValue( - availableGradients || gradients, - colorValue - ); - ariaLabel = sprintf( - gradientIndicatorAriaLabel, - label.toLowerCase(), - ( gradientObject && gradientObject.name ) || gradientValue - ); - } - - return ( - - ); - } - ); -}; - export const PanelColorGradientSettingsInner = ( { className, colors, @@ -99,8 +42,9 @@ export const PanelColorGradientSettingsInner = ( { __experimentalHasMultipleOrigins, __experimentalIsRenderedInSidebar, enableAlpha, - ...props } ) => { + const panelId = useInstanceId( PanelColorGradientSettingsInner ); + const { batch } = useRegistry(); if ( isEmpty( colors ) && isEmpty( gradients ) && @@ -120,28 +64,38 @@ export const PanelColorGradientSettingsInner = ( { return null; } - const titleElement = ( - - { title } - - - ); - return ( - { + batch( () => { + settings.forEach( + ( { + colorValue, + gradientValue, + onColorChange, + onGradientChange, + } ) => { + if ( colorValue ) { + onColorChange(); + } else if ( gradientValue ) { + onGradientChange(); + } + } + ); + } ); + } } + panelId={ panelId } + __experimentalFirstVisibleItemClass="first" + __experimentalLastVisibleItemClass="last" > { children } ) } - + ); }; diff --git a/packages/block-editor/src/components/colors-gradients/style.scss b/packages/block-editor/src/components/colors-gradients/style.scss index e936859db68560..e2794bee8bdc63 100644 --- a/packages/block-editor/src/components/colors-gradients/style.scss +++ b/packages/block-editor/src/components/colors-gradients/style.scss @@ -10,25 +10,14 @@ min-width: 0; } -.block-editor-panel-color-gradient-settings { - .block-editor-panel-color-gradient-settings__panel-title { - display: flex; - gap: $grid-unit-10; - - .component-color-indicator { - width: $grid-unit-15; - height: $grid-unit-15; - align-self: center; - - &:first-child { - margin-left: $grid-unit-15; - } - } +.block-editor-panel-color-gradient-settings.block-editor-panel-color-gradient-settings { + &, + & > div:not(:first-of-type) { + display: block; } +} - &.is-opened &__panel-title .component-color-indicator { - display: none; - } +.block-editor-panel-color-gradient-settings { // Must equal $color-palette-circle-size from: // @wordpress/components/src/circular-option-picker/style.scss @@ -49,32 +38,12 @@ margin-bottom: inherit; } - .block-editor-panel-color-gradient-settings__dropdown { - display: block; - } -} - -.block-editor-panel-color-gradient-settings__dropdown { - width: 100%; } .block-editor-panel-color-gradient-settings__dropdown-content .components-popover__content { width: $sidebar-width; } -.block-editor-panel-color-gradient-settings__dropdown:last-child > div { - border-bottom-width: 0; -} - -.block-editor-panel-color-gradient-settings__item { - padding-top: $grid-unit-15 !important; - padding-bottom: $grid-unit-15 !important; - - &.is-open { - background: $gray-100; - color: var(--wp-admin-theme-color); - } -} .block-editor-panel-color-gradient-settings__color-indicator { // Show a diagonal line (crossed out) for empty swatches. @@ -97,6 +66,7 @@ border-bottom: 1px solid rgba(0, 0, 0, 0.1); &.first { + margin-top: $grid-unit-30; border-top-left-radius: 2px; border-top-right-radius: 2px; border-top: 1px solid rgba(0, 0, 0, 0.1); @@ -126,3 +96,7 @@ } } } + +.block-editor-panel-color-gradient-settings__dropdown { + width: 100%; +} diff --git a/packages/block-editor/src/hooks/color.js b/packages/block-editor/src/hooks/color.js index b02b9f2bfbbad6..3219e016923f3e 100644 --- a/packages/block-editor/src/hooks/color.js +++ b/packages/block-editor/src/hooks/color.js @@ -76,34 +76,6 @@ const hasTextColorSupport = ( blockType ) => { return colorSupport && colorSupport.text !== false; }; -/** - * Checks whether a color has been set either with a named preset color in - * a top level block attribute or as a custom value within the style attribute - * object. - * - * @param {string} name Name of the color to check. - * @return {boolean} Whether or not a color has a value. - */ -const hasColor = ( name ) => ( props ) => { - if ( name === 'background' ) { - return ( - !! props.attributes.backgroundColor || - !! props.attributes.style?.color?.background || - !! props.attributes.gradient || - !! props.attributes.style?.color?.gradient - ); - } - - if ( name === 'link' ) { - return !! props.attributes.style?.elements?.link?.color?.text; - } - - return ( - !! props.attributes[ `${ name }Color` ] || - !! props.attributes.style?.color?.[ name ] - ); -}; - /** * Clears a single color property from a style object. * @@ -114,20 +86,6 @@ const hasColor = ( name ) => ( props ) => { const clearColorFromStyles = ( path, style ) => cleanEmptyObject( immutableSet( style, path, undefined ) ); -/** - * Resets the block attributes for text color. - * - * @param {Object} props Current block props. - * @param {Object} props.attributes Block attributes. - * @param {Function} props.setAttributes Block's setAttributes prop used to apply reset. - */ -const resetTextColor = ( { attributes, setAttributes } ) => { - setAttributes( { - textColor: undefined, - style: clearColorFromStyles( [ 'color', 'text' ], attributes.style ), - } ); -}; - /** * Clears text color related properties from supplied attributes. * @@ -139,18 +97,6 @@ const resetAllTextFilter = ( attributes ) => ( { style: clearColorFromStyles( [ 'color', 'text' ], attributes.style ), } ); -/** - * Resets the block attributes for link color. - * - * @param {Object} props Current block props. - * @param {Object} props.attributes Block attributes. - * @param {Function} props.setAttributes Block's setAttributes prop used to apply reset. - */ -const resetLinkColor = ( { attributes, setAttributes } ) => { - const path = [ 'elements', 'link', 'color', 'text' ]; - setAttributes( { style: clearColorFromStyles( path, attributes.style ) } ); -}; - /** * Clears link color related properties from supplied attributes. * @@ -184,17 +130,6 @@ const clearBackgroundAndGradient = ( attributes ) => ( { }, } ); -/** - * Resets the block attributes for both background color and gradient. - * - * @param {Object} props Current block props. - * @param {Object} props.attributes Block attributes. - * @param {Function} props.setAttributes Block's setAttributes prop used to apply reset. - */ -const resetBackgroundAndGradient = ( { attributes, setAttributes } ) => { - setAttributes( clearBackgroundAndGradient( attributes ) ); -}; - /** * Filters registered block settings, extending attributes to include * `backgroundColor` and `textColor` attribute. @@ -496,12 +431,16 @@ export function ColorEdit( props ) { const newStyle = cleanEmptyObject( immutableSet( - style, + localAttributes.current?.style, [ 'elements', 'link', 'color', 'text' ], newLinkColorValue ) ); props.setAttributes( { style: newStyle } ); + localAttributes.current = { + ...localAttributes.current, + ...{ style: newStyle }, + }; }; const enableContrastChecking = @@ -529,8 +468,6 @@ export function ColorEdit( props ) { style?.color?.text ).color, isShownByDefault: defaultColorControls?.text, - hasValue: () => hasColor( 'text' )( props ), - onDeselect: () => resetTextColor( props ), resetAllFilter: resetAllTextFilter, }, ] @@ -553,10 +490,6 @@ export function ColorEdit( props ) { : undefined, isShownByDefault: defaultColorControls?.background, - hasValue: () => - hasColor( 'background' )( props ), - onDeselect: () => - resetBackgroundAndGradient( props ), resetAllFilter: clearBackgroundAndGradient, }, ] @@ -573,8 +506,6 @@ export function ColorEdit( props ) { clearable: !! style?.elements?.link?.color ?.text, isShownByDefault: defaultColorControls?.link, - hasValue: () => hasColor( 'link' )( props ), - onDeselect: () => resetLinkColor( props ), resetAllFilter: resetAllLinkFilter, }, ] diff --git a/packages/block-editor/src/hooks/color.scss b/packages/block-editor/src/hooks/color.scss index 2b79f03a504e27..f9b7898f941b75 100644 --- a/packages/block-editor/src/hooks/color.scss +++ b/packages/block-editor/src/hooks/color.scss @@ -20,4 +20,13 @@ row-gap: 0; } } + + /** + * After converting PanelColorGradientSettings to render as a ToolsPanel + * we need to remove the top margin when wrapping inner content due to + * rendering via SlotFills. + */ + .block-editor-tools-panel-color-gradient-settings__item.first { + margin-top: 0; + } } diff --git a/packages/block-library/src/social-links/edit.js b/packages/block-library/src/social-links/edit.js index ed148909ad1b30..f06f2ff42b7579 100644 --- a/packages/block-library/src/social-links/edit.js +++ b/packages/block-library/src/social-links/edit.js @@ -215,16 +215,17 @@ export function SocialLinksEdit( props ) { __experimentalIsRenderedInSidebar title={ __( 'Color' ) } colorSettings={ colorSettings } - /> - { ! logosOnly && ( - - ) } + > + { ! logosOnly && ( + + ) } +