Skip to content

IconPicker: support the WordPress 7.1 core icon store (wp/v2/icons) #411

Description

@fabiankaegy

What / Why

WordPress 7.1 introduces a first-party icon registration API (dev note):

  • PHP: wp_register_icon_collection() / wp_register_icon() / wp_get_icon(), backed by WP_Icons_Registry / WP_Icon_Collections_Registry
  • REST: read-only wp/v2/icons and wp/v2/icon-collections
  • Editor: icons are exposed as core-data root entitiesgetEntityRecords( 'root', 'icon', { collection } ) and getEntityRecords( 'root', 'iconCollection' ) (record shape: { name: 'my-collection/my-icon', label, content, collection }). There is no dedicated icon data store; the core core/icon block's inserter reads these entities directly.

Currently <IconPicker> / <Icon> / <IconPickerToolbarButton> only list icons pushed into block-components' own internal store via registerIcons(). Plugins adopting the core API end up with two parallel icon stores again — the exact problem the core registry was meant to solve — and have to bridge them manually.

Current workaround

We migrated our icon system to wp_register_icon() and kept <IconPicker> by hydrating the internal store from core-data on editor load:

import domReady from '@wordpress/dom-ready';
import { resolveSelect } from '@wordpress/data';
import { registerIcons } from '@10up/block-components/api/register-icons';

domReady( async () => {
	const [ collections, icons ] = await Promise.all( [
		resolveSelect( 'core' ).getEntityRecords( 'root', 'iconCollection' ),
		resolveSelect( 'core' ).getEntityRecords( 'root', 'icon' ),
	] );

	collections?.forEach( ( collection ) => {
		registerIcons( {
			name: collection.slug,
			label: collection.label,
			icons: icons
				?.filter( ( icon ) => icon.collection === collection.slug )
				.map( ( icon ) => ( {
					name: icon.name.split( '/' )[ 1 ],
					label: icon.label,
					source: icon.content,
				} ) ) ?? [],
		} );
	} );
} );

It works, but every consumer has to ship it, it duplicates icon state alongside the core-data cache, and registration races editor mount.

Proposal

On WP ≥ 7.1, have the icon components read the core icon store natively:

  1. <IconPicker> (and friends) list icons from getEntityRecords( 'root', 'icon' ) / getEntityRecords( 'root', 'iconCollection' ), merged with anything registered via registerIcons() for back-compat. The natural mapping is iconSet ↔ collection slug, name ↔ unqualified icon name, sourcecontent.
  2. <Icon> resolves from the same entities (falling back to the internal store).
  3. Longer term, document registerIcons() as legacy in favor of wp_register_icon() — server registration comes with kses sanitization and REST exposure for free.

Feature detection could be as simple as checking whether the root/icon entity resolves (or window.wp version), keeping WP < 7.1 behavior unchanged.

Activity

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions