Component libraries have become one of the first things organizations require for new engagements. There are many reasons for organizations to want a component library, but the reality is that Drupal, and PHP in general, have not been in a good place to deliver great solutions in this area. This is why we have created the Component Libraries suite of modules. This article will walk through what we mean when we say component and why we think these modules offer an excellent, flexible solution.
Before we talk about component libraries, let's clarify what we mean by Components.
In our opinion, a Drupal component is a combination of:
- A Twig template.
- Metadata describing the input data the template accepts.
- Optional Styles.
In this context, a component is not a type of block plugin (like Component and Decoupled Blocks modules). Those are progressive decoupling approaches. It's a different problem space, and in that space, we leverage the JS Widgets modules.
The Components module (the plural is an entirely different module from the singular) is a very popular and useful module, but it does not help us declare or render components. Its function is to simplify Twig namespaces and provide some additional Twig functions and filters for use in Drupal templates. Also, a different problem space. In fact, you can leverage this module with our solution.
We developed the Component Libraries: Components (aka CL Components) as a way to way to declare and manage components in Drupal. Our understanding of components aligns with the Single File Components module and the UI Patterns module. We only differ in how components are declared and used. CL Components takes the simplest and most familiar approach, where the developer writes the Twig, JS, and SCSS in separate files and then embeds the components in the Drupal templates (like
node--article--card.twig.html). Check the documentation if you want to learn more about how to declare components. Since CL Components is still in early development, we are researching ways to make these three compatible.
Moving away from Twig.js
Twig.js is currently a work in progress and supports a limited subset of the Twig templating language (with more coming).
The problem with sending our Twig templates to Twig.js so they can be rendered in our component library is that they don't match Drupal. When Twig.js renders a template, it turns a
my-template-file.twig file with some example data into
output.html. On the surface, this seems enough. However, this workflow does not take into account:
- The styles of your Drupal theme.
- Any additional styles and JS added by custom & contrib modules.
- Preprocess functions that alter the HTML or massage the data.
In summary, this workflow does not take Drupal into account. How can we confidently tell our clients that what they see in Storybook is what they will see in Drupal? The uncomfortable truth is that we cannot. How can this work if this workflow doesn't know what Drupal theme should be used? We can try to make the emulation of Drupal as realistic as possible, but as soon as you change a line of CSS, install a new contrib, or add a preprocess, the emulation is outdated.
On top of that, the emulation of PHP will inevitably have rough edges. A consistent transformation of
As you can see, there are many problems and wasted effort in emulating Drupal for your component library. Our solution is to stop emulating Drupal and start using Drupal to render your components using the CL Server module.
Make Drupal render the components
Storybook started working on server-rendered components back in 2020. Even if they are not yet, present on the documentation site, the Storybook team has pledged compatibility for the server framework. This means that we can use Storybook as our component library and instruct it to make HTTP requests to Drupal to render the components. If you are interested, you can look at the step-by-step tutorial to configure Storybook + Drupal.
The CL Server module will allow you to render a component in isolation. To do so, the module uses your theme to render a full page with your component in a way that is usable for Storybook. Then the
@lullabot/storybook-drupal-addon removes all the unnecessary bits (like menus, sidebar blocks, etcetera). The result is an HTML document that contains only the component as rendered by Drupal. Storybook will use that HTML to display the component. The Storybook Drupal addon will let you select what Drupal theme you want to use because the same component renders differently depending on the theme.
Using this setup, you can ensure that
my-template-file.twig will render the same as in your Drupal pages. As soon as you change a line of CSS, install a new contrib, or add a preprocess, the component library is properly updated. No effort required.
The result is a component library that showcases components that stay true to your Drupal themes and enables modern development techniques for Drupal developers. Techniques that, in the past, were reserved for JS devs.