From 2fa125097bab64fb0d67d12ca9db232edb742ed1 Mon Sep 17 00:00:00 2001 From: annezazu Date: Tue, 3 Mar 2026 17:05:41 -0800 Subject: [PATCH 1/5] Add Site Logo & Icon screen to Design panel Move site logo and icon management to a top-level Design panel route instead of a sub-screen inside Global Styles. Uses DataForm with MediaEdit for a clean, declarative approach (~80 lines vs ~400 lines in the previous manual MediaReplaceFlow implementation). Co-Authored-By: Claude Opus 4.6 --- packages/block-library/src/site-logo/edit.js | 30 +------ .../sidebar-navigation-screen-main/index.js | 17 +++- .../index.js | 38 +++++++++ .../sidebar-site-logo-and-icon/index.js | 79 +++++++++++++++++++ .../components/site-editor-routes/index.js | 2 + .../site-editor-routes/site-logo-and-icon.js | 39 +++++++++ 6 files changed, 177 insertions(+), 28 deletions(-) create mode 100644 packages/edit-site/src/components/sidebar-navigation-screen-site-logo-and-icon/index.js create mode 100644 packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js create mode 100644 packages/edit-site/src/components/site-editor-routes/site-logo-and-icon.js diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index 3a97c9d4c8448c..a9ae18c15eefa4 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -7,11 +7,7 @@ import clsx from 'clsx'; * WordPress dependencies */ import { isBlobURL } from '@wordpress/blob'; -import { - createInterpolateElement, - useEffect, - useState, -} from '@wordpress/element'; +import { useEffect, useState } from '@wordpress/element'; import { __, isRTL } from '@wordpress/i18n'; import { RangeControl, @@ -257,28 +253,8 @@ const SiteLogo = ( { ); } - // Support the previous location for the Site Icon settings. To be removed - // when the required WP core version for Gutenberg is >= 6.5.0. - const shouldUseNewUrl = ! window?.__experimentalUseCustomizerSiteLogoUrl; - - const siteIconSettingsUrl = shouldUseNewUrl - ? siteUrl + '/wp-admin/options-general.php' - : siteUrl + '/wp-admin/customize.php?autofocus[section]=title_tagline'; - - const syncSiteIconHelpText = createInterpolateElement( - __( - 'Site Icons are what you see in browser tabs, bookmark bars, and within the WordPress mobile apps. To use a custom icon that is different from your site logo, use the Site Icon settings.' - ), - { - a: ( - // eslint-disable-next-line jsx-a11y/anchor-has-content - - ), - } + const syncSiteIconHelpText = __( + 'Site Icons are what you see in browser tabs, bookmark bars, and within the WordPress mobile apps.' ); return ( diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js index 1420dc6ca9a175..038ffc0334503d 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js @@ -3,7 +3,14 @@ */ import { __experimentalItemGroup as ItemGroup } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { layout, symbol, navigation, styles, page } from '@wordpress/icons'; +import { + layout, + symbol, + navigation, + styles, + page, + siteLogo, +} from '@wordpress/icons'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; @@ -13,6 +20,7 @@ import { store as coreStore } from '@wordpress/core-data'; import SidebarNavigationScreen from '../sidebar-navigation-screen'; import SidebarNavigationItem from '../sidebar-navigation-item'; import { SidebarNavigationItemGlobalStyles } from '../sidebar-navigation-screen-global-styles'; +import { SidebarNavigationItemSiteLogoAndIcon } from '../sidebar-navigation-screen-site-logo-and-icon'; export function MainSidebarNavigationContent( { isBlockBasedTheme = true } ) { return ( @@ -34,6 +42,13 @@ export function MainSidebarNavigationContent( { isBlockBasedTheme = true } ) { > { __( 'Navigation' ) } + + { __( 'Site Logo & Icon' ) } + + ); +} + +export default function SidebarNavigationScreenSiteLogoAndIcon() { + return ( + } + /> + ); +} diff --git a/packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js b/packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js new file mode 100644 index 00000000000000..a5fe69f8968f3c --- /dev/null +++ b/packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js @@ -0,0 +1,79 @@ +/** + * WordPress dependencies + */ +import { Page } from '@wordpress/admin-ui'; +import { __ } from '@wordpress/i18n'; +import { useMemo } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { DataForm } from '@wordpress/dataviews'; +import { MediaEdit } from '@wordpress/fields'; + +const fields = [ + { + id: 'site_logo', + type: 'media', + label: __( 'Site Logo' ), + description: __( 'Upload a logo to display in the Site Logo block.' ), + Edit: MediaEdit, + setValue: ( { value } ) => ( { + site_logo: value ?? 0, + } ), + enableSorting: false, + filterBy: false, + }, + { + id: 'site_icon', + type: 'media', + label: __( 'Site Icon' ), + description: __( + 'Site Icons are what you see in browser tabs, bookmark bars, and within the WordPress mobile apps. It should be square and at least 512 by 512 pixels.' + ), + Edit: MediaEdit, + setValue: ( { value } ) => ( { + site_icon: value ?? 0, + } ), + enableSorting: false, + filterBy: false, + }, +]; + +const form = { + layout: { + type: 'regular', + labelPosition: 'top', + }, + fields: [ 'site_logo', 'site_icon' ], +}; + +export default function SidebarSiteLogoAndIcon() { + const { record } = useSelect( ( select ) => { + const { getEditedEntityRecord } = select( coreStore ); + return { + record: getEditedEntityRecord( 'root', 'site' ), + }; + }, [] ); + const { editEntityRecord } = useDispatch( coreStore ); + + const data = useMemo( () => { + return { + site_logo: record?.site_logo ?? 0, + site_icon: record?.site_icon ?? 0, + }; + }, [ record?.site_logo, record?.site_icon ] ); + + const onChange = ( edits ) => { + editEntityRecord( 'root', 'site', undefined, edits ); + }; + + return ( + + + + ); +} diff --git a/packages/edit-site/src/components/site-editor-routes/index.js b/packages/edit-site/src/components/site-editor-routes/index.js index 3be552aeb6061b..976190b1ff7fec 100644 --- a/packages/edit-site/src/components/site-editor-routes/index.js +++ b/packages/edit-site/src/components/site-editor-routes/index.js @@ -10,6 +10,7 @@ import { useEffect } from '@wordpress/element'; import { unlock } from '../../lock-unlock'; import { store as siteEditorStore } from '../../store'; import { homeRoute } from './home'; +import { siteLogoAndIconRoute } from './site-logo-and-icon'; import { stylesRoute } from './styles'; import { navigationRoute } from './navigation'; import { navigationItemRoute } from './navigation-item'; @@ -35,6 +36,7 @@ const routes = [ patternsRoute, navigationItemRoute, navigationRoute, + siteLogoAndIconRoute, stylesRoute, homeRoute, stylebookRoute, diff --git a/packages/edit-site/src/components/site-editor-routes/site-logo-and-icon.js b/packages/edit-site/src/components/site-editor-routes/site-logo-and-icon.js new file mode 100644 index 00000000000000..d37dbecc607dc2 --- /dev/null +++ b/packages/edit-site/src/components/site-editor-routes/site-logo-and-icon.js @@ -0,0 +1,39 @@ +/** + * WordPress dependencies + */ +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import Editor from '../editor'; +import { unlock } from '../../lock-unlock'; +import SidebarNavigationScreenSiteLogoAndIcon from '../sidebar-navigation-screen-site-logo-and-icon'; +import SidebarSiteLogoAndIcon from '../sidebar-site-logo-and-icon'; + +const { useLocation } = unlock( routerPrivateApis ); + +function MobileSiteLogoAndIconView() { + const { query = {} } = useLocation(); + const { canvas } = query; + + if ( canvas === 'edit' ) { + return ; + } + + return ; +} + +export const siteLogoAndIconRoute = { + name: 'site-logo-and-icon', + path: '/site-logo-and-icon', + areas: { + sidebar: , + content: , + preview: , + mobile: , + }, + widths: { + content: 380, + }, +}; From 24aaddc51ac4b702a04f4f2af130487a6983eddf Mon Sep 17 00:00:00 2001 From: annezazu Date: Wed, 4 Mar 2026 14:16:18 -0800 Subject: [PATCH 2/5] Rename section to Identity and address review feedback - Rename "Site Logo & Icon" to "Identity" in page title and sidebar nav - Add descriptive subtitle to the Identity page - Update field descriptions per design feedback - Add placeholder text ("Choose logo" / "Choose icon") - Remove unnecessary enableSorting and filterBy props Co-Authored-By: Claude Opus 4.6 --- .../sidebar-navigation-screen-main/index.js | 2 +- .../sidebar-site-logo-and-icon/index.js | 20 ++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js index 038ffc0334503d..ad99ab6efbbf18 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js @@ -47,7 +47,7 @@ export function MainSidebarNavigationContent( { isBlockBasedTheme = true } ) { uid="site-logo-and-icon-navigation-item" icon={ siteLogo } > - { __( 'Site Logo & Icon' ) } + { __( 'Identity' ) } ( { site_logo: value ?? 0, } ), - enableSorting: false, - filterBy: false, }, { id: 'site_icon', type: 'media', label: __( 'Site Icon' ), description: __( - 'Site Icons are what you see in browser tabs, bookmark bars, and within the WordPress mobile apps. It should be square and at least 512 by 512 pixels.' + 'Shown in browser tabs, bookmarks, and mobile apps. It should be square and at least 512 by 512 pixels.' ), + placeholder: __( 'Choose icon' ), Edit: MediaEdit, setValue: ( { value } ) => ( { site_icon: value ?? 0, } ), - enableSorting: false, - filterBy: false, }, ]; @@ -67,7 +67,13 @@ export default function SidebarSiteLogoAndIcon() { }; return ( - + Date: Thu, 5 Mar 2026 13:49:08 +0200 Subject: [PATCH 3/5] simplify SidebarSiteLogoAndIcon --- .../sidebar-site-logo-and-icon/index.js | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js b/packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js index 360f7d7a9f9fe4..507f14c19ef98a 100644 --- a/packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js +++ b/packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js @@ -3,7 +3,6 @@ */ import { Page } from '@wordpress/admin-ui'; import { __ } from '@wordpress/i18n'; -import { useMemo } from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { DataForm } from '@wordpress/dataviews'; @@ -47,20 +46,13 @@ const form = { }; export default function SidebarSiteLogoAndIcon() { - const { record } = useSelect( ( select ) => { - const { getEditedEntityRecord } = select( coreStore ); - return { - record: getEditedEntityRecord( 'root', 'site' ), - }; - }, [] ); - const { editEntityRecord } = useDispatch( coreStore ); + const data = useSelect( + ( select ) => + select( coreStore ).getEditedEntityRecord( 'root', 'site' ), - const data = useMemo( () => { - return { - site_logo: record?.site_logo ?? 0, - site_icon: record?.site_icon ?? 0, - }; - }, [ record?.site_logo, record?.site_icon ] ); + [] + ); + const { editEntityRecord } = useDispatch( coreStore ); const onChange = ( edits ) => { editEntityRecord( 'root', 'site', undefined, edits ); From b6ef24913f387987e5dd5dc2623fbb9d91330beb Mon Sep 17 00:00:00 2001 From: annezazu Date: Thu, 5 Mar 2026 12:27:51 -0800 Subject: [PATCH 4/5] Address review feedback: rename to identity, revert block changes - Rename files, components, and route from `site-logo-and-icon` to `identity` to match the section name. - Revert out-of-scope changes to site-logo block's edit.js. - Remove Identity section description. - Ensure site logo is listed before site icon in save panel. Co-Authored-By: Claude Opus 4.6 --- packages/block-library/src/site-logo/edit.js | 30 ++++++++++++-- .../index.js | 11 +----- .../index.js | 6 +-- .../sidebar-navigation-screen-main/index.js | 10 ++--- .../components/site-editor-routes/identity.js | 39 +++++++++++++++++++ .../components/site-editor-routes/index.js | 4 +- .../site-editor-routes/site-logo-and-icon.js | 39 ------------------- .../hooks/use-is-dirty.js | 19 ++++++--- 8 files changed, 92 insertions(+), 66 deletions(-) rename packages/edit-site/src/components/{sidebar-site-logo-and-icon => sidebar-identity}/index.js (80%) rename packages/edit-site/src/components/{sidebar-navigation-screen-site-logo-and-icon => sidebar-navigation-screen-identity}/index.js (81%) create mode 100644 packages/edit-site/src/components/site-editor-routes/identity.js delete mode 100644 packages/edit-site/src/components/site-editor-routes/site-logo-and-icon.js diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index a9ae18c15eefa4..3a97c9d4c8448c 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -7,7 +7,11 @@ import clsx from 'clsx'; * WordPress dependencies */ import { isBlobURL } from '@wordpress/blob'; -import { useEffect, useState } from '@wordpress/element'; +import { + createInterpolateElement, + useEffect, + useState, +} from '@wordpress/element'; import { __, isRTL } from '@wordpress/i18n'; import { RangeControl, @@ -253,8 +257,28 @@ const SiteLogo = ( { ); } - const syncSiteIconHelpText = __( - 'Site Icons are what you see in browser tabs, bookmark bars, and within the WordPress mobile apps.' + // Support the previous location for the Site Icon settings. To be removed + // when the required WP core version for Gutenberg is >= 6.5.0. + const shouldUseNewUrl = ! window?.__experimentalUseCustomizerSiteLogoUrl; + + const siteIconSettingsUrl = shouldUseNewUrl + ? siteUrl + '/wp-admin/options-general.php' + : siteUrl + '/wp-admin/customize.php?autofocus[section]=title_tagline'; + + const syncSiteIconHelpText = createInterpolateElement( + __( + 'Site Icons are what you see in browser tabs, bookmark bars, and within the WordPress mobile apps. To use a custom icon that is different from your site logo, use the Site Icon settings.' + ), + { + a: ( + // eslint-disable-next-line jsx-a11y/anchor-has-content + + ), + } ); return ( diff --git a/packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js b/packages/edit-site/src/components/sidebar-identity/index.js similarity index 80% rename from packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js rename to packages/edit-site/src/components/sidebar-identity/index.js index 507f14c19ef98a..f24bb4bfaaca07 100644 --- a/packages/edit-site/src/components/sidebar-site-logo-and-icon/index.js +++ b/packages/edit-site/src/components/sidebar-identity/index.js @@ -45,11 +45,10 @@ const form = { fields: [ 'site_logo', 'site_icon' ], }; -export default function SidebarSiteLogoAndIcon() { +export default function SidebarIdentity() { const data = useSelect( ( select ) => select( coreStore ).getEditedEntityRecord( 'root', 'site' ), - [] ); const { editEntityRecord } = useDispatch( coreStore ); @@ -59,13 +58,7 @@ export default function SidebarSiteLogoAndIcon() { }; return ( - + ); } -export default function SidebarNavigationScreenSiteLogoAndIcon() { +export default function SidebarNavigationScreenIdentity() { return ( { __( 'Navigation' ) } - { __( 'Identity' ) } - + ; + } + + return ; +} + +export const identityRoute = { + name: 'identity', + path: '/identity', + areas: { + sidebar: , + content: , + preview: , + mobile: , + }, + widths: { + content: 380, + }, +}; diff --git a/packages/edit-site/src/components/site-editor-routes/index.js b/packages/edit-site/src/components/site-editor-routes/index.js index 976190b1ff7fec..231cae42894f69 100644 --- a/packages/edit-site/src/components/site-editor-routes/index.js +++ b/packages/edit-site/src/components/site-editor-routes/index.js @@ -10,7 +10,7 @@ import { useEffect } from '@wordpress/element'; import { unlock } from '../../lock-unlock'; import { store as siteEditorStore } from '../../store'; import { homeRoute } from './home'; -import { siteLogoAndIconRoute } from './site-logo-and-icon'; +import { identityRoute } from './identity'; import { stylesRoute } from './styles'; import { navigationRoute } from './navigation'; import { navigationItemRoute } from './navigation-item'; @@ -36,7 +36,7 @@ const routes = [ patternsRoute, navigationItemRoute, navigationRoute, - siteLogoAndIconRoute, + identityRoute, stylesRoute, homeRoute, stylebookRoute, diff --git a/packages/edit-site/src/components/site-editor-routes/site-logo-and-icon.js b/packages/edit-site/src/components/site-editor-routes/site-logo-and-icon.js deleted file mode 100644 index d37dbecc607dc2..00000000000000 --- a/packages/edit-site/src/components/site-editor-routes/site-logo-and-icon.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * WordPress dependencies - */ -import { privateApis as routerPrivateApis } from '@wordpress/router'; - -/** - * Internal dependencies - */ -import Editor from '../editor'; -import { unlock } from '../../lock-unlock'; -import SidebarNavigationScreenSiteLogoAndIcon from '../sidebar-navigation-screen-site-logo-and-icon'; -import SidebarSiteLogoAndIcon from '../sidebar-site-logo-and-icon'; - -const { useLocation } = unlock( routerPrivateApis ); - -function MobileSiteLogoAndIconView() { - const { query = {} } = useLocation(); - const { canvas } = query; - - if ( canvas === 'edit' ) { - return ; - } - - return ; -} - -export const siteLogoAndIconRoute = { - name: 'site-logo-and-icon', - path: '/site-logo-and-icon', - areas: { - sidebar: , - content: , - preview: , - mobile: , - }, - widths: { - content: 380, - }, -}; diff --git a/packages/editor/src/components/entities-saved-states/hooks/use-is-dirty.js b/packages/editor/src/components/entities-saved-states/hooks/use-is-dirty.js index 2c3061e908c8d7..0ff2017be2f484 100644 --- a/packages/editor/src/components/entities-saved-states/hooks/use-is-dirty.js +++ b/packages/editor/src/components/entities-saved-states/hooks/use-is-dirty.js @@ -39,15 +39,24 @@ export const useIsDirty = () => { ); const siteEntityLabels = siteEntityConfig?.meta?.labels ?? {}; - const editedSiteEntities = []; - for ( const property in siteEdits ) { - editedSiteEntities.push( { + const { + site_logo: siteLogoEdit, + site_icon: siteIconEdit, + ...otherSiteEdits + } = siteEdits ?? {}; + const orderedSiteProperties = [ + siteLogoEdit !== undefined && 'site_logo', + siteIconEdit !== undefined && 'site_icon', + ...Object.keys( otherSiteEdits ), + ].filter( Boolean ); + const editedSiteEntities = orderedSiteProperties.map( + ( property ) => ( { kind: 'root', name: 'site', title: siteEntityLabels[ property ] || property, property, - } ); - } + } ) + ); return [ ...editedEntitiesWithoutSite, ...editedSiteEntities ]; }, [ editedEntities, siteEdits, siteEntityConfig ] ); From a76d816bc912beb011bcc7fe31f11082d46f0874 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Fri, 6 Mar 2026 11:01:24 +0200 Subject: [PATCH 5/5] do not animate sidebar on `identity` --- packages/edit-site/src/components/layout/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index 1c44937ab6b2a3..2b706e1160452f 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -138,7 +138,8 @@ function Layout() {