Problem/Motivation
When I configure a Display Builder profile,
I want the View panels to be where they were designed to be,
so I can stop choosing between placements that were never meant to work.
For View panels the choice is not real, libraries or navigator makes no sense in the main, as well as builder on sidebar. Historically preview could make sense but is now shipped separately as a split view in main.
The flexibility of regions create permutations nobody test.
The precedent already exists in the codebase: Floating islands declare attach_to as a fixed plugin property, deliberately not admin configurable, for the same reason.
Steps to reproduce
Proposed resolution
Make View panel placement structural, owned by the plugin.
IslandType::regions()— remove theViewcase.ProfileFormalready
handles an emptyregions()result, so the Region column stops rendering for
View islands with no form change.ProfileViewBuilder::prepareViewIslands()— read the plugin definition's
default_regioninstead of$configuration['region'for the sidebar/main
split.Profile::setIslandConfiguration()— the region preservation branch stays,
Button islands still use it. Fix the comment.config/optional/display_builder.profile.default.yml— drop the now dead
region:key from the View islands.hook_post_update— stripregionfrom View islands in stored profiles, so
exports do not carry a key nothing reads.
Out of scope, on purpose:
- Button
regionstays configurable.save_statusoverrides the plugin
default to sit at the toolbarstart, and left or right of the toolbar is a
genuine preference with no wrong answer. The schema key and the last
IslandType::regions()case stay for it. Whether toolbar placement should
also be structural is a product decision, not this cleanup. - The
library_flat,library_tabs_display,contextual_tabs_displayand
view_panels_displayknobs. Separate issue.
User interface changes
The Region radio disappears from the profile form for View panels. It stays for toolbar buttons. No change to the builder itself.
API changes
`IslandType::regions()` returns an empty array for the `View` type. Any custom View island plugin relying on a profile stored region now needs `default_region` on its `#[Island]` attribute.
Data model changes
None to instance state. Profile config only: the `region` key on View islands becomes ignored, then removed by the post_update hook. The schema key stays, Button islands still use it.
| Comment | File | Size | Author |
|---|---|---|---|
| #10 | Capture d’écran du 2026-08-12 19-14-38.png | 79.32 KB | pdureau |
Issue fork display_builder-3614990
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mogtofu33 commentedComment #3
mogtofu33 commentedComment #5
mogtofu33 commentedComment #6
mogtofu33 commentedComment #7
mogtofu33 commentedComment #8
mogtofu33 commentedComment #10
pdureau commentedSo, we have for the main area:
For the sidebar:
But they are all mixed in the Profile edit form:

Which is confusing, because we drag and mix stuff which are always separated at the end. I know it was more or less the case already, but at least there was a reason for that.
Also, the
default_regionattribute has now 2 different meanings, as explained in the doc:Why not clarifying/simplifying this by splitting the
IslandType::Viewbetween something likeIslandType::MainandIslandType::Side?Comment #11
mogtofu33 commentedRight double usage of
default_regioncould have a fix, but split seems problematic:IslandType match a slot in render pipeline to
components/display_builder/, the deferrable feature (raise +1 case),prepareViewIslandsis impacted, and DOM class used for css/js. Main and Side will be extremely close codewise (base class, traits, event, keyboard,...).So the collateral is important and a split will inflate instead of simplify, with a bunch of Playwright affected. I feel it require a more profound refactor to simplify, which for now seems to me not worth it.
AI recommend 2 new enums:
IslandRegion::main|sidebarandToolbarSide::start|endto fix the mix of usage/impact/meaning between buttons and viewPanels. So no moredefault_regionremoveIslandType::regions(), and we addIslandInterface::getRegion()IslandInterface::getToolbarSide()Benefit is no css/js Playwright impact, possible easier post_update, better clarity for Island builders.
Wdyt?
Comment #12
pdureau commentedOnly this would be kind of fine, but this alongside the UX issue in admin UI is concerning. We need to find a way to fix both together.
OK. Let's try to simplify and not make a mess.
Sorry if I am rounding about the AI proposal, but I am still sorting this out.
So, we already have 2 mechanisms in play here: the IslandType and the region, and it would be great to not add more.
Can we keep those two with a single change: regions are not a configurable value anymore? Neither for view panel (as already stated by your MR), nor for buttons:
default_regionattributes simply becomeregionProfileViewBuilderIslandType::regions()and put the View panels one back there (as it is currently in 1.0.x).This will also allow us to address the UX issue: instead of a "region" table column in the admin UI, we print a distinct table by region in the panel type. Mockup for View Panels:

It would be easier for users to understand:
This change nothing in the storage, which is still a flat list of islands with weight:
What do you think?
Comment #13
mogtofu33 commenteddefault_region→ region, non-configurable for buttons too. IslandType::regions() keeps both types, and the admin UI prints one table per region. Storage unchanged, post_update_3 now strips region from every island.One catch: save_status was region: start in the shipped profiles while the plugin declared end. Fixed the plugin to start, so nothing moves. Every other island already matched its plugin default. We could follow up, and as discussed it could be a task with history/state/logs to decide where to bring the logs messages and mostly merge or deprecate
save_statusthen.Region is resolved once in IslandPluginManager::processDefinition(), so an invalid value falls back to the type default instead of vanishing from the form.
Unrelated but had to add a bit of cleanup to
clearlegacy, mostly to round up tests that this one touch.Comment #14
pdureau commentedOk, that's great.
Comment #15
mogtofu33 commented