Overview

For the sdc ComponentSource plugin

When a component is placed it is assumed that it contains at least some HTML, which is wrapped in comments and has a data attribute attached so the XB UI can manipulate it.

However, it is not mandatory for components to output any HTML at all, e.g. if the component contains defensive code such as

{% if image and image.src %}
  <img src="{{ image.src }}" alt="{{ image.alt }}" />
{% endif %}

It is also possible for a component to output text, but not HTML.

For the block ComponentSource plugin

#3497747: Global regions containing only "dynamically missing blocks" (due to emptiness or access) cause malformed pages fixed the incorrect rendering of pages rendered not by the BlockPageVariant but by XB's XbPageVariant, when it is rendering blocks.

But, as demonstrated at #3497747-18: Global regions containing only "dynamically missing blocks" (due to emptiness or access) cause malformed pages, a critical bug remains:

This is caused by blocks possibly resulting in an empty render array to render:

    $content = $block->build();
    if (Element::isEmpty($content)) {
      $content['#access'] = $access;
      return $content;
    }

👆 Inside XB's preview while editing, the preview is very different from the end result, due to the need to visualize upon hovering component instances in the Layers panel where on the page those component instances are placed.

😭 Unfortunately, the designs do not provide answers for the highly dynamic Block-sourced Components: it assumes all component instances in the Layers panel are always visible. That's not true for many Block plugins:

  • messages block
  • local tasks block
  • local actions block

Proposed resolution

TBD.

For sdc components

When we are previewing a component that does not contain any HTML tags, detect this special situation and wrap them in a container, so they can still be previewed and manipulated correctly by the UI.

For block components

⚠️ This likely requires the use of \Drupal\Core\Plugin\PreviewAwarePluginInterface — because some blocks only render at all in specific contexts — for example: the messages block is only visible at all when there's actual messages.

See \Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray::onBuildRender() (see also how that uses \Drupal\Core\Render\PreviewFallbackInterface), introduced in #3027653: Allow block and layout plugins to determine if they are being previewed and CR at https://www.drupal.org/node/3272267. Note that this will also require core changes, because not all crucial block plugins implement that interface, which is why #3137995: Can't manage Status Messages block in Layout Builder still exists.

P.S.: This tangentially relates to #3491701: [later phase] ApiLayoutController must use the previewed route's controller, and override canonical content entity routes' received entity object, because without that, the preview will not be accurate. Hopefully we can do that at a later time, though.

User interface changes

TBD

Comments

wim leers created an issue. See original summary.

effulgentsia’s picture

Title: [Needs design] Previews of pages containing (dynamically) empty blocks are malformed » The XB canvas incorrectly renders blocks (and their corresponding margins as specified by the theme's CSS) that usually have empty content for most/all site visitors
Issue tags: -Needs design

I think we should make two quick hard-coded fixes for now, and then figure out how to abstract and provide UI affordance in a follow-up:

  • Don't render the Highlighted region within the canvas. It can still be in the layers panel.
  • Don't render the Help block within the canvas. It can still be in the layers panel.

My premise here is that what editors generally want to see in the canvas is what their site visitors will see under typical circumstances, not what only other admin users will see or what site visitors will see only under rare circumstances. There's plenty of gray area around this, but the above two items seem pretty clear cut to me, and I wonder how much closer the canvas will get to the preview with just those two fixed.

lauriii’s picture

I agree with the premise set by @effulgentsia in #2. There was already some related discussion in #3489899: Add support for global regions on this.

Content creators not seeing the site as the site visitor is a pain point that comes up consistently in interviews with users. There are several actions that are already on the way to make the rendered preview represent more closely what an actual visitor of the site would see.

We are already moving local tasks from the page to the navigation in Drupal Core in #3402046: Create the Top Bar. The goal would be to do the same for local actions.

Messages may need a special case along with main content and help because they are usually not changed after the initial configuration. The initial configuration could be done by a developer.

effulgentsia’s picture

wim leers’s picture

Per #4.

wim leers’s picture

Assigned: wim leers » effulgentsia
Status: Active » Needs review
Related issues: +#3497648: Focus mode for global regions
StatusFileSize
new85.24 KB

The way both of you are talking about this, is about hiding irrelevant regions from the XB user. That's a different problem than the one described in the issue summary.

We can do that, but then not here: I don't want to repeat the problem space I outlined in the issue summary that will still need to be resolved anyway.

Hardcoded temporary work-around for hiding irrelevant regions in Olivero only, imperfectly

I disagree with #2 (and hence #3) being a solution to the problem described in the issue summary.

It would only solve the "problem" for a very small set of users:

  • Those using Olivero
  • Those who aren't putting similarly dynamically empty blocks in other regions: primary_menu, secondary_menu, hero

All #2 would achieve is the out-of-the-box experience for Olivero users, without placing more blocks.

I'm fine with doing what's proposed in #2, if it's something that we believe improves #3455753: Milestone 0.2.0: Early preview for the Drupal CMS demoing purposes. But then it must be explicitly acknowledged that this MUST be removed prior to 1.0-stable.

A possible long-term solution

I agree that hiding certain regions is likely worthwhile, actually! (Related: #3497648: Focus mode for global regions would become more usable/useful as a bonus!)

Proposal:

  • Build upon this single checkbox:
  • … upon checking it, show a list of checkboxes: one per region, to allow opting specific regions out from editing through XB.
  • This information could trivially be stored in the PageTemplate config entity.
  • … we could then automatically respect that in ApiLayoutController + ApiPreviewController
wim leers’s picture

wim leers’s picture

Title: The XB canvas incorrectly renders blocks (and their corresponding margins as specified by the theme's CSS) that usually have empty content for most/all site visitors » [later phase] [Needs design] Previews of pages containing (dynamically) empty blocks are malformed
Assigned: effulgentsia » Unassigned
Priority: Critical » Major
Status: Needs review » Postponed
Issue tags: -Drupal CMS dependency critical +Needs design
Parent issue: #3497543: Milestone 0.2.0: the one for Drupal CMS 1.1 »

#3498248 works. See #3498248-21: PageTemplate: allow configuring which regions are exposed.

Restoring original title. I explained in #6 why #2 is about a different problem.

That also means this is no longer a Drupal CMS dependency critical, because the proposal in #2 is achieved in #3498248: PageTemplate: allow configuring which regions are exposed. 😊

wim leers’s picture

Title: [later phase] [Needs design] Previews of pages containing (dynamically) empty blocks are malformed » [Needs design] Previews of pages containing (dynamically) empty blocks are malformed
Component: Page builder » Component sources
Issue tags: +stable blocker
Related issues: +#3518250: [PP-1] Handle components instances rendering nothing: wrap them in a container

I think #3518250: [PP-1] Handle components instances rendering nothing: wrap them in a container is a duplicate of this. Let's see if @longwave agrees :)

wim leers’s picture

Title: [Needs design] Previews of pages containing (dynamically) empty blocks are malformed » [Needs design] SDCs and Block plugins that (sometimes) render as an empty string are impossible to interact with in XB's canvas
Issue tags: +Needs title update, +Needs issue summary update

… but #3518250 is for SDCs, wheras this one is for Blocks. I think we need a general solution for all component sources!

longwave’s picture

Title: [Needs design] SDCs and Block plugins that (sometimes) render as an empty string are impossible to interact with in XB's canvas » SDCs and Block plugins that (sometimes) render as an empty string are impossible to interact with in XB's canvas
Status: Postponed » Active

Aha, good find - I agree that #3518250: [PP-1] Handle components instances rendering nothing: wrap them in a container is basically a duplicate, will close that one.

However I think we can try to do something here even without a design? There are two slightly different cases here: a component that's completely blank, and a component that contains some text but no HTML wrapper.

I think we need to ensure that we are at least outputting an HTML tag that can have the XB UUID attached so the front end can find something to receive the click/be draggable/etc. We could also add some text similar to the "broken" block in core if there is none at all in the output? Leaving the "needs design" tag but removing the postponed flag because I think this could be worked on now and iterated over time.

effulgentsia’s picture

I think we need to ensure that we are at least outputting an HTML tag that can have the XB UUID attached so the front end can find something to receive the click/be draggable/etc.

Now that we have #3512455: Implement new drag-and-drop solution that removes the need to drop items into the preview iFrame, do we really need this? I think what's receiving the click now is a transparent box over the iframe, and the bounds of the component are known by the HTML comments before and after it, so we shouldn't need to wrap the bare text that's inside the iframe, or at least I hope we don't have to. It would be great to keep our previews accurate regardless of what CSS people happen to have by not having to insert any wrappers.

larowlan’s picture

I still think it makes sense to use \Drupal\Core\Render\PreviewFallbackInterface::getPreviewFallbackString as there are some blocks that might be expecting this
We could have the component source interface extend that and defer to each source on how to handle an empty component

wim leers’s picture

Issue summary: View changes
wim leers’s picture

Assigned: Unassigned » lauriii
Status: Active » Needs review
Issue tags: -Needs title update, -Needs issue summary update +Needs product manager review

@larowlan in #13: That is indeed a possibility, but it violates the promise of “accurate previews”. So I think @lauriii won’t want to follow Layout Builder’s example?

lauriii’s picture

Assigned: lauriii » Unassigned

Layout Builder has to use \Drupal\Core\Render\PreviewFallbackInterface::getPreviewFallbackString because it doesn't have an alternative way to interact with the blocks that have been placed. In Experience Builder, we do have the layers as an escape hatch.

Relying on the layers isn't necessarily ideal so there's a trade-off between preview accuracy and discoverability of these components. I'll make sure to discuss this with @callumharrod and @reneelund in future but I don't think this is something we need to solve urgently.

I'm leaning towards removing this from stable blockers, and handling #3518250: [PP-1] Handle components instances rendering nothing: wrap them in a container separately as a stable blocker.

wim leers’s picture

Assigned: Unassigned » lauriii

@lauriii #3518250: [PP-1] Handle components instances rendering nothing: wrap them in a container has already been closed in favor of this — were you really intending to link to that? 🤔

lauriii’s picture

I did. I think we should do the narrower scope from #3518250: [PP-1] Handle components instances rendering nothing: wrap them in a container for stable and leave this as a separate issue to deal with later.

wim leers’s picture

Title: SDCs and Block plugins that (sometimes) render as an empty string are impossible to interact with in XB's canvas » [later phase] Support Block's PreviewAwarePluginInterface (and similar for other component sources)
Assigned: lauriii » Unassigned
Category: Bug report » Task
Status: Needs review » Postponed
Issue tags: -Needs product manager review

Alright. Retitling/tightening scope, and contrasting it with #3518250. Please confirm that I interpreted your comments correctly — both here and at #3518250-7: [PP-1] Handle components instances rendering nothing: wrap them in a container. 🙏

wim leers’s picture

lauriii’s picture

Issue tags: -stable blocker

Project: Experience Builder » Drupal Canvas
Version: 0.x-dev » 1.x-dev

Experience Builder has been renamed to Drupal Canvas in preparation for its beta release. You can now track issues on the new project page.

wim leers’s picture