Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const PanelColorGradientSettingsInner = ( {
'block-editor-panel-color-gradient-settings',
className
) }
hasInnerWrapper
label={ showTitle ? title : undefined }
resetAll={ () => {
batch( () => {
Expand All @@ -88,23 +89,25 @@ export const PanelColorGradientSettingsInner = ( {
__experimentalFirstVisibleItemClass="first"
__experimentalLastVisibleItemClass="last"
>
<ColorGradientSettingsDropdown
settings={ settings }
panelId={ panelId }
{ ...{
colors,
gradients,
disableCustomColors,
disableCustomGradients,
__experimentalIsRenderedInSidebar,
enableAlpha,
} }
/>
{ !! children && (
<>
<Spacer marginY={ 4 } /> { children }
</>
) }
<div className="block-editor-panel-color-gradient-settings__inner-wrapper">
<ColorGradientSettingsDropdown
settings={ settings }
panelId={ panelId }
{ ...{
colors,
gradients,
disableCustomColors,
disableCustomGradients,
__experimentalIsRenderedInSidebar,
enableAlpha,
} }
/>
{ !! children && (
<>
<Spacer marginY={ 4 } /> { children }
</>
) }
</div>
</ToolsPanel>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,6 @@ $swatch-gap: 12px;
min-width: 0;
}

.block-editor-panel-color-gradient-settings.block-editor-panel-color-gradient-settings {
&,
& > div:not(:first-of-type) {
display: block;
}
}

.block-editor-panel-color-gradient-settings {
@media screen and (min-width: $break-medium) {
.components-circular-option-picker__swatches {
Expand All @@ -46,6 +39,23 @@ $swatch-gap: 12px;
margin-bottom: inherit;
}

/* Increased specificity required to remove the slot wrapper's row gap */
&#{&} {
.block-editor-panel-color-gradient-settings__inner-wrapper {
// `ToolsPanel` spans the inner wrapper across its grid via a
// positional selector that assumes a header is present. This panel
// can render without one (`showTitle={ false }`), so span it here.
grid-column: 1 / -1;
row-gap: 0;

// Unlike the other panels using an inner wrapper, this component
// accepts arbitrary children. Those carry no `ToolsPanelItem`
// class, so they'd otherwise be auto-placed into a single column.
> * {
grid-column: 1 / -1;
}
}
}
Comment on lines +42 to +58

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because consumers can add arbitrary children to the component, should we ensure that children are full width to the column, e.g. something like:

  &#{&} {
        .block-editor-panel-color-gradient-settings__inner-wrapper {
                row-gap: 0;

                > * {
                        grid-column: 1 / -1;
                }
        }
  }

@andrewserong andrewserong Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might also want the inner wrapper itself to be grid-column: 1 / -1; too, so possibly:

  /* Increased specificity required to remove the slot wrapper's row gap */
  &#{&} {
        .block-editor-panel-color-gradient-settings__inner-wrapper {
                grid-column: 1 / -1;
                row-gap: 0;

                > * {
                        grid-column: 1 / -1;
                }
        }
  }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this on top of what .tools-panel-with-inner-wrapper provides? Or just a precaution?

https://github.com/WordPress/gutenberg/blob/fix/panel-color-gradient-settings-space/packages/components/src/tools-panel/style.module.scss#L17

.tools-panel-with-inner-wrapper {
	> div:not(:first-of-type) {
        ...
		grid-column: 1 / -1;
	}
}

If not, the first example works a treat!

Screenshot 2026-08-05 at 11 03 28 am

Here's the test code:

Example
( () => {
	const { createElement: el, Fragment, useState } = wp.element;
	const { createHigherOrderComponent } = wp.compose;
	const { InspectorControls, PanelColorSettings } = wp.blockEditor;
	const { ToggleControl, Notice } = wp.components;

	// Loud outlines so it is obvious whether a child spans the full panel
	// width or gets auto-placed into one of the inner wrapper's two columns.
	const style = document.createElement( 'style' );
	style.textContent = `
		.debug-child {
			outline: 2px solid magenta !important;
			background: rgba(255, 0, 255, 0.08) !important;
		}
		.block-editor-panel-color-gradient-settings__inner-wrapper {
			outline: 2px dashed limegreen !important;
		}
		.block-editor-tools-panel-color-gradient-settings__item {
			outline: 1px solid blue !important;
		}
	`;
	document.head.appendChild( style );

	const withColorPanel = createHigherOrderComponent(
		( BlockEdit ) => ( props ) => {
			const [ colorA, setColorA ] = useState();
			const [ colorB, setColorB ] = useState();
			const [ toggle, setToggle ] = useState( false );

			const colorSettings = [
				{ value: colorA, onChange: setColorA, label: 'Color A' },
				{ value: colorB, onChange: setColorB, label: 'Color B' },
			];

			if ( ! props.isSelected ) {
				return el( BlockEdit, props );
			}

			return el(
				Fragment,
				null,
				el( BlockEdit, props ),
				el(
					InspectorControls,
					{},

					// CONTROL: no children. Should look correct both before
					// and after the change.
					el( PanelColorSettings, {
						__experimentalIsRenderedInSidebar: true,
						title: 'A. No children (control)',
						colorSettings,
					} ),

					// TEST: arbitrary children. These carry no
					// `.tools-panel-item` class, so nothing gives them
					// `grid-column: 1 / -1`.
					el(
						PanelColorSettings,
						{
							__experimentalIsRenderedInSidebar: true,
							title: 'B. With children (the test)',
							colorSettings,
						},
						el(
							'div',
							{ className: 'debug-child' },
							'CHILD 1 - full width?'
						),
						el(
							'div',
							{ className: 'debug-child' },
							'CHILD 2 - same row as CHILD 1?'
						),
						el( ToggleControl, {
							className: 'debug-child',
							label: 'A real control as a child',
							checked: toggle,
							onChange: setToggle,
						} ),
						el(
							Notice,
							{
								className: 'debug-child',
								status: 'warning',
								isDismissible: false,
							},
							'Notice child - squashed into one column?'
						)
					)
				)
			);
		},
		'withColorPanel'
	);

	wp.hooks.addFilter(
		'editor.BlockEdit',
		'debug/panel-color-settings',
		withColorPanel
	);

	// Force a re-render so already mounted blocks pick up the filter.
	wp.data.dispatch( 'core/block-editor' ).clearSelectedBlock();
} )();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this on top of what .tools-panel-with-inner-wrapper provides? Or just a precaution?

The potential issue I ran into is that this component supports setting showTitle: false so the colors wind up as the first item (not the header).

Image

Here's some more test code:

Some test code for `showTitle: false`
( () => {
        const { createElement: el, Fragment, useState } = wp.element;
        const { createHigherOrderComponent } = wp.compose;
        const { InspectorControls, PanelColorSettings } = wp.blockEditor;

        const style = document.createElement( 'style' );
        style.textContent = `
                .block-editor-panel-color-gradient-settings__inner-wrapper {
                        outline: 2px dashed limegreen !important;
                }
                .debug-child {
                        outline: 2px solid magenta !important;
                        background: rgba(255, 0, 255, 0.08) !important;
                        font-size: 11px;
                }
        `;
        document.head.appendChild( style );

        const child = ( label ) => el( 'div', { className: 'debug-child' }, label );

        const withColorPanel = createHigherOrderComponent(
                ( BlockEdit ) => ( props ) => {
                        const [ colorA, setColorA ] = useState();
                        const [ colorB, setColorB ] = useState();

                        if ( ! props.isSelected ) {
                                return el( BlockEdit, props );
                        }

                        const colorSettings = [
                                { value: colorA, onChange: setColorA, label: 'Color A' },
                                { value: colorB, onChange: setColorB, label: 'Color B' },
                        ];

                        return el(
                                Fragment,
                                null,
                                el( BlockEdit, props ),
                                el(
                                        InspectorControls,
                                        {},

                                        // Header renders: wrapper is full width, children are not.
                                        el(
                                                PanelColorSettings,
                                                {
                                                        __experimentalIsRenderedInSidebar: true,
                                                        title: 'A. With title',
                                                        colorSettings,
                                                },
                                                child( 'CHILD 1 — full width?' ),
                                                child( 'CHILD 2 — own row?' )
                                        ),

                                        // No header: the wrapper itself is only half width.
                                        el(
                                                PanelColorSettings,
                                                {
                                                        __experimentalIsRenderedInSidebar: true,
                                                        title: 'B. showTitle false',
                                                        showTitle: false,
                                                        colorSettings,
                                                },
                                                child( 'CHILD — full width?' )
                                        )
                                )
                        );
                },
                'withColorPanel'
        );

        wp.hooks.addFilter(
                'editor.BlockEdit',
                'debug/panel-color-settings',
                withColorPanel
        );

        // Force a re-render so already mounted blocks pick up the filter.
        wp.data.dispatch( 'core/block-editor' ).clearSelectedBlock();
  } )();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I feel you! Thanks for the added test steps. Worth the extra rule then. Ignore me!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, no, it was good to double-check, thanks for the extra 👀! I'll push the CSS change 👍

}

.block-editor-panel-color-gradient-settings__dropdown-content {
Expand Down
Loading