Problem/Motivation
Since #3562060: Render UI with admin theme the builder UI runs on the admin theme and the Canvas renders each component in its own declarative shadow DOM, on the front theme.
One shadow tree per component costs the Canvas fidelity:
- a selector spanning a parent and a child component does not match (Bootstrap navbar links lose their padding)
- the theme's JS does not run (accordions, carousels, dropdowns stay static)
- the theme's web components stay undefined or get the builder's own version of a shared tag, and
remfollows the admin page
The Preview panel has none of these problems: it is an iframe of the real page.
Proposed resolution
- Render the Canvas in a same-origin iframe, on a new front-theme route, as the Preview does. The iframe runs no builder script and no htmx.
- The builder page drives it: it listens on the iframe document and sends every request through its own htmx, so the out-of-band swaps of the other islands are unchanged.
- The Canvas refreshes through a token, like the Preview, reloading into a buffer iframe with the scroll and the selection kept.
- Drops from the library and the Scaffold reach the iframe through an overlay over it; reordering inside the Canvas uses the iframe's own Sortable.
- Behind an
iframesetting of the Canvas island, off until every Canvas interaction works in it, then on by default.
A spike passed: front theme and its JS in the Canvas, selection, refresh and drops in Chromium and Firefox. An insert refreshes in 400 ms against 696 ms for the shadow DOM Canvas on the same layout.
Remaining tasks
- Canvas page and iframe mode, with kernel tests.
- Refresh by token.
- Selection, contextual menu and keyboard shortcuts across the frame.
- Drag and drop into and inside the iframe.
- Highlight and loading state in the iframe, sidebar resize over it.
- Viewport switcher on the Canvas.
- Switch the default on, migrate the Canvas Playwright tests.
User interface changes
The Canvas looks and behaves like the real page, theme JS included, and the viewport switcher applies to it. A node cannot be dragged out of the Canvas into the Scaffold or the Navigator at first.
API changes
None.
Data model changes
New iframe setting on the Canvas island of a profile, false by default.
AI-Generated: Yes
Issue fork display_builder-3629497
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:
- 3629497-canvas-iframe
changes, plain diff MR !469
- 3629497-iframe-only
changes, plain diff MR !470
Comments
Comment #2
mogtofu33 commentedComment #3
pdureau commentedDo we need such a setting? It may be better to use the way which work the best, instead of having 2 different implementations and asking the user to pick one.
I guess we already have this problem with the dropzone in between a slot and its renderable content. So it may not be introduced to DSD.
It would be nice to fix that, indeed.
The first issue may be related to is the
once()function provided by https://github.com/drupal/drupal/blob/bf4ae811643c6e50e5263e19f8eb28e123... which is always returning an empty array, maybe because thecontextobject passed a third parameter is the full page instead of the shadow dom.I have no idea about webcomponents being undefined. Maybe it is a similar issue.
Comment #4
mogtofu33 commentedProbably no setting, I think the idea was it's because not all themes will have js/css fix necessity.
Yes for some part, for example Bootstrap component navbar_nav in a navbar slot, before menu are inline, with the DSD admin menu items are stacked. It's obvious on the Bootstrap recipe that use that.
I guess it's related to custom wc that needs js init. Not tested as it's very specific and we have no full theme with wc.
My point of view as discussed is that this is a proposition to review and not something that needs to be done, just looking if we have a clean working solution, if not it can be for later.
Will push a draft to review soon.
Comment #6
pdureau commentedHello,
I moved #3562060: Render UI with admin theme to RTBC and I am evaluating this proposal.
I guess the big diff in this MR (+4795 -1086) is because there are rendering modes (DSD & iframe) with a config switch, and if we pick iframe at the end, the MR will be way more compact.
I don't see any
in_iframeoption in BuilderPanel configuration modal, but that's OK because I only need to test the iframe version here.Comment #7
pdureau commentedFeature review
Work in progress:
DaisyUI
Bootstrap
DSFR
✅ It works well with Bootstrap Carousel & Accordion.
✅ It is lovely to have Preview floating controls into Canvas panel.
That's great news !!! I don't "feel" this speedup, but the number are impressive, and DSD was already feeling faster/snappier than the current 1.0.x where we render the Builder in front theme.
Code review
This feature woks well and looks "final", and the "price" to pay was a bump of JS code (+20%):
So, if my understanding is right:
This raises some questions if we go the iframe way:
db-block? It was useless in #3562060: Render UI with admin theme because ofdb-isolatebut what about now?Comment #8
pdureau commentedHi Jean,
The current draft is very exciting. I have shared my first thoughts in previous comment. What are the next steps?
Comment #9
mogtofu33 commentedI forgot to update the summary: the setting is removed.
Yes, without the shadow root the reason for #3627001: Invalid HTML nesting in the Canvas takes the contextual menu and the messages out of the builder is back: a wrapper inside markup the browser closes early must be a custom element, or its closing tag closes an ancestor.
Added a commit here to use
<db-block>again, for block and component boxes, registered in the iframe.Mostly right, but it went both ways. The front theme reaches the dropzones, placeholders, boxes and the hover label, which is manageable. Ours reached the front theme too: the iframe loaded Shoelace's theme, which sets
color-schemeand every--sl-*token on:root, and our token files with generic names. It now loads none of them: the builder page copies the tokens the chrome reads onto the iframe root, so the Canvas chrome also follows the builder's dark theme. The button placeholder is plain markup, as Shoelace's script never ran there.Yes, it still gives what the Canvas does not: the draft on its pinned page with the theme's regions around it, and the output without dropzones and boxes.
But it's not a first-class feature as before, so the split can be challenged with a preview integrated in the Canvas panel for example.
Depends on some choices: DSD is still required for the Scaffold rendered components and the library hover previews, but:
:rootrewrite.One part was only used by the shadow DOM Canvas, the lazy build of blocks:
SourceLazyBuilder::lazy()now requires a component source.Next steps: once !468 is merged, I rebase this MR without its commits, so the diff shows only this work.
AI-Generated: Yes (review analysis and part of this text drafted with AI, reviewed and edited by me)
Comment #11
mogtofu33 commentedAdded proposition with full iframe, no more DSD and loss of Scaffold render components.
Comment #12
pdureau commentedOK, cool, so now we have 2 MR:
canvas_frame,canvas_frame_inner&canvas_queryaddedshadow_root_styles.js&htmx_shadow_domremovedCanvasControlleraddedDeclarativeShadowDomRenderer,SourceLazyBuilder&SubRequestInternalControllerremovedThe removal of the hook theme and the 2 templates (
html--ds-shadow-dom.html.twigpage--ds-shadow-dom.html.twig) is warmly welcomed.Currently testing the 2 branches. If they provide the same features with the same perf, I would advocate to go full iframe.
I am taking time because there is something "to good to be true" here:
Let's check
Comment #13
mogtofu33 commentedNote that #3630345: Preview as a switch on the Canvas, and in a new tab, instead of a split view is progressing in top of 3629497-iframe-only.
To provide a better experience with preview, it includes some minor fixes on current iframe branch and helped discover performance issues fixed on display builder, and some other related issue for performance problems in UI Patterns:
Comment #14
pdureau commentedOK, thanks, having a look on both.
Comment #15
pdureau commentedReplaced by #3630345: Preview as a switch on the Canvas, and in a new tab, instead of a split view