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 entities —
getEntityRecords( '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:
<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, source ↔ content.
<Icon> resolves from the same entities (falling back to the internal store).
- 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.
What / Why
WordPress 7.1 introduces a first-party icon registration API (dev note):
wp_register_icon_collection()/wp_register_icon()/wp_get_icon(), backed byWP_Icons_Registry/WP_Icon_Collections_Registrywp/v2/iconsandwp/v2/icon-collectionsgetEntityRecords( 'root', 'icon', { collection } )andgetEntityRecords( 'root', 'iconCollection' )(record shape:{ name: 'my-collection/my-icon', label, content, collection }). There is no dedicated icon data store; the corecore/iconblock's inserter reads these entities directly.Currently
<IconPicker>/<Icon>/<IconPickerToolbarButton>only list icons pushed into block-components' own internal store viaregisterIcons(). 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: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:
<IconPicker>(and friends) list icons fromgetEntityRecords( 'root', 'icon' )/getEntityRecords( 'root', 'iconCollection' ), merged with anything registered viaregisterIcons()for back-compat. The natural mapping isiconSet↔ collection slug,name↔ unqualified icon name,source↔content.<Icon>resolves from the same entities (falling back to the internal store).registerIcons()as legacy in favor ofwp_register_icon()— server registration comes with kses sanitization and REST exposure for free.Feature detection could be as simple as checking whether the
root/iconentity resolves (orwindow.wpversion), keeping WP < 7.1 behavior unchanged.