Problem/Motivation
Edit Mode sidebars were assembled imperatively in Edit::buildSideBars() and the client tracked a single active sidebar at a time. This had several limits:
- Only one panel could be open across the whole UI, so a left-rail tool palette and a right-rail panel could not be shown together.
- Panels were effectively tied to Edit Mode; an always-on panel (for example an AI chat available on every page, including anonymous and non-edit routes) had nowhere to live.
- Tools contributed panels through
buildLeftSideBar()/buildRightSideBar(), which the mode hard-wrapped, so panels were not independently discoverable or reusable.
Proposed resolution
Introduce a discoverable #[Sidebar] plugin type, move panel assembly to NavigationPlusUi, and make the client SidebarManager track one active panel per side.
- Add the
Sidebarattribute,SidebarInterface,SidebarPluginBaseandSidebarPluginManager. Two axes govern a panel:applies()decides DOM presence, while themode/toolbinding plus the{id}_sidebaropen/close cookie decide visibility. - Move sidebar building from
Edit::buildSideBars()intoNavigationPlusUi::buildSidebars(),buildSidebarPanel()andisSidebarVisible().buildSidebarPanel()is public so dynamic, per-request panels (e.g. edit_plus per-entity Change forms) can be rendered for AJAX replacement into the stablenavigation-plus-{side}-sidebarwrapper. - Port the built-in Settings and Notifications panels to
#[Sidebar]plugins. Their toggle buttons are pulled from the plugins into the mode top bar; an always-on (mode-independent) panel instead gets a fixed-position floating launcher. - Extract
ModeState, a lightweight request-derived mode lookup, so the cookie-auth-critical messenger decorator no longer depends on the now heavierNavigationPlusUi(which pulls in the plugin managers), avoiding a container circular reference. - Dispatch
LoadEditablePageEventwhen the editable page AJAX response is built so modules can attach their own commands. - Client:
SidebarManagerexposesopenSidebar(id)/closeSidebar(id)/closeSide()/closeAll()/closeEphemeral()as the single open/close path; type and side are read from the panel element. A sharedCLOSE_BLOCKEDsentinel and a[data-sidebar-close]behavior let a panel own its close control. Persistent panels survive leaving Edit Mode.
User interface changes
- Left- and right-rail panels can now be open simultaneously (one active panel per side, mutually exclusive within a side).
- Always-on panels render a floating launcher button outside Edit Mode.
API changes
- BC break:
ToolInterface::buildLeftSideBar()andbuildRightSideBar()are removed. Tools that need a panel now ship a#[Sidebar]plugin. - New plugin type
#[Sidebar](Plugin/Sidebar/), with manager serviceplugin.manager.navigation_plus_sidebarsandhook_navigation_plus_sidebar_info_alter(). - New
navigation_plus.mode_stateservice (ModeState);EditModeMessengernow depends on it instead ofNavigationPlusUi. NavigationPlusUigains publicbuildSidebarPanel(),isSidebarVisible(),getActiveTool()andgetToolPlugins().- New
LoadEditablePageEvent. - Shared sidebar JS moved to the
navigation_plus/sidebarlibrary; theSidebarManagerAPI changed from a single active sidebar to per-side tracking.
Comments
Comment #3
tim bozeman commentedComment #5
tim bozeman commentedComment #6
tim bozeman commented