Mikhail Romanov

@michaelromanov

Front end journey into Drupal + Pattern Lab

January 9th 2018

Pattern Lab is a hot topic in Drupal community nowadays, it offers a lot of perks and it promises easy life for designers, clients and finally for developers. Being modern and innovative our team surely couldn’t pass by so we watched and read several articles about and full of excitement brought it to the upcoming project. One thing I noted though was that most part of the presenters had significant knowledge of Drupal which wasn’t my case but I didn’t pay attention that time.

There are 3 reasons we liked Pattern Lab for and I will go through them sharing what we found out and which you should pay attention on while adopting the technology.:

  1. Component based approach
  2. Decoupling frontend and backend so frontend can work without knowing the guts of Drupal
  3. Nice pattern library playground which can be shown to the customer/designer for early review

1. Component based approach

With rising of frontend frameworks like React, Angular 2+, Polymer and many others it is hard to imaging non-component based front end architecture nowadays which in short means that every component has its own scope for data, view and controller logic, which are normally presented with JS, CSS and JSON or YML, meaning changes inside one component won’t affect styles and internal logic of others.

So the normal component looks like this:

Pattern Lab recommends to group assets into folders based on Atomic design methodology and provides a great support for component’s isolated dummy data giving us freedom to choose our own tools to handle JS and CSS scope which is a clever move in the sense that they cannot predict the preferred stack we normally use for that.

HTML: there is no much of complications about HTML scope so we just create own twig template for each component and then use it wherever we want through include and embed twig directives passing appropriate parameter values.

Component Data: we can choose JSON or YAML format for components dummy data. Both are great and there are easy ways to quickly migrate from one to another though we picked YAML as it looks cleaner:

JSON vs YAML example

These files are used solely to render components in the Pattern Lab UI and never appears on production. We can set multiple instances of dummy data for each component by simply altering the file name postfix separated with the tilde symbol which makes it super useful for testing and demonstrating different states of the component.

Data file structure
Example of different component states

There is a global data file which is accessible throughout the tree of components so it is good idea to put for example global menu items or footer links there. Global data file is normally accessible by this location: pattern-lab/source/_data/data.yml.

Caution: The only data that is used to render a component is its own data and global data. If we include or embed component_1 inside component_2 we have to put data for component_1 into the data file of component_2. If you want to avoid that manual work check out this plugin: Data Inheritance Plugin.

CSS: we used SCSS + SMACSS + BEM combination which gave us a way to isolate CSS through class naming convention. I won’t go into details here but you can take a look on some SCSS tricks to achieve this. I’m also looking forward into CSS Modules for future projects.

JS: is the most complicated part and breaks into several tasks.

Module bundler: Drupal 8 by default provide a very cool way to attach component’s CSS and JS to the page by introducing a library concept which allows to specify different bundles in Drupal config and then include only those of them into the page which are really required. A library definition can look like this:

And then has to be attached to the template by any of the methods described in documentation here.

The problem can rise if accordion.js from our example has its own dependency inside. It’s not a good idea just to put this dependency on the same level in config file cause in this case we have to copy it over everywhere. And if there are several levels of dependencies things become very confusing.

To solve this we used good old Browserify, and Webpack can also be an option. To make it work we just require module inside our JS file and let Browserify handle it for us through a gulp task. That’s how our overlay component javascript file begins:

Another issue is that Pattern Lab knows nothing about the Drupal libraries concept and if we want our components to work inside its sandbox we have to add all same libraries into the pattern-lab/source/_meta/_01-foot.twig file to make sure our JS is accessible on all pages inside the testing environment.

To simplify things in the beginning we just created one big JS bundle and attached it both to Drupal and Pattern Lab. Luckily we were able to keep the bundle relatively small and there were no much room to split JS between pages so our temporary solution became permanent :)

Component interaction: Once we have all components isolated we have to define a way how they communicate to each other.

Imagine we have a header component and a sidebar menu which slides-in any time button is pressed in the header.

We could do the logic right inside the header JS(inside a click event handler) but as soon as we strived to a loosely coupled architecture we decided to go with a simple mediator pattern in place and choose Redux. It’s a pretty popular one and I covered some of its aspects before.

One issue to not forget is that Redux by default calls all store subscribers which we don’t want to happen cause we don’t have Virtual DOM and clever change detection mechanism here like React has, so we used an extension called redux-watch and wrapped our subscribe method in the way that only required reducer is invoked:

If terminology sounds confusing Redux documentation may be helpful.

Drupal behaviors: If you never worked in Drupal projects you have to make yourself familiar with Drupal Behavior concept. In short in Drupal world we cannot rely on any document load events because any time Drupal through AJAX can replace any part of HTML with the fresh version of it and the only way we know about that is through attachBehaviors method call.

So rule of thumb here:

Always wrap your JS code with Drupal.behaviors.yourName object
Behavior example

Though Pattern Lab knows nothing about behaviors and we have to manually attach drupal.js from Drupal core to all of our Pattern Lab pages inside pattern-lab/source/_meta/_01-foot.twig file:

Code for attached drupal.js

Together with ready.js. This is already included in Emulsify Drupal theme which I will cover later so probably you just need to uncomment appropriate lines of code.

Taking everything above is done and working seems we are good to go.

But wait!

2. Decoupling

One of the important aspects of Drupal + Pattern Lab combination is decoupling frontend work from backend meaning that those two teams can work almost independently by having clear separation defined by list of components and their parameters. And here tricky things begin.

Decoupling is achieved by twig namespaces module which gives a way to put all frontend templates in one place and then reference them from Drupal templates folder.

Still sounds good overall.

Forms: So let’s start with the forms. If you think you can make an input component and then in a Pattern Lab template include it inside a form like this :

you are wrong.

The way Drupal handles it is first it renders separately each input component as a field and then provide this rendered HTML as a string parameter to the form. First time we found that out, we created an if clause where for Pattern Lab we used include and for Drupal we used rendered field . We created a global parameter named patternLab in pattern-lab/source/_data/data.yml file to have a way to distinguish if we are inside Pattern Lab or not.

Example of incorrect code

Don’t do this.

First you cannot be sure there is no patternLab variable in Drupal and second there is a cleaner way to do the same which allows to have single version of twig file by moving Pattern Lab data to the place where it is supposed to be, to the YAML file:

Example of correct code — twig
Example of correct code — yml

This is achievable thanks to Data Transform Plugin by aleksip(very cool guy!, follow him if you are into Drupal front end).

Attribute object: My first implementation of input looked like this:

Input — example of incorrect code

Guess what? This is wrong. Drupal uses Attribute object for the forms and form controls to set and manipulate their HTML attributes.

Learn about Attribute object and best practices how to use it here

So the correct way is something like this:

Input — example of correct code

Luckily to make it work in Pattern Lab(thanks again to Data Transform Plugin) we can emulate attributes object inside a data file:

Update 19.01.2018: There is a cleaner way to handle attributes in Pattern Lab. Please check out the superb response from Evan Willhite, maintainer of Emulsify here.

But

Don’t use create_attribute() method inside Pattern Lab. It is not supported. You should only use it in the Drupal templates folder.

Modules: Drupal allows to quickly build a web application thanks to huge amount of contributed modules.

I am not sure why(may be some modules are not fully migrated to Drupal 8 or it is simply difficult to separate a view for them) but there are cases where you have to deal with whatever HTML you get from the server if you want to keep your fast development pace fast. One of the examples is a search results. If you prepared a template for that you can throw it away. The only way you can style it is overriding CSS for that HTML which is already provided by the module.

Define with your team all modules to be used in the project in advance

Forms, validation messages, shariff, sitemap are good candidates for that. There was a case where I had to ask Drupal team to add a class to the element so I can add a padding in the end. Like it or not we have to deal with it.

Sometimes a module may be picked based on the underlying JS technology. Very popular Simple hierarchical select for example uses Backbonejs inside so be ready to learn it on the way to debug your application.. or ask team to consider alternative one.

Responsive images: Separate attention to Drupal Responsive Images module cause there are high chances it will be used in the application.

Be ready to receive from the server the whole rendered <picture> element instead of image path in your templates.

Translations: Not very Drupal-specific but remember about translations in your twigs. Discuss with the team which of those you’re going to use:

string | t or {% trans %} string {% endtrans %}

and don’t forget about translation context if it is required though it can be fixed later with replace-all IDE functionality.

Debug Drupal: It is forbidden to write about Drupal debugging in the chapter dedicated to decoupling frontend with backend but

learn about kint and locating of Drupal templates

We front end developers may not use these methods ourselves but at least we should know they exist and ask Drupal team to help with debugging when needed.

Themes: Drupal is a big open-source community meaning many things are already in place and done by some clever guys. To avoid reinventing the wheel it is good idea to start with the Drupal theme which already includes Pattern Lab. The most popular are:

Particle

Emulsify.

We started with Emulsify and I very appreciate the way they organized the gulp tasks and documentation but be careful as they use Pattern Lab Standard Edition for Twig by default which doesn’t include important Drupal plugins namely:

Drupal Twig Components plugin which allows to use Drupal filters and functions in Pattern Lab(say | t filter)

and already mentioned above

Data Transform plugin which makes life much much easier(Attributes object, include inside YML files, etc.)

Particle theme at the same time uses Pattern Lab Twig Standard Edition for Drupal which includes both mentioned plugins by default and some useful methods like npm run new.

Choose the correct Pattern Lab edition.

If you still prefer the way everything organized in Emulsify theme just update pattern_lab.sh file in it to pick the right edition.

3. Pattern Lab UI

Pattern Lab UI is good and easy to use. It allows to view a specific component, group of components or search one if you are not sure how to access it from the menu.

One thing you probably should remember is that

all your controls are tested inside an iframe

If issues or special case arises(print page feature, for example) there is a way to test the component in a separate window outside of iframe:

Menu to open component in a separate window

Pattern Lab UI has a lot of settings but I didn’t find any good documentation for them. Please share in comments if you know one.

Who to follow

There are couple of blogs/repos I would suggest to follow to get some insights:

Emulsify theme maintainer’s Evan Willhite blog:

And other resources suggested in the responses below(here).

Conclusion

Pattern Lab indeed is a very nice way to organize and present front end template library and I don’t know any good alternatives for achieving that at the moment taking it is not a headless Drupal project.

Projects like Particle and Emulsify make a strong move towards decoupling the front end and back end work though it is naive to think that having a prior Drupal experience is not a requirement anymore to write high quality front end code in such projects. Knowing how Drupal theming, forms and other popular modules work is still indispensable in my opinion.

Have fun with coding and please let me know about your experience in the comments.

More by Mikhail Romanov

More Related Stories