Component-based theming with Layout Builder

I have previously written about using Drupal’s definition files in component-based theming and how it is possible to have component-specific layout and asset library definition files. Now that Layout Builder is stable it is time to have a look at how it can be used with theme components.

Two schools

There are two main approaches to integrating independent theme components with Drupal. They could be described as the ‘Twig developer’ approach and the ‘site builder’ approach.

In the Twig developer approach integration is done entirely in Twig ‘presenter’ templates. A significant benefit of this straightforward approach is that no contrib modules are required (although Component Libraries is usually used). There is also no need for endless pointing and clicking in the admin UI, and dealing with related configuration. The downside is that in most cases this approach leaves the admin UI disconnected from the components. This means that a site builder not familiar with Twig or with no access to the Twig templates has no way of affecting the appearance of the integrated components.

In the site builder approach integration is done using the admin UI. Until now this has required sophisticated contrib modules like Display Suite and UI Patterns, with their own ecosystems of related modules. These are great modules, but ideally it should be possible to use just Drupal core for the site builder approach. With Layout Builder in core we are a huge leap closer to that goal.

Revisiting an old example

Back in January 2017 I wrote a blog post on how to use UI Patterns to integrate a simple Code component. I will now use the same component in an example of how to use Layout Builder for the same task.

Step 1: Create layout and asset library definitions

Starting from where we ended up in that old blog post, we need to provide information about the component’s variables and assets to Drupal in some other way than a .ui_patterns.yml file. This can now be easily done using Drupal core’s definition files.

Drupal core only supports theme (or module) specific definition files, but the Multiple Definition Files module can be used to add support for component-specific files. The results are identical in both approaches, so using Multiple Definition Files is completely optional.

Multiple Definition Files does add one useful feature though. Drupal places layout regions in content, so for example a code region would be accessed in Twig as content.code. To remove this Drupalism, Multiple Definition Files makes layout regions accessible in the Twig root context, so a code region is accessible in Twig as just code.

The definitions in this example are in component-specific files. If you want to use Multiple Definition Files, be sure to enable the module at this point.

The layout definition, shila-code.layouts.yml:

shila_code:
label: 'Code'
category: 'Shila'
template: source/_patterns/01-molecules/content/shila-code/shila-code
library: shila_theme/shila_code
regions:
language:
label: 'Language'
code:
label: 'Code'

and the library definition, shila-code.libraries.yml:

shila_code:
css:
theme:
source/_patterns/01-molecules/content/shila-code/prism.css: {}
js:
source/_patterns/01-molecules/content/shila-code/prism.js: {}

Note the library reference in shila-code.layouts.yml, linking the two definitions. Be sure to clear caches after adding the new definitions.

(As a side note, the UI Patterns From Layouts module makes it possible to use Drupal’s definition files with UI Patterns as well.)

Step 2: Enable Layout Builder

After enabling the Layout Builder module, Layout Builder has to be enabled for our Code paragraphs type’s display.

If you are moving away from a Display Suite layout, be sure to select - None - for the layout and save the settings before enabling Layout Builder. It seems that if you do not do this, Display Suite is still active and Layout Builder won’t work as expected.

Manage display

Step 3: Integrate the component using Layout builder

Clicking on the ‘Manage layout’ button takes us to Layout Builder. Display Suite and UI Patterns show a textual representation of a layout, but Layout Builder is different as it displays the layout visually.

Layout Builder

First we remove the default section, then we add a new section and choose the ‘Code’ layout for it.

Choose layout

As a reminder, this is what our extremely simple shila-code.html.twig template looks like:

<pre><code{% if language %} class="language-{{ language }}"{% endif %}>{{ code }}</code></pre>

Layout Builder’s visual representation will not be a problem in many cases. However, components often use variables for non-visual purposes or have layouts with overlapping regions. Our Code component is a good example, since language is used as a part of a CSS class name. Layout Builder does not expect layouts to be used in this way, and the result is a completely unusable UI.

Unusable UI

Oh no. What we need is a text based way to configure the layout. The good news is that due to accessibility reasons a textual version of the Layout Builder UI is already in the works. So, let’s apply the patch from that issue, clear the caches, and see what happens.

Layout overview link

A ‘Layout overview’ link has appeared! Let’s click on it.

Layout overview

This is looking good! We can now add the right paragraph fields to the respective regions in the Code layout and then click on the ‘Save layout’ button. Let’s have a look at a page that contains a Code paragraph.

Broken component

Something is obviously going wrong here. Let’s have a look at the HTML source.

HTML source code showing markup from Drupal’s block and field templates.
HTML source code showing markup from Drupal’s block and field templates.

Since we have placed fields in Layout Builder blocks, there is unwanted HTML from the block and field templates. What we really need is just the contents of the fields, nothing else. This can be an issue with many independent theme components, since they often do not expect extra markup to be provided.

Display Suite has a ‘Full Reset’ field formatter and UI Patterns has an ‘Only content’ option. But what can we do here? Creating specific Twig templates to remove the HTML is an option, but not an ideal one. What we want is an easy UI based way to deal with the problem.

Step 4: Install and enable the Full Reset module (if required)

After searching for existing solutions and not coming up with anything, I ended up writing a small module for this particular purpose. Full Reset does two things: it provides a field formatter and adds a reset option to Layout Builder blocks. The name is a hat tip to the trusty Display Suite field formatter I have used so many times.

A good way to support third party settings for Layout Builder blocks is still being worked on, so a core patch must be applied for Full Reset to work.

With the core patch applied and Full Reset installed and enabled, we can select the ‘Full Reset’ field formatter and tick the ‘Full Reset this block’ checkbox.

Full Reset options

Now the block and field templates are not used at all, and the component works and looks like expected! It still does not work in Layout Builder’s visual preview though, because Layout Builder expects the content to be a valid DOM node and have a surrounding HTML tag. For this reason Full Reset does not remove block theming in the preview.

Conclusion

Layout Builder can be successfully used in component-based theming today. There might be some problems with specific components like the one in this example, but these problems can be circumvented by applying two patches and using the Full Reset module.

For me this means that I can now stop using Display Suite, a module that I have used in almost all of my Drupal projects since 2011. Personally I find this change to be just as significant as it was when Field API and Views were added to core.

I have previously written about using Drupal’s definition files in component-based theming and how it is possible to have component-specific layout and asset library definition files. Now that Layout Builder is stable it is time to have a look at how it can be used with theme components.

A new approach for a new Pattern Lab

The PHP version of Pattern Lab has been a trusty tool for a long time, especially for many of us working with Twig and component-based theming for Drupal. However, ever since a decision was made to focus development efforts on Pattern Lab Node, it has been clear that it would eventually become necessary to switch from using the PHP version to using the Node version.

Twig developers do not need to worry about compatibility, since thanks to the efforts of Evan Lovely and Salem Ghoweri, Pattern Lab Node now uses a PHP Twig renderer to render Twig templates. This means that templates are rendered using the official PHP implementation of Twig, and it is even possible to add PHP extensions to the Twig environment used by the renderer.

Pattern Lab Node 3.0 is the future of Pattern Lab, with many improvements over the PHP version, especially in the UI. However, it is still in beta and a bit rough around the edges. There have been issues with pseudo-patterns, and more work is needed to support plugins. With well-established development approaches based on the use of data files and plugins in Pattern Lab PHP, how can we make the switch to using the Node version?

A new approach

Limitations can often drive creativity. I do not know if that is the case here, but a great new development approach is being used by folks already using Pattern Lab Node. This approach was described by Evan Lovely in his excellent presentation ‘Pattern Lab: The Definitive How-to’, and is used by Aaron Froehlich and Jeff Amaral in Union, an inspiring project well worth checking out.

The basic idea in this new approach is to use a new type of template in Pattern Lab. These new templates provide demo data for the actual component templates, making traditional Pattern Lab JSON/YAML data files mostly unnecessary.

As an example, if we have a _heading.twig template (note the leading underscore, which hides the pattern in Pattern Lab)

<h1>{{ title }}</h1>

instead of creating a heading.yml data file

title: ‘Hello’

we create a heading-demo.twig template

{% include ‘_heading.twig’ with {‘title’: ‘Hello’} only %}

These demo templates are very similar to ‘presenter’ templates used in component-based Drupal theming, as they only process and pass data to the actual component templates, and do not contain any markup.

Pros and possible cons

Even though plugins like Data Transform Plugin can make plain data files more powerful, using Twig to provide demo data opens up a whole new world of possibilities. For example, demo templates can use Twig extensions that might not be acceptable in plain Twig components. I am certain that there will be a lot of innovation within this approach and related best practices in the future.

One possible drawback is that the Pattern Lab UI will display the Twig source of the demo template instead of the source of the actual component. However, it is only a possible drawback, as in many cases it might actually be useful to show how the component should be included from another template. And it is still possible to use a data file if it is important to show the source of the component itself.

A new version of Shila theme

I have been wanting to switch to using Pattern Lab Node for some time now, and this new approach has made it possible. I have refactored Shila theme, which I use as a starting point for all my Drupal theme projects, to use demo templates. This change makes it possible to use Shila theme with both Pattern Lab PHP and Pattern Lab Node. If you are interested in seeing an example of a full implementation of this new approach, be sure to check out the new version of Shila theme.

The PHP version of Pattern Lab has been a trusty tool for a long time, especially for many of us working with Twig and component-based theming for Drupal. However, ever since a decision was made to focus development efforts on Pattern Lab Node, it has been clear that it would eventually become necessary to switch from using the PHP version to using the Node version.

Using Drupal’s definition files in component-based theming

All the great work already done and to be released by the Layout Initiative has inspired me to think about how core’s definition files can be used in component-based theme development. As a result I am now happy to announce two Drupal modules and a Pattern Lab plugin which enable new ways of using core’s definition files.

Layout definitions have superpowers

Layout definition regions can be used for both blocks and fields, to create both page-level layouts and more intricate layouts for smaller pieces of content and components.

Data mapped to layout regions can also be used in component template files to configure the component in some way, instead of just displaying the data as it is.

The terms ‘layout’ and ‘region’ can be a bit misleading in that last use case. However, I am not aware of any reason why layouts should not be used in this way. Layout definitions have been successfully used as de facto component definitions in component-based theming for quite a while now. There are no ugly hacks involved, and soon Drupal core will even have UI support for it.

Layout definitions can also reference an asset library, which can be used to define all the assets of a component.

Introducing the Multiple Definition Files module

So, what could be done to improve component-based theming with these superpowers we already have in core?

One of the general principles of component-based theming is that all files related to a particular component should be located in a component-specific folder. However, Drupal core currently only supports extension (theme) specific definition files for asset libraries and layouts. Wouldn’t it be nice to have component-specific definition files?

I decided to try an approach that uses existing definition file types, with no specific requirements as to where they should be located. The Multiple Definition Files module recursively scans the default theme’s directories for .libraries.yml and .layouts.yml files and then merges all found definitions to the theme’s main definition files. I haven’t found any problems with this approach so far, and I think it would be great to have this type of functionality in core some day.

Introducing the UI Patterns From Layouts module

What about the great features provided by UI Patterns? To use UI Patterns we still need to create .ui_patterns.yml definitions, or Pattern Lab and Fractal users can install an additional module that exposes their respective component definition files as patterns.

UI Patterns includes the UI Patterns Layouts module that exposes patterns as layouts. But what if it was done the other way round? Could layouts be exposed as patterns?

Thanks to another core layout definition superpower, support for arbitrary properties, we can add the preview values expected by UI Patterns to the layout definition file. And thus was born the UI Patterns From Layouts module!

Introducing the Drupal Definition Files plugin for Pattern Lab

Being a Pattern Lab user and contributor, I naturally turned my attention to Pattern Lab next. If Drupal core definition files could already be used for everything in Drupal, why not add support for them in Pattern Lab, removing the need to create Pattern Lab specific files?

So, I wrote a Pattern Lab plugin that adds support for .layouts.yml files and the arbitrary preview data section. The Drupal Definition Files plugin also supports defining the data for the base pattern and all of its pseudo-patterns in just one file. This is a nice feature for projects that have many pseudo-patterns.

Data Transform Plugin users need not worry, because all of its data transform features can be used in .layouts.yml files too!

Currently the plugin supports just layout definitions, but the plan is to add support for asset library definitions. Pull Requests are welcome!

Pick and mix

The modules and plugin introduced here can be used on their own or in any combination. The Pattern Lab plugin can be useful on its own just for the pseudo-pattern feature, even for non-Drupal projects.

The modules and plugin can probably also be used for other things not described in this blog post. If so, I would be interested to learn about such use cases.

All the great work already done and to be released by the Layout Initiative has inspired me to think about how core’s definition files can be used in component-based theme development. As a result I am now happy to announce two Drupal modules and a Pattern Lab plugin which enable new ways of using core’s definition files.

Drupal’s Layout Initiative and component-based theming

A quick overview of some things happening with Drupal’s Layout Initiative from the perspective of component-based theming, a theme development approach that has been gaining popularity in the past few years.

Layouts in core

The Layout API and the Layout Discovery module were added in Drupal 8.3 as an experimental subsystem, and they were stabilized in Drupal 8.4.

Layouts have been an important tool in component-based theming as they can be used to map data to component templates. Layouts can be used with well-established contrib modules like Display Suite and Panels, and the UI Patterns module can expose its patterns as layouts.

Field Layout

An experimental Field Layout module was also added in Drupal 8.3. Field Layout provides a simple UI for arranging rows of entity fields into regions of a single layout, in a very similar way to Display Suite. Field Layout was planned to be stabilized in Drupal 8.5, but it continues to be an experimental module.

Layout Builder

An experimental Layout Builder module was added in Drupal 8.5. Layout Builder provides a UI with a visual preview and it supports using multiple layouts together, placing blocks in layout regions and creating layouts for individual pieces of content. It is powerful and unique and a huge step forward in capabilities offered by core. Layout Builder is currently planned to be stabilized in Drupal 8.7.

Field Layout might be removed from core

Layout Builder has essentially deprecated much of what Field Layout provides, and uses a completely different technical approach. Layout Builder does not currently support form displays, however. As Field Layout is still experimental, it has been proposed that Field Layout should be removed from core after moving its form display capabilities to core’s Field UI.

An alternative non-visual UI has been proposed for Layout Builder

Drupal’s values and principles include building software that everyone can use. Core changes must pass through a series of ‘gates’ to ensure their quality is up to standards, and one of them is accessibility.

Modern UIs can be challenging to build in an accessible way, as the WordPress community has sadly discovered recently. Layout Builder is no exception, and it might prove difficult to pass Drupal’s accessibility gate in time to stabilize Layout Builder in Drupal 8.7. Because of this it has been proposed that Layout Builder provide an alternative accessible UI without a visual preview, not unlike Field Layout or the block admin UI.

Component-based theming use cases

Both aforementioned types of UIs are useful from a component-based theming perspective. However, a simple non-visual UI can be a better option in many cases. Layout definitions for components might include regions for adding things that are not displayed, for example.

Such a case can be found in my old blog post about using UI Patterns. The Code component described in that blog post defines a layout region for adding the code language. Instead of displaying the value, the component uses it as a part of a CSS class name.

Another example might be a component that defines a layout region for an image and a region for text, which the component then displays over the image. Such visually overlapping regions would be unnecessarily hard to implement perfectly in a UI with a visual preview, when a simple non-visual UI could just as well be used.

Now is a good time to get involved in the discussion

Personally I think it would be really great to have an alternative simple UI without a visual preview for layouts in core. If you would like to express your opinion on this, or can think of further use cases for such a UI, now is a good time to get involved in the related issues on Drupal.org:

On experimental modules

This case is a good reminder that experimental core modules should only be used for experimentation, not in production. An experimental module might be removed instead of being stabilized.

Thank you

Finally, I want to thank everyone involved in the Layout and Media Initiatives! Your work is very impressive and keeps making Drupal core better and more capable for component-based theming.

A quick overview of some things happening with Drupal’s Layout Initiative from the perspective of component-based theming, a theme development approach that has been gaining popularity in the past few years.

How popular is decoupled Drupal?

Decoupled Drupal has been an increasingly visible topic at Drupal events and on the web for several years now. But what is the percentage of decoupled Drupal sites out of all Drupal sites?

Unfortunately there is no way to get hard numbers at the moment. It also looks as if there have been no user surveys about decoupled Drupal usage so far.

One way to estimate the number of decoupled sites is to look at the usage statistics of modules commonly used on decoupled sites. So I thought I would do that.

(All figures are from 15 April 2018.)

Number of Drupal sites:

  • Drupal 8: 226,908 sites
  • Drupal 7: 895,343 sites
  • Drupal 8 and 7 total: 1,122,251 sites.

To get a better overall picture let’s first look at the the most popular modules:

The difference between the most popular module on Drupal 8 and Drupal 7 is huge! This is probably because Drupal 8 core provides much more functionality out of the box.

Now let’s look at the modules used for decoupled Drupal. For Drupal 8 I have selected the REST UI module and for Drupal 7 the Services module:

  • Drupal 8: REST UI, installed on 8,404 sites (3.7 % of all Drupal 8 sites)
  • Drupal 7: Services, installed on 43,081 sites (4.8 % of all Drupal 7 sites)
  • Drupal 8 and 7: REST UI + Services, installed on 51,485 sites (4.6 % of all Drupal 8 and 7 sites).

Finally let’s look at graphs of usage over time, starting with Services:

Usage statistics Services module

We can see that usage grew steadily until early 2016, when it stabilised at the current level. Probably something to do with Drupal 8 being released at that time.

And then the graph for REST UI:

Usage statistics REST UI module

We can see a steady and steep rise in usage right from the time Drupal 8 was released.

These figures and graphs seem to confirm that decoupled Drupal is rapidly gaining popularity, although Drupal 8 usage still has not reached Drupal 7 level (see update below). It will be interesting to see for how long this rate of increase in usage will continue.

Update 26 April 2018: It has been suggested that the JSON API module should be included in the figures for Drupal 8, and this is indeed a good suggestion. JSON API is used in decoupled Drupal distributions like Contenta and Reservoir, and there should be very little overlap in REST UI and JSON API usage.

  • Drupal 8: JSON API, installed on 6,341 sites (2.8 % of all Drupal 8 sites)
  • Drupal 8: REST UI + JSON API, installed on 14,745 sites (6.5 % of all Drupal 8 sites)
  • Drupal 8 and 7: REST UI + JSON API + Services, installed on 57,826 sites (5.2 % of all Drupal 8 and 7 sites).

Usage graph for JSON API:

Usage statistics JSON API module

This looks very similar to REST UI, with a steady and steep rise in usage.

Decoupled Drupal has been an increasingly visible topic at Drupal events and on the web for several years now. But what is the percentage of decoupled Drupal sites out of all Drupal sites?

Improving Drupal’s minor version upgrade experience

Twice a year the new Drupal upgrade model makes me both excited about new features and worried about the possibility that the sites I maintain will break. I think there are some ways how the upgrade experience could be made better.

Things that could be improved

I have already written a couple of blog posts (1, 2) about the new upgrade model, detailing things that have caused and could continue to cause problems.

The main points made in those posts are:

  • Security support is only provided for the latest minor version, and there are two minor version releases each year.
  • It is a big challenge for contrib to keep up with changes, new features and new experimental modules in core.

As a consequence:

  • A minor version upgrade can cause sites using contrib projects to break.
  • Drupal 8 sites need more resources to maintain than previous major versions of Drupal.
  • It is not clear if it is always possible to maintain a working site that is covered by security support.
  • These issues make Drupal 8 less attractive for smaller site owners currently on a previous major version of Drupal.

Improvement idea 1: Extend security support to cover the previous minor version

Extending security support to cover the previous minor version would give contrib more time to fix possible issues. It would also make maintaining sites less resource intensive, increasing interest in adopting Drupal 8.

This would of course mean more work for core committers and the security team, so I don’t know whether the idea is realistic or not. But Dries ‘liked’ the idea when I mentioned it on Twitter, so that makes me hopeful!

I have opened an issue suggesting this on Drupal.org and would love to see discussion there.

Improvement idea 2: Provide a new way to find out how contrib projects are affected by a new core version

Currently there are two ways to find out if a new core version breaks your site. The best and only completely sure way is to test the new core version on the site. Another way is to browse through the issue queues of all contrib projects used on the site, looking for issues related to the new core version.

It would be nice to be able to get a list of all contrib projects that have been found to either work or break on a new core version. I believe this functionality could also be useful in the Automatic Updates initiative, to determine whether an update can be made or not.

A lightweight implementation of this feature would be to tag issues in a commonly agreed way. If for example a contrib module was found to be broken by changes made in Drupal 8.6.0, an issue could be opened and tagged ‘Breaks in 8.6.0’. That way all projects broken by changes in 8.6.0 could be easily found using the ‘Search issues for all projects’ page.

Being able to easily find out which contrib projects have been reported to break in the next minor release would possibly help getting issues fixed quicker. This data could also be used to gain insight on the ways contrib uses core that result in breakage. It would also provide interesting statistics on how common breakages are.

Twice a year the new Drupal upgrade model makes me both excited about new features and worried about the possibility that the sites I maintain will break. I think there are some ways how the upgrade experience could be made better.