SDC in Drupal core

Finally, Drupal 10.1 standardizes the way to build components. Let's see how to use them and how to integrate them with WebProfiler.

# drupal # components # SDC # theme # webprofiler
Drupal logo

Introduction

There are a lot of contributed modules to build and manage a Drupal theme using components, but none of them has ever been elected as the de facto standard.

However, things have changed with the release of Drupal 10.1 in June 2023. A specific implementation was chosen for inclusion in the Drupal core. Initially developed as a contributed module named Component Libraries: Components, this functionality has been merged into Drupal core as the new SDC experimental module.

What is SDC?

SDC stands for Single Directory Components. It is a way to organize components in a single directory instead of splitting them across different folders. This approach is similar to the one used by React and Vue.js.

The main advantage of this solution is that it is easier to find the code that describes a component. It also simplifies the process of creating a new component, as you just need to create a new folder and add a some files to it.

Finally, it is easier to share components between different projects, as you can just copy the component folder from one project to another (SDC then allows you to override assets like CSS and JavaScript to adapt the component to the design system of the new project).

How to use SDC?

The simplest example we can think of is a button component, but let’s try to complicate things a bit by adding some JavaScript and an image.

The first step is to enable the SDC experimental module. Then you need to create a new folder named components in the theme folder or in one of your custom modules (yes, you can have more than one components folder). Those folders contain all the components that will be available in your theme.

The second step is to define a new component. Create a new folder named button in the components folder. This folder will contain all the files related to the button component.

Next, you’ll find the code for those files:

  • button.component.yml: metadata of the component (name, description, props, etc.)
  • button.twig: Twig code of the component
  • button.css: CSS code of the component
  • button.js: JavaScript code of the component
  • icons/cog.svg: cog icon
  • README.md: component’s documentation

Note how all the files related to the component are named after the component itself, this is mandatory to allow Drupal to automatically declare a library for the component.

Let’s start with button.component.yml:

'$schema': 'https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json'
name: button
status: stable
description: A simple button
libraryOverrides:
  dependencies:
    - core/once
props:
  type: object
  properties:
    title:
      type: string
      title: title
      description: Button title
      examples:
        - 'Click me'
    type:
      type: string
      title: Type
      description: Button type
      examples:
        - 'primary'
    icon:
      type: string
      title: Icon
      description: Button icon
      examples:
        - 'cog.svg'
    message:
      type: string
      title: Message
      description: Popup message
      examples:
        - 'Lorem ipsum'
  required:
    - title
    - type
    - icon
    - message

The Twig file may look like this:

 <div {{ attributes.addClass('button') }} data-message="{{ message|default('No message') }}">
   <button class="{{ type }} image-button">
     <img src="/{{ componentMetadata.path }}/icons/{{ icon }}" alt="Image">
     <span>{{ title }}</span>
   </button>
</div>

All the properties defined in the button.component.yml file are available in the Twig file as variables. The componentMetadata variable contains some helpful information, like the path of the component on the filesystem.

We then need some CSS to style the button:

.image-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 20px;
  color: #fff;
  cursor: pointer;
  background-color: #124354;
  border: none;
  border-radius: 5px;
}
.image-button img {
  height: 20px;
  margin-right: 10px;
}

To add interactivity to the button we need some JavaScript:

((Drupal, once) => {
  Drupal.behaviors.at_button = {
    attach(context) {
      once('button', '.button', context).forEach((item) => {
        item.addEventListener('click', (event) => {
          event.preventDefault();
          alert(item.dataset.message);
        });
      });
    },
  };
})(Drupal, once);

Finally, the component is ready to be included in one of the Twig templates of your theme (the ones in the templates folder):

{{ include ('example_theme:button', {
    'title': 'Click me',
    'type': 'primary',
    'icon': 'cog.svg',
    'message': 'Lorem ipsum',
  },
  with_context = false)
}}

The final result should look like this:

The button component rendered in page

Try to click on the button and see what happens.

Starting from drupal-code-generator version 3.2.0, a new generator has been added to easily create new components (this replaces the Component Libraries: Generator module that is not compatible with Drush 12). Just run this command and follow the instructions:

drush generate sdc

WebProfiler integration

The latest version of the WebProfiler module (10.1.1) offers full support for collecting and exploring the components used on a page.

On the WebProfiler toolbar, a new counter has been added to the theme widget, showing the number of components used on the page:

The SDC data collector in the WebProfiler toolbar

Clicking on the counter will open the WebProfiler dashboard, showing all the components used on the page:

The SDC data collector in the WebProfiler dashboard

At the time of writing, a core patch is required to enable this feature; be sure to apply it before enabling the SDC module.

Another new feature is the ability to explore the list of libraries used on the page (under the Asset data collector). As SDC automatically declares a library for each component, you can use the new pane to find the one used by the button component:

The libraries data collector in the WebProfiler dashboard

Conclusion

SDC is becoming the de facto standard for building Drupal components, with emerging modules (like No Markup and Single Directory Components: Display) and best practices. More will come in the future.

In this article we have just scratched the surface of this new feature, to learn more we recommend you to read the just published Modernizing Drupal 10 Theme Development book.

Modernizing Drupal 10 Theme Development

In the book you’ll find a detailed explanation about how themes work in Drupal 10, how to use SDC, how to integrate with tools like Browsersync and Backstop.js and how to expose your work to frameworks like Storybook.