Resolve #3576683 "Ux refresh"
Closes #3576683
Scale
- 155 commits ahead of
1.0.x, 0 behind (branch fully contains1.0.x). - 298 files changed, +14,567 / −6,879. A large UX-refresh branch, not an incremental change.
- Heaviest churn:
tests/src(68),modules/display_builder_entity_view(27),src/Plugin(25),modules/display_builder_page_layout(17),components/display_builder(17),components/shoelace(15),assets/js(10).
Good news up front:
- No
*.services.ymlchanges — the service graph is stable. - Event constant names unchanged (
src/Event/DisplayBuilderEvents.phpuntouched) — the island event fan-out names are stable.
🔴 Highest risk — needs a decision before merge
1. Island plugin ID layers removed, no migration
src/Plugin/display_builder/Island/LayersPanel.php (id: 'layers') was renamed to WireframePanelBase.php, now an abstract base class with no id. There is no layers id anywhere in HEAD.
Net island-ID delta vs 1.0.x:
| IDs | |
|---|---|
| Removed | layers |
| Added | scaffold, save_status, highlight, menu_styles |
There are no hook_update_N / hook_post_update_NAME() hooks in the branch.
Island plugin IDs are a stored-config contract: profiles persist island IDs, so removing one breaks any saved profile that references it. Any site upgrading from 1.0.x with a stored profile referencing layers will silently lose that panel (the plugin no longer exists). The branch's own config/optional/display_builder.profile.*.yml referenced layers on 1.0.x.
Decision needed: acceptable only if either (a) 1.0.x is still pre-stable and this is documented as a breaking change in the release notes, or (b) a post_update hook is added to rewrite layers → its replacement in stored profiles. Neither exists in the branch today.
2. HtmxTrait deleted → DisplayBuilderHtmx static class
src/HtmxTrait.php (protected addOutOfBand(), makeOutOfBand(), addTarget(), setTrigger()) was removed and replaced by final class DisplayBuilderHtmx exposing public static makeOutOfBand().
The only in-repo consumer was IslandPluginBase, so internal migration is complete — but any external island using HtmxTrait will fatal (missing trait). The set of helpers also narrowed (several protected trait methods → one static method).
🟠 Interface changes (BC breaks for direct implementers)
3. IslandInterface — 2 methods added
public function isDeferrable(): bool;
public function reload(InstanceInterface $instance): array;Part of the new off-screen island deferral system. IslandPluginBase provides default implementations, so islands extending the base are safe; islands implementing IslandInterface directly will fatal. Low external risk since extending the base is the normal path.
4. ApiControllerInterface restructured
paste(), delete(), saveAsPreset() were removed from ApiControllerInterface and moved to the new ApiContextualMenuControllerInterface / ApiContextualMenuController, with changed signatures, e.g.:
// before
public function paste(Request $r, InstanceInterface $i, string $node_id, string $parent_id, string $slot_id, string $slot_position): array;
// after (on ApiContextualMenuControllerInterface)
public function paste(Request $r, InstanceInterface $i): array;Positional route args became request-body data. New method added: reloadIsland(Request, InstanceInterface, string $island_id): array. This is route-callback surface, so external callers are rare, but it is a genuine interface break.
5. ProfileInterface — 4 methods added
public function isLibraryFlat(): bool;
public function getLibraryTabsDisplay(): string; // 'label' | 'icon' | 'icon_label'
public function getContextualTabsDisplay(): string;
public function getViewPanelsDisplay(): string;Only Profile implements this interface, so external risk is minimal. Config BC is safe: the backing properties have typed defaults (bool $library_flat = FALSE, string $library_tabs_display = 'label', contextual_tabs_display = 'icon', view_panels_display = 'icon_label'), so stored profiles missing these keys fall back cleanly — no TypeError on the typed getters.
6. DisplayBuilderEvent — 1 method added
public function getVisibleIslands(): ?array;Feeds the deferral fan-out. Additive.
🟡 Config schema & routing
Schema (config/schema/display_builder.schema.yml)
Mostly additive:
- New reusable type
display_builder.panels_display— astringwith aChoice(label | icon | icon_label)+FullyValidatableconstraint. - New profile keys:
library_flat,library_tabs_display,contextual_tabs_display,view_panels_display. - New
display_builder.islands.scaffold(components: string) anddisplay_builder.islands.preset_library.preview: boolean.
One structural change to watch: near the fullscreen → expand rename an island setting went from type: sequence (string[]) to a scalar type: string. A stored array value there will no longer match the new scalar schema. Confirm which island this is and whether any shipped or stored profile carried the old sequence form.
Routing (display_builder.routing.yml)
- No route keys removed.
- 3 routes added:
api_island_reload,api_paste_styles,api_delete_styles. - The
paste/delete/saveAsPresetroutes were re-pointed to the new controller and lost their path arguments. URLs are built server-side (HTMX), so low risk unless something hardcodes them.
🟡 Templates / assets (embedders & sub-theme overrides)
-
SDC removed:
shoelace:drawer,shoelace:tree. Renamed:shoelace:tree_item→tree_node(components/tree_node/). Any custom template embedding these breaks. -
JS/CSS relocated out of
assets/into per-component directories:assets/js/contextual_menu.js→components/contextual_menu/contextual_menu.jsassets/js/form_description.js→components/display_builder/js/form.jsassets/js/search.js→components/library_panel/search.jsassets/css/search.css→components/library_panel/search.css
The library definitions are updated in-branch, but any theme/library override pinned to the old paths breaks.
Suggested reviewer focus order
- Decide the
layersID-removal policy (breaking-notes vs.post_update) — the one that can bite real upgrades. - Identify/document any external
HtmxTrait, directIslandInterface, orApiControllerInterfaceimplementers. - Verify the
sequence → stringisland-setting schema change against any real stored profile. - Confirm sub-themes are not overriding the moved JS/CSS or the removed shoelace components.