From 10277d8b771994d38c77b65e3b2ebef4e1f2610a Mon Sep 17 00:00:00 2001 From: im3dabasia Date: Fri, 11 Sep 2026 10:49:43 +0530 Subject: [PATCH 1/8] feat: Introduce Media Panel in Inspector Panel --- .../block-library/src/cover/edit/index.jsx | 2 + .../src/cover/edit/inspector-controls.jsx | 71 ++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/cover/edit/index.jsx b/packages/block-library/src/cover/edit/index.jsx index 6e7f94b9f8bcbd..b80429174f0b08 100644 --- a/packages/block-library/src/cover/edit/index.jsx +++ b/packages/block-library/src/cover/edit/index.jsx @@ -703,6 +703,8 @@ function CoverEdit( { setOverlayColor={ onSetOverlayColor } coverRef={ ref } currentSettings={ currentSettings } + onSelectMedia={ onSelectMedia } + onUploadError={ onUploadError } toggleUseFeaturedImage={ toggleUseFeaturedImage } updateDimRatio={ onUpdateDimRatio } onClearMedia={ onClearMedia } diff --git a/packages/block-library/src/cover/edit/inspector-controls.jsx b/packages/block-library/src/cover/edit/inspector-controls.jsx index 9b368cc2662cc0..c8e8b7c074b49e 100644 --- a/packages/block-library/src/cover/edit/inspector-controls.jsx +++ b/packages/block-library/src/cover/edit/inspector-controls.jsx @@ -23,8 +23,13 @@ import { import { __ } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; +import { getFilename } from '@wordpress/url'; import { Link } from '@wordpress/ui'; -import { COVER_MIN_HEIGHT, mediaPosition } from '../shared'; +import { + ALLOWED_MEDIA_TYPES, + COVER_MIN_HEIGHT, + mediaPosition, +} from '../shared'; import { unlock } from '../../lock-unlock'; import { useToolsPanelDropdownMenuProps } from '../../utils/hooks'; import { @@ -35,6 +40,7 @@ import { } from '../../utils/style-state'; import { DEFAULT_MEDIA_SIZE_SLUG } from '../constants'; import PosterImage from '../../utils/poster-image'; +import { MediaControl } from '../../utils/media-control'; const { cleanEmptyObject, @@ -98,7 +104,11 @@ export default function CoverInspectorControls( { setOverlayColor, coverRef, currentSettings, + onSelectMedia, + onUploadError, + toggleUseFeaturedImage, updateDimRatio, + onClearMedia, featuredImage, } ) { const { @@ -138,6 +148,24 @@ export default function CoverInspectorControls( { }, [ clientId ] ); + /* + * The block only resolves the featured image record, so the record of a + * media selection of its own is resolved here to name it in the panel. + */ + const selectedMedia = useSelect( + ( select ) => + id && ! useFeaturedImage + ? select( coreStore ).getEntityRecord( + 'postType', + 'attachment', + id, + { context: 'view' } + ) + : undefined, + [ id, useFeaturedImage ] + ); + const mediaRecord = useFeaturedImage ? featuredImage : selectedMedia; + const hasSelectedStyleState = ! isDefaultBlockStyleState( selectedStyleState ); const selectedStyleStateKey = getStyleStateKey( selectedStyleState ); @@ -277,8 +305,49 @@ export default function CoverInspectorControls( { const dropdownMenuProps = useToolsPanelDropdownMenuProps(); + /* + * Rendered whether or not media has been set, so that a cover in its setup + * state can be given media from the inspector as well as from the toolbar. + * The settings below stay behind their own condition, having nothing to + * configure until there is media to configure. + */ + const mediaInspectorPanel = ( + + + !! url || !! useFeaturedImage } + onDeselect={ onClearMedia } + isShownByDefault + > + + + + + ); + return ( <> + { mediaInspectorPanel } { ( !! url || useFeaturedImage ) && ( Date: Fri, 11 Sep 2026 11:59:09 +0530 Subject: [PATCH 2/8] feat: Add media-control changes --- .../block-library/src/utils/media-control.jsx | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/block-library/src/utils/media-control.jsx b/packages/block-library/src/utils/media-control.jsx index 32f119ab0a0c16..63819711d33204 100644 --- a/packages/block-library/src/utils/media-control.jsx +++ b/packages/block-library/src/utils/media-control.jsx @@ -76,16 +76,18 @@ export function MediaControlPreview( { * MediaControl - Complete media selection control for inspector panels * * @param {Object} props - * @param {number} props.mediaId Media attachment ID - * @param {string} props.mediaUrl Media URL - * @param {string} props.filename Filename to display - * @param {Array} props.allowedTypes Allowed media types - * @param {Function} props.onSelect Callback when media selected - * @param {Function} props.onSelectURL Callback when URL entered - * @param {Function} props.onError Error callback - * @param {Function} props.onReset Reset/remove callback - * @param {boolean} props.isUploading Whether upload in progress - * @param {string} props.emptyLabel Label when no media (default: 'Add media') + * @param {number} props.mediaId Media attachment ID + * @param {string} props.mediaUrl Media URL + * @param {string} props.filename Filename to display + * @param {Array} props.allowedTypes Allowed media types + * @param {Function} props.onSelect Callback when media selected + * @param {Function} props.onSelectURL Callback when URL entered + * @param {Function} props.onError Error callback + * @param {Function} props.onReset Reset/remove callback + * @param {boolean} props.isUploading Whether upload in progress + * @param {string} props.emptyLabel Label when no media (default: 'Add media') + * @param {boolean} props.useFeaturedImage Whether the featured image is in use + * @param {Function} props.onToggleFeaturedImage Callback toggling the featured image * @return {Element} Media control component */ export function MediaControl( { @@ -99,6 +101,8 @@ export function MediaControl( { onReset, isUploading = false, emptyLabel = __( 'Media' ), + useFeaturedImage, + onToggleFeaturedImage, } ) { const { getSettings } = useSelect( blockEditorStore ); const onFilesDrop = ( filesList ) => { @@ -131,6 +135,8 @@ export function MediaControl( { onSelect={ onSelect } onSelectURL={ onSelectURL } onError={ onError } + useFeaturedImage={ useFeaturedImage } + onToggleFeaturedImage={ onToggleFeaturedImage } name={ Date: Mon, 14 Sep 2026 17:59:21 +0530 Subject: [PATCH 3/8] chore: Unsynced patterns selected cover panel show in the settings --- packages/block-library/src/cover/edit/index.jsx | 1 + packages/block-library/src/cover/edit/inspector-controls.jsx | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/cover/edit/index.jsx b/packages/block-library/src/cover/edit/index.jsx index b80429174f0b08..ed2f4f61d034d5 100644 --- a/packages/block-library/src/cover/edit/index.jsx +++ b/packages/block-library/src/cover/edit/index.jsx @@ -709,6 +709,7 @@ function CoverEdit( { updateDimRatio={ onUpdateDimRatio } onClearMedia={ onClearMedia } featuredImage={ media } + isSelected={ isSelected } /> ); diff --git a/packages/block-library/src/cover/edit/inspector-controls.jsx b/packages/block-library/src/cover/edit/inspector-controls.jsx index c8e8b7c074b49e..75922ed9b765db 100644 --- a/packages/block-library/src/cover/edit/inspector-controls.jsx +++ b/packages/block-library/src/cover/edit/inspector-controls.jsx @@ -110,6 +110,7 @@ export default function CoverInspectorControls( { updateDimRatio, onClearMedia, featuredImage, + isSelected, } ) { const { useFeaturedImage, @@ -347,7 +348,7 @@ export default function CoverInspectorControls( { return ( <> - { mediaInspectorPanel } + { isSelected && mediaInspectorPanel } { ( !! url || useFeaturedImage ) && ( Date: Tue, 15 Sep 2026 15:50:50 +0530 Subject: [PATCH 4/8] fix: CI failing tests --- .../src/cover/test/edit.browser.test.js | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/cover/test/edit.browser.test.js b/packages/block-library/src/cover/test/edit.browser.test.js index c68b34a91d05d1..457ca89e468b15 100644 --- a/packages/block-library/src/cover/test/edit.browser.test.js +++ b/packages/block-library/src/cover/test/edit.browser.test.js @@ -66,6 +66,16 @@ async function openStylesTabIfAvailable() { } } +async function openSettingsTabIfAvailable() { + const settingsTab = screen.queryByRole( 'tab', { + name: 'Settings', + } ); + + if ( settingsTab ) { + await userEvent.click( settingsTab ); + } +} + describe( 'Cover block', () => { beforeEach( () => registerCoreBlocks() ); @@ -207,11 +217,12 @@ describe( 'Cover block', () => { } ) ).not.toBeInTheDocument(); } ); - test( 'does not display settings tab when media settings are empty', async () => { + test( 'does not display media settings panel when media settings are empty', async () => { await createAndSelectBlock(); + await openSettingsTabIfAvailable(); expect( - screen.queryByRole( 'tab', { + screen.queryByRole( 'heading', { name: 'Settings', } ) ).not.toBeInTheDocument(); @@ -227,6 +238,7 @@ describe( 'Cover block', () => { } ); await selectBlock( 'Block: Cover' ); + await openSettingsTabIfAvailable(); expect( await screen.findByRole( 'heading', { name: 'Settings' } ) ).toBeInTheDocument(); @@ -241,6 +253,7 @@ describe( 'Cover block', () => { 'has-parallax' ); await selectBlock( 'Block: Cover' ); + await openSettingsTabIfAvailable(); await userEvent.click( await screen.findByLabelText( 'Fixed background' ) ); @@ -257,6 +270,7 @@ describe( 'Cover block', () => { 'is-repeated' ); await selectBlock( 'Block: Cover' ); + await openSettingsTabIfAvailable(); await userEvent.click( await screen.findByLabelText( 'Repeated background' ) ); @@ -271,6 +285,7 @@ describe( 'Cover block', () => { } ); await selectBlock( 'Block: Cover' ); + await openSettingsTabIfAvailable(); await userEvent.clear( await screen.findByLabelText( 'Left' ) ); await userEvent.type( screen.getByLabelText( 'Left' ), '100' ); @@ -288,6 +303,7 @@ describe( 'Cover block', () => { } ); await selectBlock( 'Block: Cover' ); + await openSettingsTabIfAvailable(); await userEvent.type( await screen.findByLabelText( 'Alternative text' ), 'Me' From 9d2840b64bce2cabec4ac76d95f75b94a67b898f Mon Sep 17 00:00:00 2001 From: im3dabasia Date: Tue, 15 Sep 2026 17:31:30 +0530 Subject: [PATCH 5/8] fix: Failing CI tests --- test/e2e/specs/editor/blocks/cover.spec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index c3b91e21030073..3a876c618fc72a 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -403,6 +403,9 @@ test.describe( 'Cover', () => { await editor.selectBlocks( coverBlock ); + // The focal point picker is in the Settings tab of the block inspector. + await page.getByRole( 'tab', { name: 'Settings' } ).click(); + // The focal point picker renders as a `legend`-labelled group, so both // spinbuttons are resolved through it. const focalPointGroup = page.getByRole( 'group', { From eaad2398d256c39daa4f3b27ada7eb5965e8a70a Mon Sep 17 00:00:00 2001 From: im3dabasia Date: Tue, 22 Sep 2026 18:35:08 +0530 Subject: [PATCH 6/8] Cover: Remove duplicate hasSelectedStyleState declaration from trunk merge --- .../src/cover/edit/inspector-controls.jsx | 23 ++----------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/packages/block-library/src/cover/edit/inspector-controls.jsx b/packages/block-library/src/cover/edit/inspector-controls.jsx index fee111ea0497c9..1b1023af226a7b 100644 --- a/packages/block-library/src/cover/edit/inspector-controls.jsx +++ b/packages/block-library/src/cover/edit/inspector-controls.jsx @@ -149,26 +149,7 @@ export default function CoverInspectorControls( { }, [ clientId ] ); - /* - * The block only resolves the featured image record, so the record of a - * media selection of its own is resolved here to name it in the panel. - */ - const selectedMedia = useSelect( - ( select ) => - id && ! useFeaturedImage - ? select( coreStore ).getEntityRecord( - 'postType', - 'attachment', - id, - { context: 'view' } - ) - : undefined, - [ id, useFeaturedImage ] - ); - const mediaRecord = useFeaturedImage ? featuredImage : selectedMedia; - const hasSelectedStyleState = - ! isDefaultBlockStyleState( selectedStyleState ); const selectedStyleStateKey = getStyleStateKey( selectedStyleState ); const stateMinHeight = getActiveDimensionValue( { attributes, @@ -329,8 +310,8 @@ export default function CoverInspectorControls( { mediaId={ id } mediaUrl={ url } filename={ - mediaRecord?.media_details?.sizes?.full?.file || - mediaRecord?.slug || + image?.media_details?.sizes?.full?.file || + image?.slug || getFilename( url ) } allowedTypes={ ALLOWED_MEDIA_TYPES } From 2d303ba739b02191989d9a689ecaf9f2247dee8d Mon Sep 17 00:00:00 2001 From: im3dabasia Date: Tue, 22 Sep 2026 18:46:12 +0530 Subject: [PATCH 7/8] Cover: Only build the Media panel when the block is selected --- .../block-library/src/cover/edit/inspector-controls.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/cover/edit/inspector-controls.jsx b/packages/block-library/src/cover/edit/inspector-controls.jsx index 1b1023af226a7b..f01399603e52d9 100644 --- a/packages/block-library/src/cover/edit/inspector-controls.jsx +++ b/packages/block-library/src/cover/edit/inspector-controls.jsx @@ -293,7 +293,7 @@ export default function CoverInspectorControls( { * The settings below stay behind their own condition, having nothing to * configure until there is media to configure. */ - const mediaInspectorPanel = ( + const mediaInspectorPanel = isSelected ? ( - ); + ) : null; return ( <> - { isSelected && mediaInspectorPanel } + { mediaInspectorPanel } { ( !! url || useFeaturedImage ) && ( Date: Tue, 22 Sep 2026 18:50:10 +0530 Subject: [PATCH 8/8] Cover: Clarify the empty Settings panel test name --- packages/block-library/src/cover/test/edit.browser.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/cover/test/edit.browser.test.js b/packages/block-library/src/cover/test/edit.browser.test.js index 457ca89e468b15..4ccc6e4ca2a755 100644 --- a/packages/block-library/src/cover/test/edit.browser.test.js +++ b/packages/block-library/src/cover/test/edit.browser.test.js @@ -217,7 +217,7 @@ describe( 'Cover block', () => { } ) ).not.toBeInTheDocument(); } ); - test( 'does not display media settings panel when media settings are empty', async () => { + test( 'does not display settings panel in the settings tab when the block has no media', async () => { await createAndSelectBlock(); await openSettingsTabIfAvailable();