An optional WordPress editor control can disappear because it has no value, because the user hid it, or because its saved visibility preference was never restored. Those are different states. Do not write a dummy block value just to keep the control on screen.
Check the component your plugin actually loads
This guide concerns developers using ToolsPanelItem, not a setting every site owner can enable. Record WordPress, Gutenberg and the component package used by your plugin. A new package in a development lockfile does not prove that the browser loaded that version.
The component remains experimental in the official handbook. Confirm the available exports and props in your supported build before changing production code. If you consume WordPress-provided packages, test the supported WordPress versions rather than assuming your local package installation replaces the platform copy.
Keep three facts separate
Start with a synthetic spacing control. Record its block attribute, whether the control is visible, and the stored preference for showing it. Use a separate key for the preference. A visibility choice should not become part of the public page's spacing value.
The newer defaultShown prop supplies initial visibility for an optional item without a value. It is not a controlled visibility setter: changing it after the item mounts does not override the user's current choice. A value-bearing item is shown independently of that initial default.
Do not confuse this with isShownByDefault, which marks an always-visible control. If you need a user-hideable setting, making it always visible changes the interaction instead of fixing persistence.
Initial render: Restore the visibility preference. Menu action: Record onShownChange. Value reset: Keep onDeselect separate. Reload: Confirm preference survives. Proposed verification, not a customer test result.
Reproduce the empty-control failure
Use a staging post and a control whose value is genuinely absent, not zero masquerading as empty. Then follow this sequence while recording callbacks:
- Mount the panel with the optional control initially shown. Registration alone should not be counted as a user menu action.
- Hide it through the panel menu without setting a value. Capture onShownChange(false).
- Show it again and capture onShownChange(true). Check any onSelect behavior separately.
- Assign a real value, hide the control, and verify the reset behavior associated with onDeselect.
- Reload the editor and compare the stored preference with the initial state.
The important failure is step two. onDeselect is associated with resetting a value; it does not provide the complete visibility history for empty optional controls. Use onShownChange for the explicit show/hide preference and keep value reset logic separate. Wiring the same persistence operation into both callbacks can process one menu action twice.
Resolve an asynchronous preference before relying on a default
Imagine the editor mounts with defaultShown false and then receives a saved true preference. Simply changing that prop later is not a reliable way to reopen the already-mounted item.
Choose an explicit loading design for your integration. For example, resolve the preference before mounting the optional control. Keep a stable loading area so the sidebar does not jump around, and handle a failed preference read without modifying post content. Treat this as an application design choice to test, not an automatic behavior supplied by the component.
Scope preferences intentionally. Test two users, two posts and two controls with distinct identities. A shared preference key can make one author's choice change another control unexpectedly. Avoid using translated display text as your own durable storage identifier.
Test reset without inventing a menu click
Reset all and programmatic value changes are not necessarily explicit menu actions. Do not infer missing telemetry from the absence of onShownChange in those cases. Decide whether Reset all should reset values only or also restore your application's visibility preferences, then implement and document that policy separately.
Acceptance means the expected controls reopen after reload, an empty optional control can be hidden, real values are reset only by the intended action, and no preference write changes the saved article. Include keyboard operation in the test.
Use the WordPress staging preparation checklist for the surrounding update test. HandL WP can investigate an editor integration with your component versions and a small callback trace.
References: ToolsPanelItem handbook and the merged component change. The trace shown here is an expected test sequence, not a recording from a customer's site.
References reviewed October 20, 2026. Diagrams and test fixtures are explanatory, not customer results.
If the control remains visible but its dropdown clips long choices, inspect the popup sizing contract: WordPress Select Popup Too Narrow? Check the Width Prop.