PRC's override/extension of the WordPress core/tabs block family (core/tab-list, core/tab-panels, core/tab-panel).
Requires Gutenberg 23.5+ — upstream Gutenberg #77439 removed the core/tab button block. Tab labels now live in a tabs array attribute on core/tab-list, rendered as plain <button> elements.
Block Namespace
prc-block/core-tabs
Gutenberg 23.5 structure
core/tab-list— holdstabs: [{ label }](source: queryoverbutton); renders<button type="button" role="tab">{label}</button>children insave.js. No innercore/tabblocks.core/tab-panels/core/tab-panel— unchanged; parentcore/tabsstill providescore/tabs-listcontext from panels.- Styling — color, border, and spacing on tab-list apply via
.wp-block-tab-list buttonselectors (__experimentalSkipSerialization).
What PRC Customizes
- Registers a
core/tab-labelblock bindings source for syncing tab labels between the menu and tab content - Registers Country Flags and Active Underline block styles on
core/tab-list, plus a Tabbed preset oncore/tabs - Adds hover/active color attributes and inspector controls on
core/tab-list(consolidated from the removed per-tab level) - Adds a mobile dropdown mode that converts the tabs menu to a select-style dropdown below a configurable breakpoint
- Supports top and bottom dropdown placement (bottom dropdown copies the menu after tab panels)
- Adds a block transform from legacy
prc-block/tabstocore/tabs(buildstabsattribute from panel labels) - Extends
core/tab-listusesContextso parent context (core/tabs-id,core/tabs-activeTabIndex,core/tabs-editorActiveTabIndex) is available for mobile dropdown render logic - Ships an Interactivity API store for mobile dropdown state management, resize handling, and click-outside-to-close behavior
- Syncs Entity as Iframe inside each tab panel with the
core/tabspublic store'sstate.isActiveTab - Includes utility PHP functions for programmatically building tab structures with the
tabsattribute - Registers paragraph and heading variations bound to the tab label
- WP-CLI migration:
wp prc block-library migrate-core-tab-to-tabs-attrcollapses legacycore/tabinner blocks into thetabsattribute (run after deploy)
Additional Attributes
On core/tab-list:
| Attribute | Type | Default | Description |
|---|---|---|---|
mobileDropdown | boolean | false | Enable mobile dropdown mode |
mobileDropdownWidth | number | 768 | Viewport width breakpoint for dropdown trigger |
hoverBackgroundColor / customHoverBackgroundColor | string | — | Hover background (preset slug + custom hex) |
hoverTextColor / customHoverTextColor | string | — | Hover text color |
activeBackgroundColor / customActiveBackgroundColor | string | — | Active background |
activeTextColor / customActiveTextColor | string | — | Active text color |
Available Styles
| Block | Style Name | Label | Description |
|---|---|---|---|
core/tabs | tabbed | Tabbed | Folder-tab preset on the parent block |
core/tab-list | country-flags | Country Flags | Flag icons before tab labels (injected at render from panel labels) |
core/tab-list | active-underline | Active Underline | Underline on the active tab with transparent background |
Style Overrides
File: style.scss
Button selectors use .wp-block-tab-list button (not .wp-block-tab). CSS custom properties (--custom-tab-hover-color, etc.) are set on the tab-list wrapper and cascade to buttons.
Editor Enhancements
File: index.jsx
prc-block/tabs→core/tabstransform buildscore/tab-listwithtabs: [{ label }]from panel labelsmobileDropdown,mobileDropdownWidth, and hover/active color attrs oncore/tab-listonly- HOC on
core/tab-listinjectsControls(no per-tab controls;controls-tab.jsxremoved)
PHP Rendering
File: class-core-tabs.php
render_core_tab_list— enqueues view module; injects country flags into<button>elements whenis-style-country-flags; builds mobile dropdown by cloning rendered buttons; sets IAPI staterender_core_tabs_entity_iframe— adds prefetch directive on tab<button role="tab">elements; panel sync unchangedfilter_render_block_context— addscore/tab-slugoncore/tab-panelfor children
File: util.php
build_core_tab_list( $attrs, $is_vertical, $labels, $wrapper_html )— createscore/tab-listwithtabsattribute and<button>{label}</button>markupcreate_core_tabs()/render_tabs()— assemble and render fullcore/tabstrees; signature no longer includes per-button attrs/innerHTML params
Block Markup Example
<div class="wp-block-tabs" data-wp-interactive="core/tabs">
<div class="wp-block-tab-list" role="tablist">
<button type="button" role="tab">Tab 1</button>
<button type="button" role="tab">Tab 2</button>
</div>
<div class="wp-block-tab-panels">
<section role="tabpanel" class="wp-block-tab-panel" id="tab-1">
…
</section>
<section role="tabpanel" class="wp-block-tab-panel" id="tab-2">
…
</section>
</div>
</div>
Migration
After deploying with Gutenberg 23.5:
# Preview
wp prc block-library migrate-core-tab-to-tabs-attr
# Execute
wp prc block-library migrate-core-tab-to-tabs-attr --dry-run=false
Discovers posts via block-catalog terms core-tab, core-tab-list, core-tabs-menu, and core-tabs-menu-item.
The command handles two legacy shapes:
- Gutenberg 23.1–23.4 —
core/tab-listwithcore/tabbutton inner blocks: collapses buttons into thetabsattribute + plain<button>markup usingcore/tab-panellabels. - Pre-23.1 template schema —
core/tabs-menu+ singularcore/tab-panelcontainer holdingcore/tabcontent panels (e.g. country-flag interactives with one emptytabs-menu-itemtemplate): converts tocore/tab-list+core/tab-panels+core/tab-panel, builds thetabsattribute from panel labels, and hoiststabs-menu-itemstyling (e.g.is-style-country-flags, active/hover colors) ontocore/tab-list.
Safe to re-run: already-migrated posts are skipped.
Frontend Interactivity
File: view.js (Interactivity API module)
- Registers the view script module via
register_block_script_module_id; enqueue uses the handle only (not a full module URL). syncEntityIframeWithTabPanel— syncs nested Entity as Iframe blocks with the active tab panel. Uses the closed-over storestatefrom the module callback scope (not a freshstore('core/tabs')lookup) so it does not lock a public store.- Mobile dropdown state, resize handling, and click-outside-to-close behavior for tab-list mobile dropdown mode.