Repository navigation
Allow Core blocks to resolve internal UI SVGs through the Icon Registry #81225
Description
What problem does this address?
WordPress now has an Icon Registry and the core/icon block can render a named
icon from it. However, many Core blocks still render their internal UI icons as
hard-coded inline SVG markup.
This makes theme-level icon customization fragile.
My block theme, Axismundi, uses
Material Symbols as its icon language. To make Core block controls visually
consistent, the theme currently has to hide Core SVGs and recreate them with
CSS generated content and an icon font.
Examples from the theme:
-
Search block submit icon
The Search block outputs its own SVG. The theme hides it and inserts the
Material Symbols search glyph with::before. -
Top-level Navigation submenu disclosure
The Navigation block outputs an SVG disclosure icon. The theme hides it and
substitutesarrow_drop_down, changing toarrow_drop_upwhen expanded. -
Nested Navigation submenu disclosure
Nested menu rows have another internal Core SVG. The theme hides it and
substitutes Material Symbolsarrow_right. -
Responsive Navigation menu trigger
icon: "menu"renders a three-line Core SVG, but does not provide a
semantic class or identifier for that variant. The theme currently identifies
it by its SVG path data, hides the SVG, and inserts a Material Symbols
menuglyph.The selector depends on this implementation detail:
:has(svg path[d="M5 5v1.5h14V5H5z"])
A harmless Core SVG path update could silently break the theme's menu icon.
-
Image block Lightbox controls
Core Lightbox close, previous, and next SVGs are hidden and replaced with
Material Symbolsclose,chevron_left, andchevron_right.
These workarounds also require themes to preserve Core behavior manually:
control sizing, state changes, hover/focus/active styles, RTL behavior,
accessibility, responsive behavior, and editor/frontend parity.
The problem is not simply styling an SVG. It is that a theme must replace a
semantic Core UI icon through private markup details.
Theme:
https://wordpress.org/themes/axismundi/
Source:
https://github.com/Jiwoon-Kim/axismundi/tree/main/products/distributables/themes/axismundi
What is your proposed solution?
Core blocks should resolve their built-in UI icons through the WordPress Icon
Registry instead of embedding glyph-specific SVG markup directly in each block.
The important requirement is a stable semantic icon identifier. Core should
continue to provide its existing SVGs as defaults, but themes should be able to
replace their visual implementation through the registry.
For example, Core could expose identifiers conceptually similar to:
core/searchcore/navigation-menucore/navigation-submenucore/navigation-submenu-nestedcore/closecore/chevron-leftcore/chevron-right
The exact names and API shape are less important than the outcome:
- Core retains its default icon set.
- Blocks preserve their existing button markup, labels, accessibility, layout,
state handling, and responsive behavior. - Themes can replace a glyph by registering an SVG for a semantic identifier.
- The same mechanism works in both the editor and frontend.
- Themes no longer need to hide SVGs, recreate them with
::before, use icon
fonts, or select controls through SVG path data.
This would let the existing Icon Registry become a genuine theming seam for
Core block UI, rather than being limited primarily to explicit core/icon
content blocks.
P.S. I have added a deliberately small experiment to my theme: it replaces only
the registered core/menu and core/search icons with local Material Symbols
SVGs, and only when the Icon API is available.
This works for consumers of the Icon API, including explicit core/icon
blocks. It does not affect the Navigation menu button or Search submit button
today, because those blocks still render their own inline SVG markup rather
than resolving the registered icon.
That contrast is the concrete reason for this request: the registry is already
a viable theming seam, but Core block UI icons do not consistently use it yet.
Activity
Jiwoon-Kim commentedon Aug 5, 2026
I did a frontend-rendering scan against Gutenberg 23.6.2 to make this more
concrete and to identify a possible implementation path.
Current frontend SVG emitters
When the Gutenberg plugin is active, it re-registers Core block types from its
own built block-library implementation:
lib/blocks.php→gutenberg_reregister_core_block_types()The corresponding source lives under:
packages/block-library/src/The following are the current server-side frontend SVG emitters relevant to
this proposal.
packages/block-library/src/navigation/index.phpicon: "menu"variant, and closepackages/block-library/src/navigation-link/shared/render-submenu-icon.phppackages/block-library/src/navigation-overlay-close/index.phppackages/block-library/src/page-list/index.phppackages/block-library/src/search/index.phppackages/block-library/src/image/index.phpThe relevant current source examples are:
Navigation responsive controls:
https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/navigation/index.php#L712-L720
Shared Navigation submenu icon:
https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/navigation-link/shared/render-submenu-icon.php#L14-L16
Navigation Overlay Close:
https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/navigation-overlay-close/index.php#L15-L36
Image Lightbox controls:
https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/image/index.php#L299-L301
I would keep
core/social-linkout of an initial implementation. Its inlineSVGs are service/brand marks rather than generic Core UI controls, and they
need a different compatibility discussion.
Existing Icon Registry seam
core/iconalready establishes the desired rendering pattern:Source:
https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/icon/index.php#L74-L82
The Gutenberg compatibility layer currently registers the
corecollectionand loads its default icon manifest from
packages/icons/src/:This is already sufficient for Core itself to obtain an SVG with consistent
size, class, and accessibility handling.
Suggested incremental implementation
I think this can be implemented in small, independently reviewable steps.
1. Add stable semantic identifiers for block UI icons
The first step is not to expose every existing SVG path as an API. It is to
give each UI role a stable semantic identifier and register Core's current SVG
as that identifier's default.
The exact names need discussion, but they should be specific enough not to
change the meaning of existing
core/iconcontent. For example:I would prefer dedicated UI names over reusing a generic content-facing name
such as
core/menu. A theme may reasonably want to customize a Navigationcontrol without also changing every explicit
<!-- wp:icon {"icon":"core/menu"} /-->instance stored in content.
2. Replace literal SVG strings in block renderers with
wp_get_icon()For example, Navigation currently has this shape:
It could become conceptually:
The same narrow substitution applies to:
block_core_shared_navigation_render_submenu_icon();render_block_core_navigation_overlay_close();This preserves all existing wrapper markup,
aria-labelownership,Interactivity API directives, and responsive behavior. Only the source of the
inner SVG changes.
3. Deduplicate existing Core UI icon call sites
There is already an obvious first cleanup opportunity:
Page List should consume the same semantic icon helper rather than carrying a
second SVG string. This gives the proposed identifier a second real consumer
immediately.
4. Define a supported theme override mechanism separately
The current registry documentation reserves the
corecollection for Coreicons. Therefore a theme should not be expected to unregister and re-register
core/*entries, even though that can be used experimentally today.The block refactor and official theme override semantics can be separate
changes:
identifiers.
resolver/filter that can map a Core UI identifier to a theme collection
identifier, or a controlled icon-render filter.
This avoids requiring third-party themes to mutate the reserved
corecollection while still making the registry a genuine theming seam.
A resolver conceptually like the following would be enough:
The exact hook name and arguments are only illustrative. The key requirement
is that a theme can substitute its own registered SVG without parsing or
replacing rendered HTML.
5. Test at the render boundary
Tests should verify more than the default SVG output. A useful integration
test would register a temporary substitute for a UI identifier through the
supported resolver, render the relevant block with
do_blocks(), and assertthat the substitute SVG appears while the existing button markup and
accessibility attributes remain intact.
Initial coverage should include:
icon: "menu"trigger;Why this is useful even before every block migrates
A partial migration is already valuable. Search, Navigation, and Image
Lightbox are sufficient to remove several fragile theme workarounds, including
CSS selectors coupled to private SVG path data.
For reference, this small theme experiment demonstrates that the existing
registry already works for explicit
core/iconconsumers:https://github.com/Jiwoon-Kim/axismundi/blob/main/products/distributables/themes/axismundi/inc/core-icon-overrides.php
It intentionally does not affect the Navigation or Search controls today,
because those renderers still emit their own SVG strings. That is the gap this
proposal addresses.
Vrishabhsk commentedon Aug 26, 2026
Hey @Jiwoon-Kim ! I've opened a PR
Core blocks now resolve their internal UI icons through the WordPress Icon Registry instead of hardcoding inline SVGs. Themes can override any block UI icon by registering a replacement SVG for a stable semantic identifier. Core retains its exact existing SVGs as defaults — no visual regression.
Exposed icon identifiers:
core/searchcore/navigation-submenucore/navigation-menu-togglecore/menucore/closecore/chevron-left/core/chevron-rightTheme override example:
Works in both editor and frontend. The default SVGs exactly match the originals, so themes like Axismundi can now replace glyphs through the registry instead of hiding SVGs and recreating them with
::before/ icon fonts / path-data selectors.Would love feedback on the icon naming and the approach!