Hi,

This looks totally awesome.
To improve the user experience, is it planned (if it even makes sense) to display a discreet spinner / loader image by default for all the blocks loaded after the first flush?

Thanks

Related reading

  1. http://www.callumhart.com/blog/non-blocking-uis-with-interface-previews
  2. http://www.callumhart.com/demo/building-interface-previews-with-react
  3. https://calendar.perfplanet.com/2016/progressive-storyboards/
  4. https://github.com/egoist/vue-content-loader
  5. https://web.dev/layout-instability-api
  6. https://css-tricks.com/building-skeleton-screens-css-custom-properties/ via @ronaldtebrake in #72
CommentFileSizeAuthor
#94 SkeletonScreenReview.gif213.04 KBronaldtebrake
#91 interdiff_88-91.txt750 bytespooja saraah
#91 2632750-91.patch7.45 KBpooja saraah
#88 interdiff_76-88.txt2.53 KBronaldtebrake
#88 interface_previews-2632750-88.patch7.46 KBronaldtebrake
#77 2632750-76-do-not-test.patch4.72 KBronaldtebrake
#77 interdiff_73_76.txt742 bytesronaldtebrake
#73 2632750-73-do-not-test.patch5.1 KBWim Leers
#73 interdiff.txt2.23 KBWim Leers
#72 Big pipe skeleton screen.gif206.28 KBronaldtebrake
#72 bigpipe-without-skeleton-templates.gif167.57 KBronaldtebrake
#60 2632750-60-do-not-test.patch4.65 KBzaporylie
#60 2632750-preview.gif499.74 KBzaporylie
#60 2632750-no-preview.gif829.86 KBzaporylie
#59 2632750-59-do-not-test.patch11.8 KBzaporylie
#35 interface_previews-2632750-35-do-not-test.patch8.79 KBWim Leers
#35 interface_previews-2632750-35-all_commits-do-not-test.patch21.67 KBWim Leers
#35 interdiff.txt1.88 KBWim Leers
#34 interface_previews-2632750-34-do-not-test.patch7.74 KBWim Leers
#34 interface_previews-2632750-34-all_commits-do-not-test.patch19.58 KBWim Leers
#34 interdiff.txt2.61 KBWim Leers
#33 interface_previews-2632750-33-do-not-test.patch6.62 KBWim Leers
#33 interface_previews-2632750-33-all_commits-do-not-test.patch16.69 KBWim Leers
#26 Screen Shot 2016-03-14 at 10.31.29.png46.28 KBWim Leers
#25 Screen Shot 2016-07-14 at 11.34.22 AM.png7.66 KBWim Leers
#23 interdiff.txt745 bytesWim Leers
#23 interface_previews-2632750-23-all_commits-do-not-test.patch16.61 KBWim Leers
#23 interface_previews-2632750-23.patch6.56 KBWim Leers
#23 BigPipe interface preview — detail.png49.29 KBWim Leers
#20 BigPipe interface preview.mp42.2 MBWim Leers
#20 interface_previews-2632750-all_commits-do-not-test.patch15.48 KBWim Leers
#20 interface_previews-2632750-20.patch6.59 KBWim Leers
#19 interface_previews-2632750-19.patch4.34 KBkrlucas
#15 interface_previews-2632750-15.patch3.93 KBPol
#13 interface_previews-2632750-13.patch3.91 KBPol
#7 interdiff_5-7.txt1.45 KBkrlucas
#7 interface_previews-2632750-7.patch3.75 KBkrlucas
#5 interface_previews-2632750-5.patch4.07 KBkrlucas

Issue fork drupal-2632750

Command icon 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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

fourmi4x created an issue. See original summary.

Fabianx’s picture

The plan I originally formulated at DrupalCon Barcelona was to use the theme system and theme system suggestions for the BigPipe placeholders itself.

e.g.


<div class="big-pipe-placeholder" data-drupal-id="...">
{% if preview %}
  <span class="preview">{{ preview }}</span>
{% endif %}
</div>

Then it would be possible to just create a:

theme/templates/big_pipe--block--user_login.html.twig

to override that block easily.

Obviously the suggestions to use would need some help, but it would

  • a) be the easiest in my opinion
  • b) allow to use theme_debug to find possible templates / suggestions
  • c) Usually it is the theme that knows how the preview should look
  • d) By providing a standard empty preview text, a module could still provide preview via hook_preprocess_big_pipe()

And possibly we could even provide a loading / spinner by default.

Thoughts?

Wim Leers’s picture

Title: Spinner / Loader ? » Interface previews
Priority: Minor » Normal

I'm not sure a spinner by default is a good idea. Imagine many simultaneous spinners. Imagine spinners in a display: inline situation. That'll be ugly and unusable.

That being said, we definitely need interface previews to improve the UX. I forgot to create an issue for that, so I'll just repurpose this issue.

I think #2 sounds like a great path to a first implementation/iteration of interface previews.

darol100’s picture

I do not think this should be part of big_pipe module instead of part of the theme project. Because the looks of the interface preview is going to depend base on theme looks. I think we should handle this by providing good documentation on how to support "Interface Preview" in your theme and provide few examples on how to provide support for the big_pipe project in your theme.

What you guys think about this approach instead of providing a interface preview that might look bad on a different theme ?

krlucas’s picture

Status: Active » Needs review
FileSize
4.07 KB

It seems like the first step is to make js placeholder markup theme-able. Patch attached.

I used the arguments for the #lazy_builder callback to create template suggestions and default classes which works OK for some things (like blocks), less OK for things like messages (it has no arguments).

Wim Leers’s picture

Wow, this is an awesome start! Thank you so much! Excited to have you work with us on this :)


This is very clever, but it also kind of breaks down as soon as the #lazy_builder callback argument order is unfortunate. For example, for the comment form, these are the suggestions:

  1. big_pipe_js_placeholder__node
  2. big_pipe_js_placeholder__node__6
  3. big_pipe_js_placeholder__node__6__comment
  4. big_pipe_js_placeholder__node__6__comment__comment

And indeed, for Drupal\Core\Render\Element\StatusMessages::renderMessages() it flat out fails.

I think using the #lazy_builder (and cleaning it up of course, removing colons and backslashes etc) instead would yield a more workable result. But even then it can be verbose.

I wonder if we can think of a more elegant solution. But again, I love this first iteration :)

krlucas’s picture

Glad to help!

Here's another iteration that uses the lazy_builder callback and cache keys (if available) for the suggestions. I also removed the class and id generation from the template preprocessor--it looks like most core modules just leave that up to the themes now.

krlucas’s picture

I raised this issue at the Boston Drupal meetup, demoing the current state of Big Pipe using the Big Pipe demo module (yay!!). In particular, I surfaced the issue of how to render a sensible, visual placeholder--one that claims page space so the page doesn't dramatically reflow as "actual" content is replaced--when by definition you and the system don't know much about the ultimate content.

One suggestion that came up was allowing users or developers to specify or suggest how the placeholder is rendered. For instance, if one is creating a custom block, allow the user to specify the relative size--small, medium, large--of the placeholder and then allow the theme to determine what that means in a particular region. There's a bunch of UX considerations here--in particular that a custom block would only really need that setting if the "Roles" visibility setting was set. Also "interface previews" are generally only necessary for content that appears above the fold.

But I think it does suggest an API change: #lazy_builder needs to be a little more robust. It should be able to provide not just a callback for the "real" content, but also some clues on how to render the placeholder. So #lazy_builder could be an array:

'#lazy_builder' => [
  '#callback' => '/the/method/that/renders/the/real/content()'
  '#placeholder callback' => '/the/method/that/renders/the/placeholder()' 
   'placeholder' [
     // And/or just a Render Array for the placeholder
   ]
]

Thoughts?

krlucas’s picture

Status: Needs review » Needs work
Wim Leers’s picture

Project: BigPipe » Drupal core
Version: 8.x-1.x-dev » 8.1.x-dev
Component: User interface » big_pipe.module

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Wim Leers’s picture

Version: 8.2.x-dev » 8.1.x-dev
Pol’s picture

Rerolled patch, just testing.

Pol’s picture

Now trying to find out why this is not working anymore.

Pol’s picture

Updated patch, working now.

If you want to see it working, edit the template and add some CSS:

<div{{ attributes }} style="background-color: #eeeeee; min-height: 100px;"></div>

Wim Leers’s picture

Wim Leers’s picture

Related to BigPipe because BigPipe can sometimes cause jumpiness, depending on the lazy-loaded content: https://developers.google.com/web/updates/2016/04/scroll-anchoring — Google Chrome is introducing scroll anchoring preventing jumpiness caused by reflowing.

krlucas’s picture

Note the latest patch is replacing explode() with DOMDocument parsing which I think is necessary to allow the placeholders to be fully theme-able (not dependent on the placeholder beginning exactly <div data-big-pipe-placeholder-id="). But there's discussion in issue #2678662: Ensure BigPipe does not break when HTML document contains CDATA sections or inline scripts matching certain patterns about whether DOMDocument is the best method.

krlucas’s picture

Re-rolled relative to the drupal root.

Wim Leers’s picture

I've thought about this some more. More importantly, I've been weighing whether this is something we should do in 8.1, or later. The thing is: we don't have enough insight or experience yet with how "interface previews" would and should work. I think #2702061: Unify & simplify render & theme system: component-based rendering (enables pattern library, style guides, interface previews, client-side re-rendering) and #2759849: Create a new user-facing core theme as part of a Drupal demo could and should inform how this works. Especially the latter.

What matter most at this time, is two things:

  1. Whether this can be added without breaking BC.
  2. Whether we see a mechanism to elegantly and simply define interface previews, again without breaking BC.

So, I set out to prove that. I did not look at any work done here so far, to see what I'd come up with independently, and in which ways that would be worse or better. My results:

  1. Note that we only can use interface previews if placeholders are replaced using JS. The JS doesn't need any modifications to support that (it's just looking for an element with a certain data- attribute). The PHP needs to be modified slightly: it should not rely on string parsing, but on DOM parsing to determine the order in which to render the placeholders. That's it! (Commit 1 in the patch.)
    Turns out that I independently came up with pretty much identical code to what #19 already contains :D
  2. I did three incremental iterations (commits 2, 3 and 4 in the patch) of this:
    1. The first one was just to get a sense of what the end user's experience would look like. So, no elegant mechanism to define placeholders, but ugly hardcoded. Great for end users, not yet great for developers/themers.
    2. The second one was to evolve the first one to a place where there is a way for a lazy builder to provide an interface preview. If the lazy builder is called controller::foo, then you can provide an interface preview for it by ensuring controller::fooPreview exists. Very simple. And very logical for those writing lazy builders. Great for end users, great for developers, but bad for themers: they can't override it to match their theme.
    3. However, if we can change it to not use hardcoded HTML, but use the existing #type and #theme and just pass in placeholder variables… then we're again in a great place. When doing so, specify __preview as a suffix, to indicate this is for rendering a preview. That means it is also overridable per theme: you can provide a Twig template to render a preview first. (In the case of comment links, a theme can provide links--comment-preview.html.twig.)

      This doesn't work for everything — it works for things like links and blocks, but it doesn't work for more complex things, like forms. Because forms are often highly customized on a per-site basis. And so the preview for one site won't be good for all sites. Although even there, we can have rough approximations, in templates that themes can override.

All this demonstrated in the included screencast (see below).

This patch shows that this can be done without breaking BC. It's a pure API addition. It's different from the prior patches in that it won't have a very tricky template name, and for the cases where a separate template is not necessary (like the comment links example), it's far, far simpler, and in fact doesn't require any work on the side of the themer: the preview will automatically match the final result! (This is also the direction #2702061: Unify & simplify render & theme system: component-based rendering (enables pattern library, style guides, interface previews, client-side re-rendering) takes.)

Wim Leers’s picture

Status: Needs review » Postponed
Related issues: +#2759849: Create a new user-facing core theme as part of a Drupal demo

I've moved this to 8.2, because I think this is something that we should first gain a better understanding of. #2759849: Create a new user-facing core theme as part of a Drupal demo will focus on component-based themes, and I think we may get valuable insights there about interface previews, that could help this implementation to change direction.

What matters, is that we've proven in two independent implementations (see patches #19 and #20) that this can definitely be implemented without breaking BC.

Therefore, marking this postponed for now.

The last submitted patch, 20: interface_previews-2632750-20.patch, failed testing.

Wim Leers’s picture

Dammit, I left some "resetting" code in the patch to record my screencast!

Also, I realize that the visual end result of the placeholders is not very clear at this low resolution. But posting the full resolution video would probably be excessive. So here's a screenshot showing the full detail:

Wim Leers’s picture

Issue summary: View changes
Wim Leers’s picture

I've had an interesting conversation with Kevin O'Leary about this.

  1. He first missed the placeholder boxes. Hence the screenshot in #23. Apparently this is called "greeking" (at least when boxes represent where text will appear).
  2. He felt it would be much better if there was also a placeholder to represent the text editor. Something like the attached image (he created that).

Point 1 is addressed in #23.

Point 2 is very interesting. I contemplated doing that. There's one big problem with that: we don't know where it will be positioned: it could be towards the bottom, or towards the top, depending on which fields the site has configured, and which fields are accessible for the current user. This would be a quite prominent preview, so it'd be quite strange to see this prominent thing shift around significantly.

We can choose to go with more-generic-but-broadly-applicable or high-fidelity-but-narrowly-applicable. I went with the former. To put it in Callum Hart's terminology: the current patch does something between "barebones" and "aspiring". Kevin would like to see something between "aspiring" and "perfectionist".

I'm +1 to striving towards that, but in the current render system (i.e. before #2702061: Unify & simplify render & theme system: component-based rendering (enables pattern library, style guides, interface previews, client-side re-rendering)), it'd be quite a chore to maintain all those preview templates.


Finally, Kevin added that for a certain set of generic elements like user pictures, wysiwyg editor, videos, images, lists, paragraphs etc. provide a lightweight scalable svg. placeholder. As long as those SVGs don't show too much detail, I think that could definitely be valuable.


Interesting stuff to take into account when we continue working on this!

Wim Leers’s picture

In March, I noticed that the (excellent!) Belgian real estate website https://www.realo.be/en also uses interface previews. Screenshot included.

Fabianx’s picture

I don't think we need to use DOM parsing.

I think we should use HTML comments to wrap the theme output of the selector in addition to having an ID, that comment could also have the ID itself, so no further parsing needed.

Then we can continue to use simple explodes() for non-JS and the data-selector for JS.

It would put some restraints on the templates, but that should be okay - given the flexibility it gives.

Wim Leers’s picture

I don't understand your comment.

Interface previews only ever make sense when using JS. When using no-JS, we can't first send a placeholder, because we can't replace it afterwards. Therefore we can't have previews in that case. And since we already generate no-JS BigPipe placeholders separately from JS BigPipe placeholders, we don't need to deal with the complexity that you are referring to in #27. :)

See my PoC patches above.

Fabianx’s picture

#28 I don't understand it either.

I am sorry, what I wrote was completely bizarre.

What I meant to write is:

Lets use placeholders that look like:

<!-- START_BIGPIPE_PLACEHOLDER BIG_PIPE_PLACEHOLDER_UNIQUE_IDENTIFIER="my-placeholder-id" -->
<span data-big-pipe-placeholder-id="my-placeholder-id">
  <img src="mypreview.png" />
</span>
<!-- END_BIG_PIPE_PLACEHOLDER-->

which means the code to get the placeholder order does not need to use DOM parsing, but can continue to use explode().

But this time not on the <div id="..."> or <span id="...">, but on the HTML comment and as those are safe for JS to replace we know we can add HTML comments around it.

And the user would never see those comments in HTML anyway, so its just helping markup.

Then the template can be whatever it wants to be - as long as it has the right data selector.

And then we don't need the DOM parsing and it might likely be more reliable, too.

Wim Leers’s picture

Hah :D

which means the code to get the placeholder order does not need to use DOM parsing, but can continue to use explode().

Ahhh! That 's an option, yes. We'll take that into account in the next iteration of this patch.


I won't be working on this for now: this issue is postponed, see #21 for the "why".

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Wim Leers’s picture

First, let's rebase this. These patches are identical to #23, but apply cleanly to 8.4.x.

Wim Leers’s picture

My main concern with #23 (and #33) is the TX/DX: it works, but it's not clear how you can make it work.

#19 and earlier patches definitely were simpler: they allow you to define a template, always, and call it a day. However, they do come with a significant disadvantage: they require you to duplicate potentially complex compositions of existing render elements. Because you're replacing an entire render array of arbitrary size with a single template.

This is why I took a different approach in #20. Let me quote a bit from that comment:

This patch shows that this can be done without breaking BC. It's a pure API addition. It's different from the prior patches in that it won't have a very tricky template name, and for the cases where a separate template is not necessary (like the comment links example), it's far, far simpler, and in fact doesn't require any work on the side of the themer: the preview will automatically match the final result!


The key example of this benefit (as that quote already indicates) is the comment links example:

+++ b/core/modules/comment/src/CommentLazyBuilders.php
@@ -151,6 +163,25 @@ public function renderLinks($comment_entity_id, $view_mode, $langcode, $is_in_pr
+  public function renderLinksPreview() {
+    return [
+      '#theme' => 'links__comment__preview',
+      '#pre_render' => ['drupal_pre_render_links'],
+      '#attributes' => ['class' => ['links', 'inline']],
+      'preview' => [
+        '#theme' => 'links__node',
+        '#links' => [
+          ['title' => '▆▆▆▆▆', 'url' =>  Url::fromRoute('<none>')],
+          ['title' => '▆▆▆▆▆', 'url' =>  Url::fromRoute('<none>')],
+        ],
+      ],
+    ];
+    return $this->renderer->renderPlain($links);
+  }

This is what the developer would need to provide. A themer can customize it by providing a links--comment--preview.html.twig template. But usually, that would not be necessary. Because in this example, the preview lies not in a complex rendering, but in showing bars/blocks in the place of the text that will appear.

The patch also provides an example of something that is too complex to benefit from this approach: the comment form.

+++ b/core/modules/comment/src/CommentLazyBuilders.php
@@ -111,6 +112,17 @@ public function renderForm($commented_entity_type_id, $commented_entity_id, $fie
   /**
+   * Interface preview for ::renderForm().
+   */
+  public function renderFormPreview() {
+    return [
+      '#type' => 'form',
+      '#theme' => 'form__comment__preview',
+      '#form_id' => 'comment_form_preview',
+    ];
+  }

+++ b/core/themes/classy/templates/form/form--comment--preview.html.twig
@@ -0,0 +1,3 @@
+<div style='height: 450px; background-color: lightgrey'>
+    <div style='position: absolute; bottom: 20px; width: 150px; height: 30px; background-color: darkgrey'></div>
+</div>

For the comment form, the interface preview callback does not even try to mimic the comment form (it has no way of remotely knowing what it would look like — because a site might e.g. have customized it with lots of additional fields).

So in this case, it makes sense to use that "interface preview template" to provide a rough approximation as the interface preview.


It's entirely possible that experience will tell us that option 1 is something we use so rarely that it is not worth it, and that we hence might as well go back to the approach in #19. That's fine. That's why this is not yet in the BigPipe module in core: because it needs experimentation.

However, in the mean time, the TX/DX should point people in the right direction: a developer (DX) needs to provide an "interface preview callback". And the themer then has the ability to provide a template to customize the default interface preview. That's what I'm doing in this iteration: generate HTML comments (much like Twig debug output) if Twig debug is enabled (duh!), to provide direction.

For the two examples above, that results in:

  1. <span data-big-pipe-placeholder-id="callback=comment.lazy_builders%3ArenderLinks&amp;args[0]=1&amp;args[1]=default&amp;args[2]=en&amp;args[3]=&amp;token=f2l6E3exSxFDxa_4V_oxZaC4lhbUjGxcEMIVDS7iiXI">
    <!-- BEGIN BIGPIPE INTERFACE PREVIEW -->
       <!-- #lazy_builder callback: comment.lazy_builders:renderLinks -->
       <!-- interface preview callback: comment.lazy_builders:renderLinksPreview -->
       <!-- interface preview callback implemented? YES! See theme debug output below: -->
    
    <!-- THEME DEBUG -->
    <!-- THEME HOOK: 'links__comment__preview' -->
    <!-- FILE NAME SUGGESTIONS:
       * links--comment--preview.html.twig
       * links--comment.html.twig
       x links.html.twig
    -->
    <!-- BEGIN OUTPUT from 'core/themes/classy/templates/navigation/links.html.twig' -->
    <ul class="links inline"><li><a href="">▆▆▆▆▆</a></li><li><a href="">▆▆▆▆▆</a></li></ul>
    <!-- END OUTPUT from 'core/themes/classy/templates/navigation/links.html.twig' -->
    
    
    <!-- END BIGPIPE INTERFACE PREVIEW -->
    </span>
    
  2. <span data-big-pipe-placeholder-id="callback=comment.lazy_builders%3ArenderForm&amp;args[0]=node&amp;args[1]=1&amp;args[2]=comment&amp;args[3]=comment&amp;token=TPDftITiSkK7fDcIvkjj1cDUjEih2r6BVIhw_dm-H4I">
    <!-- BEGIN BIGPIPE INTERFACE PREVIEW -->
       <!-- #lazy_builder callback: comment.lazy_builders:renderForm -->
       <!-- interface preview callback: comment.lazy_builders:renderFormPreview -->
       <!-- interface preview callback implemented? YES! See theme debug output below: -->
    
    <!-- THEME DEBUG -->
    <!-- THEME HOOK: 'form' -->
    <!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form.html.twig' -->
    <form method="post" accept-charset="UTF-8">
      
    
    <!-- THEME DEBUG -->
    <!-- THEME HOOK: 'form__comment__preview' -->
    <!-- FILE NAME SUGGESTIONS:
       x form--comment--preview.html.twig
       * form--comment.html.twig
       x form--comment--preview.html.twig
       * form.html.twig
    -->
    <!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form--comment--preview.html.twig' -->
    <div style='height: 450px; background-color: lightgrey'>
        <div style='position: absolute; bottom: 20px; width: 150px; height: 30px; background-color: darkgrey'></div>
    </div>
    
    <!-- END OUTPUT from 'core/themes/classy/templates/form/form--comment--preview.html.twig' -->
    
    
    </form>
    
    <!-- END OUTPUT from 'core/themes/classy/templates/form/form.html.twig' -->
    
    
    <!-- END BIGPIPE INTERFACE PREVIEW -->
    

And for everything else, which doesn't have that interface preview callback, this is what you see:

<span data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&amp;args[0]&amp;token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA">
<!-- BEGIN BIGPIPE INTERFACE PREVIEW -->
   <!-- #lazy_builder callback: Drupal\Core\Render\Element\StatusMessages::renderMessages -->
   <!-- interface preview callback: Drupal\Core\Render\Element\StatusMessages::renderMessagesPreview -->
   <!-- interface preview callback implemented? NO, contact a developer… -->
<!-- END BIGPIPE INTERFACE PREVIEW -->
</span>
Wim Leers’s picture

One of the most common things that you might want to create an interface preview for: a personalized or uncacheable block. As of this patch, blocks are supported.

This led me to discover an interesting limitation in the current approach: the "preview" callback does not receive any arguments… and hence it technically only allows a single "interface preview" for all blocks. That's of course then missing the point.

So, I had to make this slightly more flexible. It's working great :)

Now seeing output like this:

<!-- BEGIN BIGPIPE INTERFACE PREVIEW -->
   <!-- #lazy_builder callback: Drupal\block\BlockViewBuilder::lazyBuilder -->
   <!-- interface preview callback: Drupal\block\BlockViewBuilder::lazyBuilderPreview -->
   <!-- interface preview callback implemented? YES! See theme debug output below: -->

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'block' -->
<!-- FILE NAME SUGGESTIONS:
   * block--preview--bigpipedemoblock-2.html.twig
   * block--preview--big-pipe-demo-block.html.twig
   x block--preview.html.twig
   * block.html.twig
-->
…
…

:)

Wim Leers’s picture

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

webchick’s picture

Issue tags: +Usability

We reviewed this issue in the product management team meeting today.

We are confused on why this issue is postponed on #2759849: Create a new user-facing core theme as part of a Drupal demo. That issue (at least in this day and age) is specifically for the example profile, which will be experimental for at least a release or two. With Big Pipe moving into Standard profile (hopefully), the impact of interface previews is a lot more important, so postponing them on such an ambitious initiative seems sub-optimal, especially given there's been some great progress in the patches up above. We would love to see this un-postponed and active again; happy to provide reviews during UX hours if that's the predominant concern.

webchick credited Bojhan.

webchick credited yoroy.

webchick’s picture

Wim Leers’s picture

Status: Postponed » Active

#2759849: Create a new user-facing core theme as part of a Drupal demo was originally bi-focal: one of its focuses was doing "discovery work" for #2702061: Unify & simplify render & theme system: component-based rendering (enables pattern library, style guides, interface previews, client-side re-rendering). That has since changed. So I agree it no longer makes sense to postpone this issue on that.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Wim Leers’s picture

Issue summary: View changes

Relevant: https://github.com/egoist/vue-content-loader, and its sibling http://danilowoz.com/create-react-content-loader/ — the latter even has a UI to create placeholders!

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Wim Leers’s picture

Lullabot's Mike Herchel blogged about this! See https://www.lullabot.com/articles/quick-tip-add-a-loading-animation-for-....

I left a comment asking him to chime in here: https://www.lullabot.com/articles/quick-tip-add-a-loading-animation-for-... 🙏

mherchel’s picture

Hey Everyone! Thanks for working on this!

Warning: I read the issue description, but haven't gone through all of the comments.

Anyway, my thought is that Wim is right that we need to make sure that we don't insert loading or placeholder content into content that is quickly loaded. When I first inserted the loading animation in, I was really surprised to see it pop up all over the place (keep in mind I have all types of caching disabled on my local environment). We definitely don't want that.

That being said, there's room for improvement! Here are some thoughts:

1. Instead of just inserting a hardcoded span, make this themable by using a template. If we have the ability to affect the markup, themers could then insert more complex loading animations (including SVGs, weird CSS stuff, etc). Maybe we could also change the markup based on node type, regions, etc?

2. A non-💩 way to add a default loader is to have it not appear until a certain number of seconds has passed. I think 2 seconds would be reasonable. We could do this really cheaply with CSS only by animating the opacity of the loader, and then setting the animation-delay property to 2 seconds or whatever. This means that the animation will not show, unless 2 seconds goes by.

3. As far as placeholder content, I don't really think core should insert anything unless we know what it's going to look like (which I don't think we can do). To me, this seems a bit too complicated, and if we implement the ability to affect placeholder markup, the themer could easily do this.

Thoughts?

Wim Leers’s picture

  1. +1 for template in principle, but we'll have to figure out whether it's practically achievable. Actually, I tried exactly that in my patches above! 😀 Looking forward to your feedback!

    Changing markup based on node type/region/… — I'm not sure what you mean exactly here. But I think you want the placeholder to be aware of its context. That's possible, if and only if the logic that renders the contents of the placeholder is itself also given information about its context, i.e. if one of the arguments to the placeholder's callback is this context. (Hope that made sense! That's going pretty deep into the weeds. I think we can tackle this in a later phase)

  2. I like both your emoji use and pragmatism 😆 +1 to this!
  3. Agreed. Doing this automatically is absolutely impossible. But for certain UI components that we know will be placeholder in Drupal core (e.g. comment form), I think core can itself provide a "placeholder template", so that the default (core) experience is nice. When a theme overrides the default template, it's then their responsibility to also override the placeholder template to match. Thoughts?
Wim Leers’s picture

Title: Interface previews » Interface previews through optional "preview" or "placeholder" templates

Closed #2992283: Allow custom markup as placeholder as a duplicate of this. Also improving the issue title to settle on what seems to be getting consensus: we want template support for this!

Wim Leers’s picture

Crediting @mherchel and @yogeshchaugule8.

mherchel’s picture

1. Exactly. I'd love to be able to affect the markup, and turn on/off loaders based on what is loading.
2. Sounds awesome. I can put together some initial CSS.
3. I still don't think we need placeholder content even for comment forms. To me, its not worth the complexity. In the use-case of comment form, they're generally loaded outside of the initial field of view, so it's not terribly important.

Thanks!

Wim Leers’s picture

So you're basically saying that: Interface previews are nice, but not worth the complexity, just having nice spinners is good enough?

mherchel’s picture

IMO yep. That being said, I really don't feel too strongly about it.

zaporylie’s picture

reg #54 - good enough as default but customizable via templates, right? I don't think spinner will do for everyone.

yogeshchaugule8’s picture

+1 to @zaporylie say.

Actual content size will always be different for everyone, and having spinner loaded initially will cause re-arrange content after loading, which doesn't look good if content size is bigger.

Wim Leers’s picture

#57: that's my concern exactly: content that's jumping around, lots of spinners.

Still, perhaps @mherchel's proposal would be a better default than today's?

What do you think, @zaporylie and @yogeshchaugule8?

P.S.: I really appreciate all of you sharing your opinions in this issue! 👌🙏

zaporylie’s picture

My thoughts:

  1. I believe placeholders should stay empty by default. I think adding them now to all sites using BigPipe is too disruptive. We could add opt-in in settings.php or config where one can enable default interface previews.
  2. I have no objections against spinners with delay. I just think there should be an easy way to opt-in to spinners. Maybe we could just add spinners for core themes and keep custom theme a freedom of choice?
  3. I still believe that adding contextual interface previews will give us WOW factor and my personal opinion is that we should add the possibility to define them via public API.
  4. If placeholder has interface preview, the spinner is no longer required - there should be some conditional check to that
  5. I looked at #35 and as far as I can tell preview callbacks are tied to lazy_builder callbacks. I must say I'm not the biggest fan of prefix (`preview_`)/suffix (`*Preview`) approach - not easy to document, names can overlap on existing plugins and methods, etc.
  6. I'm leaning towards using one of two APIs:
    • LazyBuilderPreviewInterface with a lazyBuilderPreview member method added to all classes implementing #lazy_builder callbacks - provides good documentation but limits params you can pass to lazyBuilderPreview so the signature won't be 1-to-1 with the #lazy_builder callback
    • ChainInterfacePreviewResolver that uses service_collector to resolve interface preview for given placeholder or placeholder group and DefaultInterfacePreviewResolver with low priority that returns empty interface preview

    I like the second option more. I think it could be a nice addition to the big_pipe's placeholder API. I added a patch with a PoC.

zaporylie’s picture

On the other hand...

Well, I kinda like the idea that module developers can provide the default interface preview, but in the end, it's all about making it look good in the theme context. So maybe templates _are_ enough?

I've implemented some basic block preview for Belgrade theme (commerce demo), just to see how it's gonna look like in actual context and... I'm very excited to see it done in the, hopefully, near future.

Without preview:
screencast with no interface preview

With preview:
screencast with a demo interface preview

Wim Leers’s picture

I'm glad you're so excited by this, @zaporylie, because so am I! I will start pushing this forward again somewhere in the next few weeks. Coincidentally, I believe this can also solve #2992410: Provide placeholders for empty blocks (for example, an empty Views listing).

Wim Leers’s picture

Assigned: Unassigned » Wim Leers
Issue tags: +front-end performance

(Actually, let's start RIGHT NOW!)

@zaporylie Your approach seems very similar to the one I propose in #35, but simpler/less logic. I like that!
On the other hand, it seems like it's requiring more complex template names. Could you share the filenames of the template for the demo that you showed in #60?

My concern with #60 is that it completely couples these preview templates to BigPipe, which would prevent us from reusing those previews (those templates) for #2992410: Provide placeholders for empty blocks (for example, an empty Views listing).

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Wim Leers’s picture

Quoting #17:

Related to BigPipe because BigPipe can sometimes cause jumpiness, depending on the lazy-loaded content: https://developers.google.com/web/updates/2016/04/scroll-anchoring — Google Chrome is introducing scroll anchoring preventing jumpiness caused by reflowing.

I wrote that nearly three years ago.

Yesterday, Firefox implemented this too: https://hacks.mozilla.org/2019/03/scroll-anchoring-in-firefox-66/. This means Firefox is now also less adversely affected by not having accurate interface previews.

geerlingguy’s picture

I wanted to chime in and just offer my support for at least making the themeability easier by default. I worked through this using @mherschel's blog post for a project, and that was adequate but it was very hard to try to understand how to target just the placeholders I wanted to target, and without that blog post I would've been lost.

It might be nice to offer a spinner of some sort (do we have a core convention for that) by default, or maybe even just make the div very light grey or something? But make it easy to disable that behavior.

Otherwise, just making this more themeable / discoverable would be great.

Wim Leers’s picture

Just added a new Ensuring a smooth visual page load experience section to https://www.drupal.org/docs/8/core/modules/big-pipe/overview (diff: https://www.drupal.org/node/2677712/revisions/view/10422380/11422628). It also references this issue.

Wim Leers’s picture

Assigned: Wim Leers » Unassigned

(Actually, let's start RIGHT NOW!)

Oops … that didn't happen 😢

Wim Leers’s picture

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

ronaldtebrake’s picture

Thanks for all the great input so far, this is also really exciting me.
I'm trying to achieve Skeleton Screens, especially with different views blocks it's difficult to achieve.
Also with the amount of blocks we have on a single page throbbers are not a viable solution for me.

As per #60

So maybe templates _are_ enough?

is more than sufficient to achieve my goal.

However as noted in #62

On the other hand, it seems like it's requiring more complex template names.

This seems like the case as shown below:

<!-- THEME HOOK: 'big_pipe_interface_preview' -->
<!-- FILE NAME SUGGESTIONS:
   * big-pipe-interface-preview--Drupal-block-BlockViewBuilder--lazyBuilder--full.html.twig
   * big-pipe-interface-preview--Drupal-block-BlockViewBuilder--lazyBuilder--socialblue-views-block--activity-stream-block-stream-homepage.html.twig
   * big-pipe-interface-preview--Drupal-block-BlockViewBuilder--lazyBuilder.html.twig
   x big-pipe-interface-preview.html.twig
-->
<!-- BEGIN OUTPUT from 'core/modules/big_pipe/templates/big-pipe-interface-preview.html.twig' -->

For

$variables['arguments'] = [
'full',
'socialblue_views_block__activity_stream_block_stream_homepage',
];

For me simply removing the callback part in the theme_suggestions would already be a great improvement.

But I'm not sure where we stand with the rest of the open comments, e.g. re-use it for other preview functionality.

This is what I was able to do with / without this patch:

Proof of concept without & with templates:
without-templates
with-templates

Wim Leers’s picture

Title: Interface previews through optional "preview" or "placeholder" templates » Interface previews/skeleton screens through optional "preview" or "placeholder" templates
Issue summary: View changes
Status: Active » Needs review
FileSize
2.23 KB
5.1 KB

😭

I got logged out just as I submitted a thoughtful and long comment … and now I have to re-enter it all. DRUPAL.ORG, thanks for making me lose half an hour of work. 😬

I don't have the time to reconstruct it all, so here's a terse version of it.


#72: awesome work! Thanks for https://css-tricks.com/building-skeleton-screens-css-custom-properties/, that looks great! Updating issue title & summary.

Coincidence: at https://twitter.com/wimleers/status/1328755710512013314, there's somebody else looking for exactly this!

So … let's get this done now that there's been quite a bit of validation.


#72 validated #60, which is a continuation of my patch from 3.5 years ago at #35.

The main concern in #72 is the verbosity. We cannot omit callback because the same arguments could exist for multiple callbacks, plus it's possible that you want to target all occurrences of a particular lazy builder's placeholder, regardless of its argument.

So, I propose to special-case blocks, since they're the 90% use case anyway. Attached reroll goes from

<!-- THEME HOOK: 'big_pipe_interface_preview' -->
<!-- FILE NAME SUGGESTIONS:
   * big-pipe-interface-preview--Drupal-block-BlockViewBuilder--lazyBuilder--full.html.twig
   * big-pipe-interface-preview--Drupal-block-BlockViewBuilder--lazyBuilder--socialblue-views-block--activity-stream-block-stream-homepage.html.twig
   * big-pipe-interface-preview--Drupal-block-BlockViewBuilder--lazyBuilder.html.twig
   x big-pipe-interface-preview.html.twig
-->
<!-- BEGIN OUTPUT from 'core/modules/big_pipe/templates/big-pipe-interface-preview.html.twig' -->

to

<!-- THEME HOOK: 'big_pipe_interface_preview' -->
<!-- FILE NAME SUGGESTIONS:
   * big-pipe-interface-preview--block--full.html.twig
   * big-pipe-interface-preview--block--socialblue-views-block--activity-stream-block-stream-homepage.html.twig
   * big-pipe-interface-preview--block.html.twig
   x big-pipe-interface-preview.html.twig
-->
<!-- BEGIN OUTPUT from 'core/modules/big_pipe/templates/big-pipe-interface-preview.html.twig' -->
Phil Wolstenholme’s picture

Wim, your excitement about this is super contagious, and thanks to ronaldtebrake for reviving this issue too!

Google announced this month that next year their Core Web Vitals web performance metrics are going to become a ranking factor, and one of those metrics is Cumulative Layout Shift – or how visually stable a page's layout is while the page loads.

It looks like the ability to provide custom placeholder markup will be a really useful tool for preventing CLS issues, giving Drupal sites a UX benefit (layout instability can be annoying and cause clicks on the wrong elements when a layout shifts during load), a perceived performance benefit, and eventually a SEO benefit too!

Wim Leers’s picture

Priority: Normal » Major

#74: Great minds think alike 🤓 My link in #68 to https://web.dev/layout-instability-api now redirects to https://web.dev/cls/ 😄

So very much +1, and bumping to Major priority because of this!

ronaldtebrake’s picture

I can feel the effects of the excitement too! Thanks so much for getting this a step further and the additional clarifications on the priority and impact of this.

As per #73

The main concern in #72 is the verbosity. We cannot omit callback because the same arguments could exist for multiple callbacks, plus it's possible that you want to target all occurrences of a particular lazy builder's placeholder, regardless of its argument.
So, I propose to special-case blocks, since they're the 90% use case anyway. Attached reroll goes from

Thanks for the clarification that definitely makes sense now and to special-case block would be definitely something I can live with.

I have updated the patch a tiny bit, cleaned up some unused CSS and changed

-    'Drupal-block-BlockViewBuilder--lazyBuilder' => 'block',
+    'Drupal_block_BlockViewBuilder__lazyBuilder' => 'block',

Due to the $callback = preg_replace('/[^a-zA-Z0-9]/', '_', $variables['callback']); happening afterwards.

With that I can confirm it works now.

Example of my theme debug.

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'big_pipe_interface_preview' -->
<!-- FILE NAME SUGGESTIONS:
   * big-pipe-interface-preview--block--full.html.twig
   * big-pipe-interface-preview--block--search-content-block-header.html.twig
   * big-pipe-interface-preview--block.html.twig
   x big-pipe-interface-preview.html.twig
-->
<!-- BEGIN OUTPUT from 'core/modules/big_pipe/templates/big-pipe-interface-preview.html.twig' -->


<!-- END OUTPUT from 'core/modules/big_pipe/templates/big-pipe-interface-preview.html.twig' -->
ronaldtebrake’s picture

You know that feeling you press submit, all excited and.... you forgot the files.. 😬

Wim Leers’s picture

Hey, at least you tested your patch 😁

John Pitcairn’s picture

I just want to say this is really cool. Thanks to all who have contributed.

saschaeggi’s picture

This is awesome! Love to see this!

acrollet’s picture

Status: Needs review » Reviewed & tested by the community

The code meets requirements, is clear to read, and does not introduce any coding standards errors. Tested working, makes a really nice DX improvement - kudos to all involved :-)

Setting RTBC.

catch’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

This needs some test coverage

  1. +++ b/core/modules/big_pipe/big_pipe.libraries.yml
    @@ -1,5 +1,8 @@
       version: VERSION
    +  css:
    +    theme:
    +      css/big_pipe.css: {}
       js:
         js/big_pipe.js: {}
    

    big_pipe.css file is missing from the patch (or this hunk is out of date?).

  2. +++ b/core/modules/big_pipe/big_pipe.module
    @@ -76,3 +76,56 @@ function big_pipe_page_attachments(array &$page) {
    +/**
    + * Implements hook_theme_suggestions_HOOK().
    + */
    +function big_pipe_theme_suggestions_big_pipe_interface_preview(array $variables) {
    +  $common_callbacks_simplified_suggestions = [
    +    'Drupal-block-BlockViewBuilder--lazyBuilder' => 'block',
    +  ];
    +
    

    We could use some test coverage for the logic here.

I'm also wondering whether it would be possible to implement this in core somewhere - Umami seems like a possible (probably only) place it could work?

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

RustedBucket’s picture

Is there any status on this? Any doc on how to actually make it load a preview? I tried the patch and spent several hours tinkering but it doesn't seem to do much of anything.

ronaldtebrake’s picture

I finally had some time to get back to this and see if we can get it a bit further.


As per #82

1.

+++ b/core/modules/big_pipe/big_pipe.libraries.yml
@@ -1,5 +1,8 @@
   version: VERSION
+  css:
+    theme:
+      css/big_pipe.css: {}
   js:
     js/big_pipe.js: {}
big_pipe.css file is missing from the patch (or this hunk is out of date?).

That got introduced in #60 and I assumed it was there for demo purposes to showcase what we could achieve. Not as an actual default CSS implementation.
Please correct me if I'm wrong of course.

2.

+++ b/core/modules/big_pipe/big_pipe.module
@@ -76,3 +76,56 @@ function big_pipe_page_attachments(array &$page) {
+/**
+ * Implements hook_theme_suggestions_HOOK().
+ */
+function big_pipe_theme_suggestions_big_pipe_interface_preview(array $variables) {
+  $common_callbacks_simplified_suggestions = [
+    'Drupal-block-BlockViewBuilder--lazyBuilder' => 'block',
+  ];
+
We could use some test coverage for the logic here.

I've tried to come up with a test covering the case we added for the simplified suggestion in the update patch.
Hope it covers it.

I'm also wondering whether it would be possible to implement this in core somewhere - Umami seems like a possible (probably only) place it could work?

That sounds amazing! I couldn't really find a good place to start though curious if there are any insights in to how we can use this in Umami.


#87

I'll see if I can get some documentation started the coming days.
Some quick tips that might put you back on track.

  1. Enable twig debugging
  2. You're looking for <!-- THEME HOOK: 'big_pipe_interface_preview' --> in your HTML which should show you what file name suggestions are available
  3. Bear in mind, this is only there as a placeholder, so the time it takes for the data to be rendered and replaced on screen, there are some ways to help you out there though. For example you could use a breakpoint to stop the page from continuing to render, stop the browser from loading once the placeholders are rendered, or maybe even add a sleep to the #lazy_builder callback function giving you some additional time to check it out.
  4. If you've found the right suggestion to use this documentation on how to work with twig templates should help tying it all together. By copying big-pipe-interface-preview.html.twig and using it correctly you have all the freedom to make some nice interface previews.

Hope it helps!

bnjmnm made their first commit to this issue’s fork.

bnjmnm’s picture

Issue tags: +Field UX
pooja saraah’s picture

Fixed failed commands on #88
Attached patch against Drupal 10.1.x
Attached interdiff

bnjmnm’s picture

Status: Needs work » Needs review
ronaldtebrake’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
213.04 KB

Awesome work, love the additional test coverage as well.

Can confirm it works,
1. i've added the recent content block to the sidebar
2. created: core/themes/olivero/templates/block/big-pipe-interface-preview--block--views-block--content-recent-block-1.html.twig with some barebones placeholders for the recent content block
3. added a sleep to make sure we can see the preview

et voila;
skeletonscreen review

lauriii’s picture

Issue tags: +Needs change record

Haven't looked at the MR in detail yet but we need a change record for this since it's a new API.

bnjmnm’s picture

Issue tags: -Needs change record

Added change record

  • lauriii committed aeac2967 on 10.1.x
    Issue #2632750 by Wim Leers, bnjmnm, krlucas, ronaldtebrake, zaporylie,...
lauriii’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs tests +10.1.0 release highlights

Reviewed the code & tests in detail. I think we could potentially still add some more test coverage for the simplified suggestions, but I didn't think that was a hard requirement for this to be committed.

Committed aeac296 and pushed to 10.1.x. Thanks!

Tagging for 10.1.0 release highlights since this is a pretty big developer facing feature.

Wim Leers’s picture

Superb! 🤩 Thank you for making happen what I hoped to do many years ago and never got around to finishing! 🙏

The first use of this new infrastructure just landed in #2951268: Improve rendering account link in the toolbar! 🥳

Also, thanks to this issue, I was able to close #3162134: Lazy builder placeholders should show a loading indicator 👍

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.