Have you ever written the same code twice while theming a Drupal website? Learn how to build a site with easily reusable components using the UI Patterns module. Such component-based software development results in faster development cycles because you build each component only once.

Component-based software development (CBD) suggests a reuse-based approach of defining, implementing and composing loosely coupled independent components into systems.  It promotes conceiving and building websites as groups of multiple smaller, reusable components. This eventually results in faster development cycles – meaning, your company makes more profit and the developers go home on time!

In this tutorial, we’ll learn to work with the UI Patterns module to create time-saving reusable components for your Drupal 8 website.

Two Minute Version

For a detailed tutorial, skip to the next heading.

  • Download and install the UI Patterns module.
    • Optionally, install the UI Patterns Library module.
  • Define a UI pattern by creating a directory at THEME/patterns/PATTERN – where THEME and PATTERN with their respective machine-names.
    • You can also use a custom module instead of a theme.
  • Create the following files in the directory:
    • PATTERN.patterns.yml containing pattern metadata as per documentation.
    • pattern-PATTERN.html.twig containing HTML for the pattern.
    • Optional CSS and JS for the pattern’s appearance and behaviors.
  • Pattern is defined! Install one of these modules to start using it:
    • UI Patterns Layouts
    • UI Patterns Field Group
    • UI Patterns Display Suite
    • UI Patterns Views

Prerequisites

  • Know basic site-building.
  • Know how to setup a custom module / theme in Drupal 8.
  • Know some basic twig.

Step 1: Getting started

Install and enable the UI Patterns module just like you install modules in Drupal 8. Also, enable the UI Patterns Library module which shows a list of all patterns on a single page at /patterns. You can use this page to preview your patterns during development.

Screenshot of a list of UI Patterns from jigarius.com
A list of patterns appears on the library page.
You won’t see any output until you’ve finished Step 3, i.e., defined the pattern and created a twig file for it.

Step 2: Defining patterns

To use a pattern, we need to define it first! Pattern definitions contain metadata about the pattern. Let’s create a pattern called blockquote. Start by creating the following file:

Note: Any changes to this YML file will only take effect after clearing Drupal’s cache.

## File: THEME/patterns/blockquote/blockquote.patterns.yml
blockquote:
  label: 'Blockquote'
  description: A block of text quoted from an external source.
  # variants: ...
  fields:
    content:
      type: text
      label: Content
      description: The body of the quote.
      preview: 'To be or to not to be... That is the question.'
    attribution:
      type: text
      label: Attribution
      description: Reference to the original author (optional).
      preview: 'William Shakespeare'
    cite:
      type: uri
      label: Citation
      description: URL where the original text can be found (optional).
      preview: 'https://example.com/'
  libraries:
    -
      blockquote:
        css:
          component:
            css/blockquote.css: {}

Here’s a description for some of the note-worthy elements of the definition.

Fields

Definition of fields supported by this pattern, keyed by field IDs. Each field must have:

  • label: A human-readable label.
  • description: A description.
  • type: The type of data expected by the field. Example: text|numeric|uri|boolean|collection|mixed. At the moment of writing this article, this is only used for documentation.
  • preview: A string or a Drupal renderable array. This is used to generate previews on the pattern library page.

Libraries

Define Drupal libraries for your pattern. This makes your UI pattern self-contained as these libraries are automatically loaded whenever you use the associated pattern.

Performance tip

If you have a large number of patterns, it might make sense to disable aggregation for patterns which are used on a handful of pages. Doing this ensures that Drupal loads aggregated CSS / JS for libraries which are used on all pages and that the pattern’s libraries are only loaded on pages where they are actually used. This makes more sense when the patterns in question have substantial amount of code in their libraries, for example, carousels.

Loading UI pattern libraries globally

What if we want to have the CSS / JS for the block quote on all pages, even the ones where the pattern is not used? You can do this by referring to the pattern’s library from your THEME.libraries.yml as follows:

global-styling:
  # ...
  dependencies:
    - ui_patterns/blockquote.blockquote
    # ...

In this way, you can style all block quotes on the site without repeating the CSS elsewhere.

Variants

The UI Patterns also support component variants. Variants are different versions of the same UI pattern. Say, we want to have 2 types of block quotes:

  1. Default version
  2. Highlighted version

You can do this by including the variants key in your pattern definition as follows:

blockquote:
  # ...
  variants:
    default:
      label: Regular
      description: A regular blockquote.
    highlighted:
      label: Highlighted
      description: A highlighted blockquote.
  fields:
  # ...

Now that the variants have been defined, there are two ways you can give them a different look:

  1. Using class names:  In your twig file, you will receive a variable named variant. Use this as a class to apply different CSS to your variants.
  2. Using multiple twig files: If your variants use completely different HTML, create a separate template named pattern-PATTERN--variant-VARIANT.html.twig to render your variants.

Step 3: Pattern templates

Once you’ve defined the pattern, create a blockquote.html.twig in your pattern’s directory. This will contain a template for the block quote.

{# File: THEME/patterns/blockquote/pattern-blockquote.html.twig #}
<blockquote class="blockquote-{{ variant }}" cite={{ cite }}>
    <div class="blockquote__content">{{ content }}</div>
    {% if author %}
        <footer class="blockquote__author">{{ attribution }}</footer>
    {% endif %}
</blockquote>

Usually, I start the twig file without any variables and add in the variables later. When the template is in place, clear Drupal cache and visit the /patterns page to see your pattern in action.

Screenshot of the UI Patterns preview page

Step 4: Organizing patterns

It is quite possible to dump all the patterns in a single directory. However, once you start creating a bunch of patterns, it is highly recommended that you organize them nicely. One such approach is to organize them into directories as per Atomic Design principles.

Screenshot of UI Patterns arranged as per Atomic Design
UI Patterns arranged as per Atomic Design

As per atomic design principles, we can arrange the patterns as follows:

  • Atoms: Basic building-blocks or the smallest of patterns. Example: A title, an image, a button.
  • Molecules: Patterns that use one or more atoms. Example: A hero that comprises of a title, an image and a button.
  • Organisms: Patterns that use a combination of one or more molecules. Example: The page header comprising of a logo, a nav bar and a hero.
  • Templates: Groups of organisms and smaller patterns, stitched together to form pages. Example: A standard page that has a header and a footer.
  • Pages: Are “specific instances of templates” and they are “the most tangible”. Example: The home page or the contact page.

I like this school of thought and I use it in my projects like many other developers. However, you can organize your templates as per your team’s preferences.

Step 5: Using patterns

Once you configure UI patterns, you are ready to reap the benefits in more than one way! You can use patterns in a wide variety of situations, some of which have been mentioned below.

Using UI Patterns with Display Suite

This is by far the method that I’ve used the most.

  1. Install the UI Patterns Display Suite and the UI Patterns Layouts module.
  2. Visit the Manage Display page for an entity
  3. Choose to render the entity with a UI Pattern layout.

Screenshot of using patterns with Display Suite
Choose a pattern, save the configuration and then map the fields.

Highly-customizable, component-driven pages

I use display suite and patterns the most with the paragraphs module to allow editors to build pages with components of their choice. You can do this as follows:

  1. Create a paragraph type, say Block quote – matching the paragraph name to the pattern name avoids confusion.
  2. Create fields to match the fields in the UI Pattern, i.e. content, author and attribution.
  3. From the Manage display  page, configure the paragraph to render as the block quote layout that we created.
  4. Map the paragraph fields to the appropriate UI pattern fields and save the configuration.

Now, if you attach the paragraph to a node (or any other entity), it will be rendered using the block quote pattern. You can create more such pattern-based paragraphs to allow editors to create a wide variety of pages with the components of their choice!

Using UI Patterns with Views

Most Drupal sites need to provide pages with lists of content, for example, a blog page, a search results page, etc. With the UI Patterns Views module, you can render the items of these list pages consistently as UI patterns.

Screenshot of configuring views row display as UI patterns
First, choose the row style as Pattern, then click on Settings to map the views fields to pattern fields.

To render Views rows as UI patterns, do the following:

  1. Edit the View and in the Show field under the format section, choose Pattern.
  2. Now, in the row style options dialog, choose a pattern — each row in the View will be rendered using this pattern.
  3. Next, add some fields to the View — these fields will provide data to the UI pattern.
  4. When all required fields are added to the view, click the Settings link for the Show field and map the View fields to the correct UI pattern fields.

Now, when you save the View and visit the page containing the View, each row will appear as a UI pattern.

Due to the way the UI pattern module works, it cannot display pattern previews on the Views admin page. You might see errors saying “Pattern Views row plugin does not support preview” which is normal.

Alternate approach using teasers

As an alternate approach, you can:

  • Configure the teaser view of your content types to be rendered as patterns.
  • Now, configure your Views rows to display as teasers.

Using this approach, you can see proper previews even in the Views preview area.

Using UI Patterns with field groups

Field groups, as the name suggests, allows you to group two or more fields. The     
UI Patterns Field Group module allows you to render field groups as patterns.

Screenshot of using UI patterns with field groups
Create a new field group of the type Pattern.

Simply go to the Manage display page for an entity and

  1. Create a field group named, say, Blockquote.
  2. Drag the related fields under the field group and save the configuration.
  3. Click on the settings icon for the field group — you’ll see a form for field mapping.
  4. Map the fields to the respective UI pattern fields and save the configuration.

Now, when the field group will be rendered as a UI pattern.

Using UI Patterns with Twig Tweak

Drupal provides a bunch of functionality in the twig templates. However, most of what core doesn’t provide can be found in the Twig Tweak module. Simply install the module and then you can render patterns from twig files as follows:

{{ pattern('blockquote', {
  'content': node.body.summary,
  'author': node.owner.name.value
}, 'highlighted') }}

Read documentation for the Twig Tweak module to learn about other cool features it provides.

Using UI Patterns programmatically

Last but not the least, there are times when you want to create a render arrays to display data as UI Patterns. You can do this as follows:

$elements['blockquote'] = [
  '#type' => 'pattern',
  '#id' => 'blockquote',
  '#variant' => 'highlighted',
  '#fields' => [
    'content' => 'The gravest battle a man can fight is the one against himself.',
    'author' => 'Jigarius'
  ]
];

Other modules will then be able to implement a hook_preprocess_HOOK() to alter your renderable and the data will then be rendered as a UI pattern.

Conclusion

UI Patterns brings component driven development to Drupal, which is awesome! I think I will never do Drupal front-end development without this module again. Have you tried this module yet? What do you think about this module? Please post your experiences in the comments section below.

What next?

On this page

Never miss an article

Follow me on LinkedIn or Twitter and enable notifications.