Skip to content

Add Icon APIs: registry and /wp/v2/icons endpoint#10909

Open
mcsf wants to merge 12 commits intoWordPress:trunkfrom
mcsf:add/icons-apis
Open

Add Icon APIs: registry and /wp/v2/icons endpoint#10909
mcsf wants to merge 12 commits intoWordPress:trunkfrom
mcsf:add/icons-apis

Conversation

@mcsf
Copy link
Contributor

@mcsf mcsf commented Feb 12, 2026

@github-actions
Copy link

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

* }
* @return bool True if the icon was registered with success and false otherwise.
*/
private function register( $icon_name, $icon_properties ) {
Copy link
Member

Choose a reason for hiding this comment

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

I do not think we should merge in this API without a public method for registering icons.

The icon library we are shipping with Core is the gutenberg icons. Those icons were never meant to be frontend design icons. They are editor interface icons.

From my POV there is very little utility to the icon block in core without the ability to register custom icons.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I understand where you're coming from, but I'd argue that the Icon block is already useful in its initial form, having access to 321 core icons.

Though @wordpress/icons was developed to support the needs of the editor, IMO it's fair to say that the icon set can accommodate more uses. Folks like @jasmussen, @jameskoster and others have been iterating on those icons and are involved in the making of the Icon block, which I take as a sign that, though imperfect, the icon set has evolved beyond its original purpose.

Keeping the Icons registry closed was a way to conserve some more room for adjustments, as the icon block itself gets adopted. It should be understood as an intermediate step, so that we can confidently expand the scope of the registry in 7.1 (third-party registration, but possibly also categories, etc.).

Choose a reason for hiding this comment

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

Thanks for the ping. As happens more often than I like, I find myself agreeing with both ends of the spectrum.

On the one hand, let's be honest that the utility of this first iteration is limited: there are many inline contexts where I would like to use icons, but can't. There's just that one set, and although there are many nice icons there, the majority of them were designed for blocks, or WordPress specific features.

On the other hand, while this effort is also about adding a block that lets you intiutively create decorative bullets and expanded patterns, it's also a mammoth infrastructure effort, to bring SVG support to WordPress, to wrap it in a UI that we can grow, expand, and iterate. Most of this work may not be quite as exciting and immediately useful, but wait til you see what we can do with it. We're building a mountain, moving dirt to one place, and eventually what we build will be visible on the horison.

In saying that, I'm validating every aspect of Fabian's point. I think this is especially important if we were to land in 7.0 and market this new feature: we should be very honest that this is a small first step, not the end-state. There are shortcomings: SVG support is the big deal. But with that, I'm also validating Miguel's instinct: this ground work is critical, and there's no better test crucible than to ship this in a major release, so we can work out the inevitable issues.

None of this is strongly felt. There's always another release. But it's a soft appeal: I'd rather take 4 deliberate, but small steps, than make one big jump and risk landing in the wrong place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After talking with Joen, I also opened WordPress/gutenberg#75526 to distinguish "front-end-ready" icons from internal ones.

Copy link
Contributor

Choose a reason for hiding this comment

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

Keeping the Icons registry closed was a way to conserve some more room for adjustments, as the icon block itself gets adopted. It should be understood as an intermediate step, so that we can confidently expand the scope of the registry in 7.1 (third-party registration, but possibly also categories, etc.).

I also agree with this approach. To get attention and move this PR forward, we might want to submit a core ticket first.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

I think the incremental approach @mcsf is suggesting is a good call. Shipping the registry and REST endpoint now gives an initial foundation to build on, and keeping register() private for this first iteration is a good way to leave room for refinement before committing to a public API surface.
I think merging this PR (and the icon block) would allow some icon block testing before committing to how third parties can add additional icons. We would get a better sense of how the block is used, and the icons package already offers some icons that can be useful.

@mcsf mcsf force-pushed the add/icons-apis branch 2 times, most recently from 9aaf4d0 to 06d0995 Compare February 12, 2026 18:57
@mcsf mcsf marked this pull request as ready for review February 16, 2026 17:00
@github-actions
Copy link

github-actions bot commented Feb 16, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props mcsf, wildworks, fabiankaegy, joen, jorgefilipecosta, ntsekouras.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link
Contributor

@ntsekouras ntsekouras left a comment

Choose a reason for hiding this comment

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

I definitely get @fabiankaegy's point, but I think we should ship this essential infrastructure and not rush the public API for registration until the next WP version. It will give some exposure to the Icon block and it will help us move forward more confidently.

Will it be as useful as it can be at first? No. Will it be useful though at all? I strongly believe yes, as the public icons set includes quite a few 'util' icons that can serve many use cases.

As @jasmussen says we shouldn't market this feature as something more than it is, but the infrastructure work shouldn't be blocked.

Copy link
Contributor

@t-hamano t-hamano left a comment

Choose a reason for hiding this comment

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

In WordPress/gutenberg#75526, we marked the icons that should be made public as 'public' => true. However, in this PR, we're not checking that field, so all icons not marked as public will be included and may be unintentionally made public. Is this correct?

If so, one of the following approaches may be necessary:

  • Copy all icons, but check whether the public field is true in the icon registry.
  • When copying icons, if the public field is not true, do not copy the icon. Additionally, remove icons not marked as 'public' => true from the manifest.php file.

Perhaps the latter approach is ideal if we don't want to ship internal icons entirely into core, but it may be a bit more complicated. What do you think?

@t-hamano
Copy link
Contributor

  • Copy all icons, but check whether the public field is true in the icon registry.
  • When copying icons, if the public field is not true, do not copy the icon. Additionally, remove icons not marked as 'public' => true from the manifest.php file.

Perhaps the latter approach is ideal if we don't want to ship internal icons entirely into core, but it may be a bit more complicated. What do you think?

@mcsf Since we're getting close to the Beta 1 release and the former approach is simpler, I’ve committed 970944b using that approach. I’d appreciate your thoughts.

@mcsf
Copy link
Contributor Author

mcsf commented Feb 17, 2026

@mcsf Since we're getting close to the Beta 1 release and the former approach is simpler, I’ve committed 970944b using that approach. I’d appreciate your thoughts.

Sorry, I thought I had submitted a reply but apparently not. Yes, that's what I would prefer!

Comment on lines +72 to +74
if ( ! ( $icon_data['public'] ?? false ) ) {
continue;
}
Copy link
Contributor

@t-hamano t-hamano Feb 17, 2026

Choose a reason for hiding this comment

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

I think this code caused the unit test to fail.

There was 1 error:

1) Tests_REST_WpRestIconsController::test_prepare_item
Undefined offset: 0

/var/www/tests/phpunit/tests/icons/wpRestIconsController.php:114
phpvfscomposer:///var/www/vendor/phpunit/phpunit/phpunit:106
/var/www/vendor/bin/phpunit:118

GitHub Action Example: https://github.com/WordPress/wordpress-develop/actions/runs/22104294772/job/63882418252?pr=10909

I think the reason is that the Gutenberg commit hash defined in WordPress core does not yet have an icon marked as public->true in manifest.php. I think there are two ways to solve this. What do you think?

  • Skip unit testsfor now, and restore unit tests after Beta1 is released.
  • Register custom icons for unit tests to avoid dependency on manifest.php.

@t-hamano
Copy link
Contributor

Update:

  • 7b941e4: I skipped the failing tests because there are no public icons in manifest.php yet. Once the Gutenberg commit hash is updated, we'll be able to re-enable the skipped tests. At first, I thought about registering a mock icon, but after reading this comment, I realized that that approach wasn't the right one.
  • 15a38c3: I added a ticket tag.


// All returned icons should contain "arrow" in their name (case insensitive)
foreach ( $data as $icon ) {
$this->assertStringContainsStringIgnoringCase( 'arrow', $icon['name'] );
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that this test isn't actually running at all, because there are no public icons.

@mcsf
Copy link
Contributor Author

mcsf commented Feb 18, 2026

  • 7b941e4: I skipped the failing tests because there are no public icons in manifest.php yet. Once the Gutenberg commit hash is updated, we'll be able to re-enable the skipped tests. At first, I thought about registering a mock icon, but after reading this comment, I realized that that approach wasn't the right one.

Awesome, thanks. For the record, I just tested building WordPress with an updated Gutenberg ref, removed the tests' skip instructions, and I can confirm that the tests pass with the right manifest. 👍

@mcsf
Copy link
Contributor Author

mcsf commented Feb 18, 2026

I think we should be good to go. What else is missing for this initial commit?

Copy link
Contributor

@t-hamano t-hamano left a comment

Choose a reason for hiding this comment

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

It looks almost good, but I overlooked an important point: the text domain of the icon in the manifest.php file is gutenberg, so it will not be translatable in core. Would it be difficult to remove this text domain during the build process?

*/

/**
* FIXME
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Can we remove the FIXME and provide a class summary here?

array(
'args' => array(
'name' => array(
'description' => __( 'Icon name.', 'gutenberg' ),
Copy link
Contributor

Choose a reason for hiding this comment

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

Oops, I missed this. Let's remove all gutenberg text domains from this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants