From 58ea5ecd3d1175f84b6b80634fe37d852f552cd8 Mon Sep 17 00:00:00 2001 From: Faisal Ahammad Date: Wed, 5 Aug 2026 03:38:30 +0600 Subject: [PATCH 1/2] Administration: Replace Dashicons with SVG icons in sidebar navigation Replace the Dashicons icon font glyphs on the default top-level admin menu items with inline SVG icons from the core icon library, via wp_get_icon(). Covers Dashboard, Posts, Media, Pages, Comments, Appearance, Plugins, Users, Tools, Settings, and the Collapse menu button. The menu icon API is unchanged: plugin and theme icons, base64 data URIs, and dashicons classes all continue to work as before. The Dashicons font remains registered for plugins that still use it. Adds the corresponding SVGs to the core icon library and updates the generated icon library manifest. Props to those involved in the icons API work in wp-includes. Fixes #65387. See WordPress/wordpress-develop#12270. --- src/wp-admin/css/admin-menu.css | 67 ++++++++++++++----- src/wp-admin/css/colors/_admin.scss | 17 ++++- src/wp-admin/menu-header.php | 11 ++- src/wp-admin/menu.php | 27 ++++---- src/wp-admin/network/menu.php | 14 ++-- .../assets/icon-library-manifest.php | 32 +++++++++ src/wp-includes/images/icon-library/brush.svg | 3 + .../images/icon-library/dashboard.svg | 3 + src/wp-includes/images/icon-library/link.svg | 3 + src/wp-includes/images/icon-library/media.svg | 4 ++ src/wp-includes/images/icon-library/page.svg | 4 ++ .../images/icon-library/plugins.svg | 3 + src/wp-includes/images/icon-library/post.svg | 3 + src/wp-includes/images/icon-library/tool.svg | 3 + src/wp-includes/post.php | 6 +- tests/phpunit/tests/post/types.php | 6 +- tests/qunit/fixtures/wp-api-generated.js | 8 +-- 17 files changed, 161 insertions(+), 53 deletions(-) create mode 100644 src/wp-includes/images/icon-library/brush.svg create mode 100644 src/wp-includes/images/icon-library/dashboard.svg create mode 100644 src/wp-includes/images/icon-library/link.svg create mode 100644 src/wp-includes/images/icon-library/media.svg create mode 100644 src/wp-includes/images/icon-library/page.svg create mode 100644 src/wp-includes/images/icon-library/plugins.svg create mode 100644 src/wp-includes/images/icon-library/post.svg create mode 100644 src/wp-includes/images/icon-library/tool.svg diff --git a/src/wp-admin/css/admin-menu.css b/src/wp-admin/css/admin-menu.css index 3747613282be1..ef629f182e3b5 100644 --- a/src/wp-admin/css/admin-menu.css +++ b/src/wp-admin/css/admin-menu.css @@ -288,6 +288,19 @@ background-size: 20px auto; } +#adminmenu div.wp-menu-image.svg-icon { + display: flex; + align-items: center; + justify-content: center; +} + +#adminmenu div.wp-menu-image.svg-icon svg { + width: 22px; + height: 22px; + fill: currentColor; + transition: color .1s ease-in-out; +} + div.wp-menu-image:before { color: #a7aaad; color: rgba(240, 246, 252, 0.6); @@ -295,24 +308,35 @@ div.wp-menu-image:before { transition: all .1s ease-in-out; } -#adminmenu div.wp-menu-image:before { +#adminmenu div.wp-menu-image:before, +#adminmenu div.wp-menu-image.svg-icon svg { color: #a7aaad; color: rgba(240, 246, 252, 0.6); } #adminmenu li.wp-has-current-submenu:hover div.wp-menu-image:before, +#adminmenu li.wp-has-current-submenu:hover div.wp-menu-image.svg-icon svg, #adminmenu .wp-has-current-submenu div.wp-menu-image:before, +#adminmenu .wp-has-current-submenu div.wp-menu-image.svg-icon svg, #adminmenu .current div.wp-menu-image:before, +#adminmenu .current div.wp-menu-image.svg-icon svg, #adminmenu a.wp-has-current-submenu:hover div.wp-menu-image:before, +#adminmenu a.wp-has-current-submenu:hover div.wp-menu-image.svg-icon svg, #adminmenu a.current:hover div.wp-menu-image:before, +#adminmenu a.current:hover div.wp-menu-image.svg-icon svg, #adminmenu li.wp-has-current-submenu a:focus div.wp-menu-image:before, -#adminmenu li.wp-has-current-submenu.opensub div.wp-menu-image:before { +#adminmenu li.wp-has-current-submenu a:focus div.wp-menu-image.svg-icon svg, +#adminmenu li.wp-has-current-submenu.opensub div.wp-menu-image:before, +#adminmenu li.wp-has-current-submenu.opensub div.wp-menu-image.svg-icon svg { color: #fff; } #adminmenu li:hover div.wp-menu-image:before, +#adminmenu li:hover div.wp-menu-image.svg-icon svg, #adminmenu li a:focus div.wp-menu-image:before, -#adminmenu li.opensub div.wp-menu-image:before { +#adminmenu li a:focus div.wp-menu-image.svg-icon svg, +#adminmenu li.opensub div.wp-menu-image:before, +#adminmenu li.opensub div.wp-menu-image.svg-icon svg { color: #72aee6; } @@ -323,6 +347,10 @@ div.wp-menu-image:before { z-index: 25; } +.folded #adminmenu div.wp-menu-image.svg-icon { + height: 34px; +} + .folded #adminmenu a.menu-top { height: 34px; } @@ -497,6 +525,9 @@ ul#adminmenu > li.current > a.current:after { } #collapse-button .collapse-button-icon { + display: flex; + align-items: center; + justify-content: center; width: 36px; height: 34px; } @@ -509,29 +540,25 @@ ul#adminmenu > li.current > a.current:after { display: none; } -#collapse-button .collapse-button-icon:after { - content: "\f148"; - content: "\f148" / ''; - display: block; +#collapse-button .collapse-button-icon svg { + width: 22px; + height: 22px; + fill: currentColor; position: relative; - top: 7px; - text-align: center; - font: normal 20px/1 dashicons !important; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + top: -1px; } /* rtl:ignore */ -.folded #collapse-button .collapse-button-icon:after, -.rtl #collapse-button .collapse-button-icon:after { +.folded #collapse-button .collapse-button-icon svg, +.rtl #collapse-button .collapse-button-icon svg { transform: rotate(180deg); } -.rtl.folded #collapse-button .collapse-button-icon:after { +.rtl.folded #collapse-button .collapse-button-icon svg { transform: none; } -#collapse-button .collapse-button-icon:after, +#collapse-button .collapse-button-icon svg, #collapse-button .collapse-button-label { transition: all .1s ease-in-out; } @@ -615,6 +642,10 @@ li#wp-admin-bar-menu-toggle { z-index: 25; } + .auto-fold #adminmenu div.wp-menu-image.svg-icon { + height: 34px; + } + .auto-fold #adminmenu a.menu-top { min-height: 34px; } @@ -656,11 +687,11 @@ li#wp-admin-bar-menu-toggle { } /* rtl:ignore */ - .auto-fold #collapse-button .collapse-button-icon:after { + .auto-fold #collapse-button .collapse-button-icon svg { transform: rotate(180deg); } - .rtl.auto-fold #collapse-button .collapse-button-icon:after { + .rtl.auto-fold #collapse-button .collapse-button-icon svg { transform: none; } diff --git a/src/wp-admin/css/colors/_admin.scss b/src/wp-admin/css/colors/_admin.scss index 366f1b86b4f16..3ef892802a906 100644 --- a/src/wp-admin/css/colors/_admin.scss +++ b/src/wp-admin/css/colors/_admin.scss @@ -261,7 +261,8 @@ input[type="radio"]:focus { color: variables.$menu-text; } -#adminmenu div.wp-menu-image:before { +#adminmenu div.wp-menu-image:before, +#adminmenu div.wp-menu-image.svg-icon svg { color: variables.$menu-icon; } @@ -274,7 +275,9 @@ input[type="radio"]:focus { } #adminmenu li.menu-top:hover div.wp-menu-image:before, -#adminmenu li.opensub > a.menu-top div.wp-menu-image:before { +#adminmenu li.menu-top:hover div.wp-menu-image.svg-icon svg, +#adminmenu li.opensub > a.menu-top div.wp-menu-image:before, +#adminmenu li.opensub > a.menu-top div.wp-menu-image.svg-icon svg { color: variables.$menu-highlight-icon; } @@ -345,13 +348,21 @@ ul#adminmenu > li.current > a.current:after { } #adminmenu li.wp-has-current-submenu div.wp-menu-image:before, +#adminmenu li.wp-has-current-submenu div.wp-menu-image.svg-icon svg, #adminmenu a.current:hover div.wp-menu-image:before, +#adminmenu a.current:hover div.wp-menu-image.svg-icon svg, #adminmenu li.current div.wp-menu-image:before, +#adminmenu li.current div.wp-menu-image.svg-icon svg, #adminmenu li.wp-has-current-submenu a:focus div.wp-menu-image:before, +#adminmenu li.wp-has-current-submenu a:focus div.wp-menu-image.svg-icon svg, #adminmenu li.wp-has-current-submenu.opensub div.wp-menu-image:before, +#adminmenu li.wp-has-current-submenu.opensub div.wp-menu-image.svg-icon svg, #adminmenu li:hover div.wp-menu-image:before, +#adminmenu li:hover div.wp-menu-image.svg-icon svg, #adminmenu li a:focus div.wp-menu-image:before, -#adminmenu li.opensub div.wp-menu-image:before { +#adminmenu li a:focus div.wp-menu-image.svg-icon svg, +#adminmenu li.opensub div.wp-menu-image:before, +#adminmenu li.opensub div.wp-menu-image.svg-icon svg { color: variables.$menu-current-icon; } diff --git a/src/wp-admin/menu-header.php b/src/wp-admin/menu-header.php index 5cced0ceaed96..eee17f1cc469a 100644 --- a/src/wp-admin/menu-header.php +++ b/src/wp-admin/menu-header.php @@ -125,7 +125,8 @@ function _wp_menu_output( $menu, $submenu, $submenu_as_parent = true ) { * If the string 'none' (previously 'div') is passed instead of a URL, don't output * the default menu image so an icon can be added to div.wp-menu-image as background * with CSS. Dashicons and base64-encoded data:image/svg_xml URIs are also handled - * as special cases. + * as special cases. Any other value is looked up as a registered icon name and, if + * found, rendered as inline SVG; otherwise it is treated as an image URL. */ if ( ! empty( $item[6] ) ) { $img = ''; @@ -140,6 +141,12 @@ function _wp_menu_output( $menu, $submenu, $submenu_as_parent = true ) { } elseif ( str_starts_with( $item[6], 'dashicons-' ) ) { $img = '
'; $img_class = ' dashicons-before ' . sanitize_html_class( $item[6] ); + } else { + $icon = wp_get_icon( $item[6], array( 'size' => 22 ) ); + if ( '' !== $icon ) { + $img = $icon; + $img_class = ' svg-icon'; + } } } @@ -283,7 +290,7 @@ function _wp_menu_output( $menu, $submenu, $submenu_as_parent = true ) { echo '
  • ' . '
  • '; } diff --git a/src/wp-admin/menu.php b/src/wp-admin/menu.php index 2a3430ebc3df8..ce2ccf7f3b632 100644 --- a/src/wp-admin/menu.php +++ b/src/wp-admin/menu.php @@ -26,7 +26,7 @@ * @global array $menu */ -$menu[2] = array( __( 'Dashboard' ), 'read', 'index.php', '', 'menu-top menu-top-first menu-icon-dashboard', 'menu-dashboard', 'dashicons-dashboard' ); +$menu[2] = array( __( 'Dashboard' ), 'read', 'index.php', '', 'menu-top menu-top-first menu-icon-dashboard', 'menu-dashboard', 'core/dashboard' ); $submenu['index.php'][0] = array( __( 'Home' ), 'read', 'index.php' ); @@ -70,7 +70,7 @@ // $menu[5] = Posts. -$menu[10] = array( __( 'Media' ), 'upload_files', 'upload.php', '', 'menu-top menu-icon-media', 'menu-media', 'dashicons-admin-media' ); +$menu[10] = array( __( 'Media' ), 'upload_files', 'upload.php', '', 'menu-top menu-icon-media', 'menu-media', 'core/media' ); $submenu['upload.php'][5] = array( _x( 'Library', 'media library menu item' ), 'upload_files', 'upload.php' ); $submenu['upload.php'][10] = array( __( 'Add Media File' ), 'upload_files', 'media-new.php' ); @@ -86,7 +86,7 @@ unset( $taxonomy, $submenu_index ); -$menu[15] = array( __( 'Links' ), 'manage_links', 'link-manager.php', '', 'menu-top menu-icon-links', 'menu-links', 'dashicons-admin-links' ); +$menu[15] = array( __( 'Links' ), 'manage_links', 'link-manager.php', '', 'menu-top menu-icon-links', 'menu-links', 'core/link' ); $submenu['link-manager.php'][5] = array( _x( 'All Links', 'admin menu' ), 'manage_links', 'link-manager.php' ); $submenu['link-manager.php'][10] = array( __( 'Add Link' ), 'manage_links', 'link-add.php' ); @@ -110,7 +110,7 @@ '', 'menu-top menu-icon-comments', 'menu-comments', - 'dashicons-admin-comments', + 'core/comment', ); unset( $awaiting_moderation ); @@ -142,19 +142,20 @@ : ++$_wp_last_object_menu; // If we're to use $_wp_last_object_menu, increment it first. $post_type_for_id = sanitize_html_class( $post_type ); - $menu_icon = 'dashicons-admin-post'; + $menu_icon = 'core/post'; if ( is_string( $post_type_obj->menu_icon ) ) { - // Special handling for an empty div.wp-menu-image, data:image/svg+xml, and Dashicons. + // Special handling for an empty div.wp-menu-image, data:image/svg+xml, Dashicons, and registered icons. if ( 'none' === $post_type_obj->menu_icon || 'div' === $post_type_obj->menu_icon || str_starts_with( $post_type_obj->menu_icon, 'data:image/svg+xml;base64,' ) || str_starts_with( $post_type_obj->menu_icon, 'dashicons-' ) + || WP_Icons_Registry::get_instance()->is_registered( $post_type_obj->menu_icon ) ) { $menu_icon = $post_type_obj->menu_icon; } else { $menu_icon = esc_url( $post_type_obj->menu_icon ); } } elseif ( in_array( $post_type, $builtin, true ) ) { - $menu_icon = 'dashicons-admin-' . $post_type; + $menu_icon = 'core/' . $post_type; } $menu_class = 'menu-top menu-icon-' . $post_type_for_id; @@ -206,7 +207,7 @@ $appearance_capability = current_user_can( 'switch_themes' ) ? 'switch_themes' : 'edit_theme_options'; -$menu[60] = array( __( 'Appearance' ), $appearance_capability, 'themes.php', '', 'menu-top menu-icon-appearance', 'menu-appearance', 'dashicons-admin-appearance' ); +$menu[60] = array( __( 'Appearance' ), $appearance_capability, 'themes.php', '', 'menu-top menu-icon-appearance', 'menu-appearance', 'core/brush' ); $count = ''; if ( ! is_multisite() && current_user_can( 'update_themes' ) ) { @@ -320,7 +321,7 @@ function _add_plugin_file_editor_to_tools() { } /* translators: %s: Number of available plugin updates. */ -$menu[65] = array( sprintf( __( 'Plugins %s' ), $count ), 'activate_plugins', 'plugins.php', '', 'menu-top menu-icon-plugins', 'menu-plugins', 'dashicons-admin-plugins' ); +$menu[65] = array( sprintf( __( 'Plugins %s' ), $count ), 'activate_plugins', 'plugins.php', '', 'menu-top menu-icon-plugins', 'menu-plugins', 'core/plugins' ); $submenu['plugins.php'][5] = array( __( 'Installed Plugins' ), 'activate_plugins', 'plugins.php' ); @@ -337,9 +338,9 @@ function _add_plugin_file_editor_to_tools() { unset( $update_data ); if ( current_user_can( 'list_users' ) ) { - $menu[70] = array( __( 'Users' ), 'list_users', 'users.php', '', 'menu-top menu-icon-users', 'menu-users', 'dashicons-admin-users' ); + $menu[70] = array( __( 'Users' ), 'list_users', 'users.php', '', 'menu-top menu-icon-users', 'menu-users', 'core/people' ); } else { - $menu[70] = array( __( 'Profile' ), 'read', 'profile.php', '', 'menu-top menu-icon-users', 'menu-users', 'dashicons-admin-users' ); + $menu[70] = array( __( 'Profile' ), 'read', 'profile.php', '', 'menu-top menu-icon-users', 'menu-users', 'core/people' ); } if ( current_user_can( 'list_users' ) ) { @@ -387,7 +388,7 @@ function _add_plugin_file_editor_to_tools() { ); } -$menu[75] = array( __( 'Tools' ), 'edit_posts', 'tools.php', '', 'menu-top menu-icon-tools', 'menu-tools', 'dashicons-admin-tools' ); +$menu[75] = array( __( 'Tools' ), 'edit_posts', 'tools.php', '', 'menu-top menu-icon-tools', 'menu-tools', 'core/tool' ); $submenu['tools.php'][5] = array( __( 'Available Tools' ), 'edit_posts', 'tools.php' ); $submenu['tools.php'][10] = array( __( 'Import' ), 'import', 'import.php' ); $submenu['tools.php'][15] = array( __( 'Export' ), 'export', 'export.php' ); @@ -402,7 +403,7 @@ function _add_plugin_file_editor_to_tools() { $submenu['tools.php'][50] = array( __( 'Network Setup' ), 'setup_network', 'network.php' ); } -$menu[80] = array( __( 'Settings' ), 'manage_options', 'options-general.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' ); +$menu[80] = array( __( 'Settings' ), 'manage_options', 'options-general.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'core/settings' ); $submenu['options-general.php'][10] = array( _x( 'General', 'settings screen' ), 'manage_options', 'options-general.php' ); $submenu['options-general.php'][12] = array( __( 'Connectors' ), 'manage_options', 'options-connectors.php' ); $submenu['options-general.php'][15] = array( __( 'Writing' ), 'manage_options', 'options-writing.php' ); diff --git a/src/wp-admin/network/menu.php b/src/wp-admin/network/menu.php index e74dc93452a2a..a14bd8c48257a 100644 --- a/src/wp-admin/network/menu.php +++ b/src/wp-admin/network/menu.php @@ -13,7 +13,7 @@ } /* translators: Network menu item. */ -$menu[2] = array( __( 'Dashboard' ), 'manage_network', 'index.php', '', 'menu-top menu-top-first menu-icon-dashboard', 'menu-dashboard', 'dashicons-dashboard' ); +$menu[2] = array( __( 'Dashboard' ), 'manage_network', 'index.php', '', 'menu-top menu-top-first menu-icon-dashboard', 'menu-dashboard', 'core/dashboard' ); $submenu['index.php'][0] = array( __( 'Home' ), 'read', 'index.php' ); @@ -57,7 +57,7 @@ $submenu['sites.php'][5] = array( __( 'All Sites' ), 'manage_sites', 'sites.php' ); $submenu['sites.php'][10] = array( __( 'Add Site' ), 'create_sites', 'site-new.php' ); -$menu[10] = array( __( 'Users' ), 'manage_network_users', 'users.php', '', 'menu-top menu-icon-users', 'menu-users', 'dashicons-admin-users' ); +$menu[10] = array( __( 'Users' ), 'manage_network_users', 'users.php', '', 'menu-top menu-icon-users', 'menu-users', 'core/people' ); $submenu['users.php'][5] = array( __( 'All Users' ), 'manage_network_users', 'users.php' ); $submenu['users.php'][10] = array( __( 'Add User' ), 'create_users', 'user-new.php' ); @@ -77,10 +77,10 @@ '', 'menu-top menu-icon-appearance', 'menu-appearance', - 'dashicons-admin-appearance', + 'core/brush', ); } else { - $menu[15] = array( __( 'Themes' ), 'manage_network_themes', 'themes.php', '', 'menu-top menu-icon-appearance', 'menu-appearance', 'dashicons-admin-appearance' ); + $menu[15] = array( __( 'Themes' ), 'manage_network_themes', 'themes.php', '', 'menu-top menu-icon-appearance', 'menu-appearance', 'core/brush' ); } $submenu['themes.php'][5] = array( __( 'Installed Themes' ), 'manage_network_themes', 'themes.php' ); $submenu['themes.php'][10] = array( __( 'Add Theme' ), 'install_themes', 'theme-install.php' ); @@ -102,16 +102,16 @@ '', 'menu-top menu-icon-plugins', 'menu-plugins', - 'dashicons-admin-plugins', + 'core/plugins', ); } else { - $menu[20] = array( __( 'Plugins' ), 'manage_network_plugins', 'plugins.php', '', 'menu-top menu-icon-plugins', 'menu-plugins', 'dashicons-admin-plugins' ); + $menu[20] = array( __( 'Plugins' ), 'manage_network_plugins', 'plugins.php', '', 'menu-top menu-icon-plugins', 'menu-plugins', 'core/plugins' ); } $submenu['plugins.php'][5] = array( __( 'Installed Plugins' ), 'manage_network_plugins', 'plugins.php' ); $submenu['plugins.php'][10] = array( __( 'Add Plugin' ), 'install_plugins', 'plugin-install.php' ); $submenu['plugins.php'][15] = array( __( 'Plugin File Editor' ), 'edit_plugins', 'plugin-editor.php' ); -$menu[25] = array( __( 'Settings' ), 'manage_network_options', 'settings.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' ); +$menu[25] = array( __( 'Settings' ), 'manage_network_options', 'settings.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'core/settings' ); if ( defined( 'MULTISITE' ) && defined( 'WP_ALLOW_MULTISITE' ) && WP_ALLOW_MULTISITE ) { $submenu['settings.php'][5] = array( __( 'Network Settings' ), 'manage_network_options', 'settings.php' ); $submenu['settings.php'][10] = array( __( 'Network Setup' ), 'setup_network', 'setup.php' ); diff --git a/src/wp-includes/assets/icon-library-manifest.php b/src/wp-includes/assets/icon-library-manifest.php index af72a1c00499c..9c21a33351db0 100644 --- a/src/wp-includes/assets/icon-library-manifest.php +++ b/src/wp-includes/assets/icon-library-manifest.php @@ -61,6 +61,10 @@ 'label' => _x( 'Block Table', 'icon label' ), 'filePath' => 'block-table.svg', ), + 'brush' => array( + 'label' => _x( 'Brush', 'icon label' ), + 'filePath' => 'brush.svg', + ), 'calendar' => array( 'label' => _x( 'Calendar', 'icon label' ), 'filePath' => 'calendar.svg', @@ -141,6 +145,10 @@ 'label' => _x( 'Create', 'icon label' ), 'filePath' => 'create.svg', ), + 'dashboard' => array( + 'label' => _x( 'Dashboard', 'icon label' ), + 'filePath' => 'dashboard.svg', + ), 'desktop' => array( 'label' => _x( 'Desktop', 'icon label' ), 'filePath' => 'desktop.svg', @@ -209,10 +217,18 @@ 'label' => _x( 'Language', 'icon label' ), 'filePath' => 'language.svg', ), + 'link' => array( + 'label' => _x( 'Link', 'icon label' ), + 'filePath' => 'link.svg', + ), 'map-marker' => array( 'label' => _x( 'Map Marker', 'icon label' ), 'filePath' => 'map-marker.svg', ), + 'media' => array( + 'label' => _x( 'Media', 'icon label' ), + 'filePath' => 'media.svg', + ), 'menu' => array( 'label' => _x( 'Menu', 'icon label' ), 'filePath' => 'menu.svg', @@ -237,6 +253,10 @@ 'label' => _x( 'Paragraph', 'icon label' ), 'filePath' => 'paragraph.svg', ), + 'page' => array( + 'label' => _x( 'Page', 'icon label' ), + 'filePath' => 'page.svg', + ), 'payment' => array( 'label' => _x( 'Payment', 'icon label' ), 'filePath' => 'payment.svg', @@ -249,6 +269,10 @@ 'label' => _x( 'People', 'icon label' ), 'filePath' => 'people.svg', ), + 'plugins' => array( + 'label' => _x( 'Plugins', 'icon label' ), + 'filePath' => 'plugins.svg', + ), 'plus' => array( 'label' => _x( 'Plus', 'icon label' ), 'filePath' => 'plus.svg', @@ -257,6 +281,10 @@ 'label' => _x( 'Plus Circle', 'icon label' ), 'filePath' => 'plus-circle.svg', ), + 'post' => array( + 'label' => _x( 'Post', 'icon label' ), + 'filePath' => 'post.svg', + ), 'previous' => array( 'label' => _x( 'Previous', 'icon label' ), 'filePath' => 'previous.svg', @@ -349,6 +377,10 @@ 'label' => _x( 'Tip', 'icon label' ), 'filePath' => 'tip.svg', ), + 'tool' => array( + 'label' => _x( 'Tool', 'icon label' ), + 'filePath' => 'tool.svg', + ), 'upload' => array( 'label' => _x( 'Upload', 'icon label' ), 'filePath' => 'upload.svg', diff --git a/src/wp-includes/images/icon-library/brush.svg b/src/wp-includes/images/icon-library/brush.svg new file mode 100644 index 0000000000000..cbc934a9ecffd --- /dev/null +++ b/src/wp-includes/images/icon-library/brush.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/wp-includes/images/icon-library/dashboard.svg b/src/wp-includes/images/icon-library/dashboard.svg new file mode 100644 index 0000000000000..69c3c8587d23f --- /dev/null +++ b/src/wp-includes/images/icon-library/dashboard.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/wp-includes/images/icon-library/link.svg b/src/wp-includes/images/icon-library/link.svg new file mode 100644 index 0000000000000..af721a53bd0cf --- /dev/null +++ b/src/wp-includes/images/icon-library/link.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/wp-includes/images/icon-library/media.svg b/src/wp-includes/images/icon-library/media.svg new file mode 100644 index 0000000000000..ded8bbce4f3aa --- /dev/null +++ b/src/wp-includes/images/icon-library/media.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/wp-includes/images/icon-library/page.svg b/src/wp-includes/images/icon-library/page.svg new file mode 100644 index 0000000000000..47e332c7a75bf --- /dev/null +++ b/src/wp-includes/images/icon-library/page.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/wp-includes/images/icon-library/plugins.svg b/src/wp-includes/images/icon-library/plugins.svg new file mode 100644 index 0000000000000..dc1b8470a5f7c --- /dev/null +++ b/src/wp-includes/images/icon-library/plugins.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/wp-includes/images/icon-library/post.svg b/src/wp-includes/images/icon-library/post.svg new file mode 100644 index 0000000000000..85eab0a974df0 --- /dev/null +++ b/src/wp-includes/images/icon-library/post.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/wp-includes/images/icon-library/tool.svg b/src/wp-includes/images/icon-library/tool.svg new file mode 100644 index 0000000000000..96e3cc4e92df6 --- /dev/null +++ b/src/wp-includes/images/icon-library/tool.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 2db73e9a20476..ac14758db916a 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -32,7 +32,7 @@ function create_initial_post_types() { 'capability_type' => 'post', 'map_meta_cap' => true, 'menu_position' => 5, - 'menu_icon' => 'dashicons-admin-post', + 'menu_icon' => 'core/post', 'hierarchical' => false, 'rewrite' => false, 'query_var' => false, @@ -68,7 +68,7 @@ function create_initial_post_types() { 'capability_type' => 'page', 'map_meta_cap' => true, 'menu_position' => 20, - 'menu_icon' => 'dashicons-admin-page', + 'menu_icon' => 'core/page', 'hierarchical' => true, 'rewrite' => false, 'query_var' => false, @@ -110,7 +110,7 @@ function create_initial_post_types() { 'create_posts' => 'upload_files', ), 'map_meta_cap' => true, - 'menu_icon' => 'dashicons-admin-media', + 'menu_icon' => 'core/media', 'hierarchical' => false, 'rewrite' => false, 'query_var' => false, diff --git a/tests/phpunit/tests/post/types.php b/tests/phpunit/tests/post/types.php index 2c8564f22aeab..0de6e7b605020 100644 --- a/tests/phpunit/tests/post/types.php +++ b/tests/phpunit/tests/post/types.php @@ -287,9 +287,9 @@ public function test_get_post_type_object_casting() { * @ticket 38844 */ public function test_get_post_type_object_includes_menu_icon_for_builtin_post_types() { - $this->assertSame( 'dashicons-admin-post', get_post_type_object( 'post' )->menu_icon ); - $this->assertSame( 'dashicons-admin-page', get_post_type_object( 'page' )->menu_icon ); - $this->assertSame( 'dashicons-admin-media', get_post_type_object( 'attachment' )->menu_icon ); + $this->assertSame( 'core/post', get_post_type_object( 'post' )->menu_icon ); + $this->assertSame( 'core/page', get_post_type_object( 'page' )->menu_icon ); + $this->assertSame( 'core/media', get_post_type_object( 'attachment' )->menu_icon ); } /** diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 1b0eaac6cccd1..f8e6a8c29864f 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -13966,7 +13966,7 @@ mockedApiResponse.TypesCollection = { "has_archive": false, "name": "Posts", "slug": "post", - "icon": "dashicons-admin-post", + "icon": "core/post", "taxonomies": [ "category", "post_tag" @@ -14001,7 +14001,7 @@ mockedApiResponse.TypesCollection = { "has_archive": false, "name": "Pages", "slug": "page", - "icon": "dashicons-admin-page", + "icon": "core/page", "taxonomies": [], "rest_base": "pages", "rest_namespace": "wp/v2", @@ -14033,7 +14033,7 @@ mockedApiResponse.TypesCollection = { "has_archive": false, "name": "Media", "slug": "attachment", - "icon": "dashicons-admin-media", + "icon": "core/media", "taxonomies": [], "rest_base": "media", "rest_namespace": "wp/v2", @@ -14327,7 +14327,7 @@ mockedApiResponse.TypeModel = { "has_archive": false, "name": "Posts", "slug": "post", - "icon": "dashicons-admin-post", + "icon": "core/post", "taxonomies": [ "category", "post_tag" From d0fbd37ca6b27058f634d2d172f6b76ef86c7100 Mon Sep 17 00:00:00 2001 From: Faisal Ahammad Date: Wed, 5 Aug 2026 14:12:10 +0600 Subject: [PATCH 2/2] Administration: Register the new sidebar icons at runtime in Core The 8 new sidebar icons (brush, dashboard, link, media, page, plugins, post, tool) were previously added by hand to the Gutenberg-versioned icon-library/ directory and manifest. Those files are regenerated by the gutenberg:copy build task from the pinned Gutenberg source, which deletes any local additions and causes the CI git-diff gate to fail. Move the SVG assets to a new, Core-owned wp-includes/images/core-icons/ directory and register them at runtime via wp_register_icon() in _wp_register_default_icons(). The versioned files revert to their upstream state, so the build regenerates them identically and the CI diff gate passes by construction. Props: see ticket #65387. --- .../assets/icon-library-manifest.php | 32 ------------------- src/wp-includes/icons.php | 29 +++++++++++++++++ .../{icon-library => core-icons}/brush.svg | 2 +- .../dashboard.svg | 2 +- .../{icon-library => core-icons}/link.svg | 2 +- src/wp-includes/images/core-icons/media.svg | 4 +++ .../{icon-library => core-icons}/page.svg | 2 +- .../{icon-library => core-icons}/plugins.svg | 2 +- .../{icon-library => core-icons}/post.svg | 2 +- .../{icon-library => core-icons}/tool.svg | 2 +- src/wp-includes/images/icon-library/media.svg | 4 --- 11 files changed, 40 insertions(+), 43 deletions(-) rename src/wp-includes/images/{icon-library => core-icons}/brush.svg (81%) rename src/wp-includes/images/{icon-library => core-icons}/dashboard.svg (78%) rename src/wp-includes/images/{icon-library => core-icons}/link.svg (72%) create mode 100644 src/wp-includes/images/core-icons/media.svg rename src/wp-includes/images/{icon-library => core-icons}/page.svg (75%) rename src/wp-includes/images/{icon-library => core-icons}/plugins.svg (65%) rename src/wp-includes/images/{icon-library => core-icons}/post.svg (72%) rename src/wp-includes/images/{icon-library => core-icons}/tool.svg (72%) delete mode 100644 src/wp-includes/images/icon-library/media.svg diff --git a/src/wp-includes/assets/icon-library-manifest.php b/src/wp-includes/assets/icon-library-manifest.php index 9c21a33351db0..af72a1c00499c 100644 --- a/src/wp-includes/assets/icon-library-manifest.php +++ b/src/wp-includes/assets/icon-library-manifest.php @@ -61,10 +61,6 @@ 'label' => _x( 'Block Table', 'icon label' ), 'filePath' => 'block-table.svg', ), - 'brush' => array( - 'label' => _x( 'Brush', 'icon label' ), - 'filePath' => 'brush.svg', - ), 'calendar' => array( 'label' => _x( 'Calendar', 'icon label' ), 'filePath' => 'calendar.svg', @@ -145,10 +141,6 @@ 'label' => _x( 'Create', 'icon label' ), 'filePath' => 'create.svg', ), - 'dashboard' => array( - 'label' => _x( 'Dashboard', 'icon label' ), - 'filePath' => 'dashboard.svg', - ), 'desktop' => array( 'label' => _x( 'Desktop', 'icon label' ), 'filePath' => 'desktop.svg', @@ -217,18 +209,10 @@ 'label' => _x( 'Language', 'icon label' ), 'filePath' => 'language.svg', ), - 'link' => array( - 'label' => _x( 'Link', 'icon label' ), - 'filePath' => 'link.svg', - ), 'map-marker' => array( 'label' => _x( 'Map Marker', 'icon label' ), 'filePath' => 'map-marker.svg', ), - 'media' => array( - 'label' => _x( 'Media', 'icon label' ), - 'filePath' => 'media.svg', - ), 'menu' => array( 'label' => _x( 'Menu', 'icon label' ), 'filePath' => 'menu.svg', @@ -253,10 +237,6 @@ 'label' => _x( 'Paragraph', 'icon label' ), 'filePath' => 'paragraph.svg', ), - 'page' => array( - 'label' => _x( 'Page', 'icon label' ), - 'filePath' => 'page.svg', - ), 'payment' => array( 'label' => _x( 'Payment', 'icon label' ), 'filePath' => 'payment.svg', @@ -269,10 +249,6 @@ 'label' => _x( 'People', 'icon label' ), 'filePath' => 'people.svg', ), - 'plugins' => array( - 'label' => _x( 'Plugins', 'icon label' ), - 'filePath' => 'plugins.svg', - ), 'plus' => array( 'label' => _x( 'Plus', 'icon label' ), 'filePath' => 'plus.svg', @@ -281,10 +257,6 @@ 'label' => _x( 'Plus Circle', 'icon label' ), 'filePath' => 'plus-circle.svg', ), - 'post' => array( - 'label' => _x( 'Post', 'icon label' ), - 'filePath' => 'post.svg', - ), 'previous' => array( 'label' => _x( 'Previous', 'icon label' ), 'filePath' => 'previous.svg', @@ -377,10 +349,6 @@ 'label' => _x( 'Tip', 'icon label' ), 'filePath' => 'tip.svg', ), - 'tool' => array( - 'label' => _x( 'Tool', 'icon label' ), - 'filePath' => 'tool.svg', - ), 'upload' => array( 'label' => _x( 'Upload', 'icon label' ), 'filePath' => 'upload.svg', diff --git a/src/wp-includes/icons.php b/src/wp-includes/icons.php index 0af4b6d61b873..e0f224cab8793 100644 --- a/src/wp-includes/icons.php +++ b/src/wp-includes/icons.php @@ -140,6 +140,35 @@ function _wp_register_default_icons() { ) ); } + + /* + * Register the sidebar menu icons in Core. These are not part of the + * Gutenberg icon library and would otherwise be reverted by the + * gutenberg:copy build task, so they are stored in their own directory + * and registered here. + */ + $core_icons_directory = ABSPATH . WPINC . '/images/core-icons/'; + + $core_sidebar_icons = array( + 'brush' => _x( 'Brush', 'icon label' ), + 'dashboard' => _x( 'Dashboard', 'icon label' ), + 'link' => _x( 'Link', 'icon label' ), + 'media' => _x( 'Media', 'icon label' ), + 'page' => _x( 'Page', 'icon label' ), + 'plugins' => _x( 'Plugins', 'icon label' ), + 'post' => _x( 'Post', 'icon label' ), + 'tool' => _x( 'Tool', 'icon label' ), + ); + + foreach ( $core_sidebar_icons as $icon_name => $icon_label ) { + wp_register_icon( + 'core/' . $icon_name, + array( + 'label' => $icon_label, + 'file_path' => $core_icons_directory . $icon_name . '.svg', + ) + ); + } } /** diff --git a/src/wp-includes/images/icon-library/brush.svg b/src/wp-includes/images/core-icons/brush.svg similarity index 81% rename from src/wp-includes/images/icon-library/brush.svg rename to src/wp-includes/images/core-icons/brush.svg index cbc934a9ecffd..18dffa96f6993 100644 --- a/src/wp-includes/images/icon-library/brush.svg +++ b/src/wp-includes/images/core-icons/brush.svg @@ -1,3 +1,3 @@ - + diff --git a/src/wp-includes/images/icon-library/dashboard.svg b/src/wp-includes/images/core-icons/dashboard.svg similarity index 78% rename from src/wp-includes/images/icon-library/dashboard.svg rename to src/wp-includes/images/core-icons/dashboard.svg index 69c3c8587d23f..374d5ba916f7b 100644 --- a/src/wp-includes/images/icon-library/dashboard.svg +++ b/src/wp-includes/images/core-icons/dashboard.svg @@ -1,3 +1,3 @@ - + diff --git a/src/wp-includes/images/icon-library/link.svg b/src/wp-includes/images/core-icons/link.svg similarity index 72% rename from src/wp-includes/images/icon-library/link.svg rename to src/wp-includes/images/core-icons/link.svg index af721a53bd0cf..5be28f494efe5 100644 --- a/src/wp-includes/images/icon-library/link.svg +++ b/src/wp-includes/images/core-icons/link.svg @@ -1,3 +1,3 @@ - + diff --git a/src/wp-includes/images/core-icons/media.svg b/src/wp-includes/images/core-icons/media.svg new file mode 100644 index 0000000000000..00aeb552e7da2 --- /dev/null +++ b/src/wp-includes/images/core-icons/media.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/wp-includes/images/icon-library/page.svg b/src/wp-includes/images/core-icons/page.svg similarity index 75% rename from src/wp-includes/images/icon-library/page.svg rename to src/wp-includes/images/core-icons/page.svg index 47e332c7a75bf..ce1918e963dd6 100644 --- a/src/wp-includes/images/icon-library/page.svg +++ b/src/wp-includes/images/core-icons/page.svg @@ -1,4 +1,4 @@ - + diff --git a/src/wp-includes/images/icon-library/plugins.svg b/src/wp-includes/images/core-icons/plugins.svg similarity index 65% rename from src/wp-includes/images/icon-library/plugins.svg rename to src/wp-includes/images/core-icons/plugins.svg index dc1b8470a5f7c..a74ce8910aac1 100644 --- a/src/wp-includes/images/icon-library/plugins.svg +++ b/src/wp-includes/images/core-icons/plugins.svg @@ -1,3 +1,3 @@ - + diff --git a/src/wp-includes/images/icon-library/post.svg b/src/wp-includes/images/core-icons/post.svg similarity index 72% rename from src/wp-includes/images/icon-library/post.svg rename to src/wp-includes/images/core-icons/post.svg index 85eab0a974df0..be934e242a1cd 100644 --- a/src/wp-includes/images/icon-library/post.svg +++ b/src/wp-includes/images/core-icons/post.svg @@ -1,3 +1,3 @@ - + diff --git a/src/wp-includes/images/icon-library/tool.svg b/src/wp-includes/images/core-icons/tool.svg similarity index 72% rename from src/wp-includes/images/icon-library/tool.svg rename to src/wp-includes/images/core-icons/tool.svg index 96e3cc4e92df6..1c9cc50018fcf 100644 --- a/src/wp-includes/images/icon-library/tool.svg +++ b/src/wp-includes/images/core-icons/tool.svg @@ -1,3 +1,3 @@ - + diff --git a/src/wp-includes/images/icon-library/media.svg b/src/wp-includes/images/icon-library/media.svg deleted file mode 100644 index ded8bbce4f3aa..0000000000000 --- a/src/wp-includes/images/icon-library/media.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -