Resolve #3576683 "Ux refresh"

Closes #3576683

Scale

  • 155 commits ahead of 1.0.x, 0 behind (branch fully contains 1.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.yml changes — the service graph is stable.
  • Event constant names unchanged (src/Event/DisplayBuilderEvents.php untouched) — 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 — a string with a Choice(label | icon | icon_label) + FullyValidatable constraint.
  • New profile keys: library_flat, library_tabs_display, contextual_tabs_display, view_panels_display.
  • New display_builder.islands.scaffold (components: string) and display_builder.islands.preset_library.preview: boolean.

One structural change to watch: near the fullscreenexpand 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 / saveAsPreset routes 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_itemtree_node (components/tree_node/). Any custom template embedding these breaks.

  • JS/CSS relocated out of assets/ into per-component directories:

    • assets/js/contextual_menu.jscomponents/contextual_menu/contextual_menu.js
    • assets/js/form_description.jscomponents/display_builder/js/form.js
    • assets/js/search.jscomponents/library_panel/search.js
    • assets/css/search.csscomponents/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

  1. Decide the layers ID-removal policy (breaking-notes vs. post_update) — the one that can bite real upgrades.
  2. Identify/document any external HtmxTrait, direct IslandInterface, or ApiControllerInterface implementers.
  3. Verify the sequence → string island-setting schema change against any real stored profile.
  4. Confirm sub-themes are not overriding the moved JS/CSS or the removed shoelace components.
Edited by Jean Valverde

Merge request reports

Loading