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
– whereTHEME
andPATTERN
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.
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:
- Default version
- 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:
- Using class names: In your twig file, you will receive a variable named
variant
. Use this as aclass
to apply different CSS to your variants. - 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.
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.
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.
- Install the UI Patterns Display Suite and the UI Patterns Layouts module.
- Visit the Manage Display page for an entity
- Choose to render the entity with a UI Pattern layout.
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:
- Create a paragraph type, say Block quote – matching the paragraph name to the pattern name avoids confusion.
- Create fields to match the fields in the UI Pattern, i.e. content, author and attribution.
- From the Manage display page, configure the paragraph to render as the block quote layout that we created.
- 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.
To render Views rows as UI patterns, do the following:
- Edit the View and in the Show field under the format section, choose Pattern.
- Now, in the row style options dialog, choose a pattern — each row in the View will be rendered using this pattern.
- Next, add some fields to the View — these fields will provide data to the UI pattern.
- 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.
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.
Simply go to the Manage display page for an entity and
- Create a field group named, say, Blockquote.
- Drag the related fields under the field group and save the configuration.
- Click on the settings icon for the field group — you’ll see a form for field mapping.
- 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?
- See the source code for the “block quote” UI pattern example on GitHub.
- Read the official documentation for the UI Patterns module.
- Read about the Twig Tweak module and the features it provides.
- Use UI Patterns module and let us know how it goes.