Repository navigation
Public API for third-party block toolbar controls in Responsive styling (the style-state counterpart to inspector group="viewport") #82633
Description
The problem
In Responsive styling, the block toolbar renders a fixed set of slots. When a viewport style state is being edited, BlockToolbar sets showSlots = false and renders only the style-state group:
block-editor/src/components/block-toolbar/index.jsx—_isEditingResponsiveStyleState = isResponsiveEditing() && hasViewportBlockStyleState( … ), thenshowSlots: ! _isZoomOut && ! _isEditingResponsiveStyleStateandshowStyleStateSlot: ! _isZoomOut && _isEditingResponsiveStyleState.- Only
<BlockControls.Slot group="style-state" />is rendered in that mode;default,block,inline,parent,otherare all suppressed.
So on Tablet or Mobile with Responsive styles on, any third-party toolbar control registered via <BlockControls> (default group) is not rendered. The control is simply unreachable while the user is doing the exact per-device work it exists for. (In our case it's a block-position offset handle, but the problem is general to any BlockControls fill.)
This is the toolbar analogue of the inspector allow-list already discussed in #82082 / #80388: core cannot know whether an arbitrary fill understands viewport states, so the suppression is deliberate — a control that silently writes the base layer while the user believes they are editing Mobile is worse than one that is absent.
The mechanism already exists — for core
style-state is a registered group (block-controls/groups.js → BlockControlsStyleState), and core's own text-align control opts into it:
block-editor/src/hooks/text-align.jsx—const controlsGroup = _isEditingResponsiveStyleState ? 'style-state' : 'default'…<BlockControls group={ controlsGroup }>.
A third-party control could do exactly the same — render <BlockControls group="style-state"> while a viewport state is active — and it would appear in the responsive toolbar.
The gap
The two pieces a third party needs are not public:
- Detection. Knowing when to switch to
style-staterequires helpers fromblock-editor/src/hooks/block-style-state.js(hasViewportBlockStyleState,isDefaultBlockStyleState,useBlockStyleState, …). None of these are part of the public@wordpress/block-editorsurface — some (getStyleForState,setStyleForState,isDefaultBlockStyleState) are routed only through the lockedprivate-apis.js, and the rest are internal to the package. - The group itself.
group="style-state"onBlockControlsis undocumented as a supported third-party value; there is no guidance that this is the sanctioned way to keep a toolbar control in Responsive styling.
Request
Treat the toolbar the same way #80388 is treating the inspector:
- Document (or explicitly bless)
<BlockControls group="style-state">as the supported way for third-party blocks to render toolbar controls during viewport style-state editing, mirroring theInspectorControls group="viewport"slot added in Enable Gallery columns and crop controls in viewport states #82003. - Include the
block-style-statedetection helpers (useBlockStyleState,hasViewportBlockStyleState,isDefaultBlockStyleState,getStyleForState/setStyleForState,scopeResetAllFilterToState) in the public@wordpress/block-editorAPI planned in Responsive style states for blocks - 7.2 tasks #80388, so a toolbar control can decide its group without reaching into private APIs.
Why it matters
Without this, any plugin adding a legitimately per-viewport toolbar affordance (position/offset handles, per-device toggles) has no supported way to keep it reachable in the one mode it belongs in, and no signal to detect that mode. The inspector story is being solved for 7.2; the toolbar should not be left as a private-API-only path.
Happy to provide a minimal reproduction plugin.
Related: #80388 (7.2 iteration), #82003 (viewport inspector group), #82082 (custom controls in responsive styling), #78280 (reverted broad approach → explicit allow-list).
Activity
tellthemachines commentedon Sep 25, 2026
With #82741 merged, this should already be doable so closing this one for now.