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.:
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](https://github.com/jprichardson/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!
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](https://weknowinc.com/blog/drupal-theming-using-pattern-lab?utm_source=drupal-newsletter&utm_medium=email&utm_campaign=drupal-newsletter-20170104)
.
Choose the correct Pattern Lab edition.
If you still prefer the way everything organized in Emulsify theme just update [pattern_lab.sh](https://github.com/fourkitchens/emulsify/blob/develop/scripts/pattern_lab.sh)
file in it to pick the right edition.
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.
There are couple of blogs/repos I would suggest to follow to get some insights:
aleksip.net_The personal website of Aleksi Peebles, a professional web developer since 1996 and a Drupal developer since 2007._www.aleksip.net
phase2/particle_particle - A starting place for using the prototyping tool, Pattern Lab, in tandem with a Drupal theme. Can be used…_github.com
Emulsify // Pattern Lab + Drupal 8_Components are the reusable chunks of web sites. They can be small (inputs, labels, buttons), medium (header, footer…_emulsify.info
Emulsify theme maintainer’s Evan Willhite blog:
Evan Willhite, Senior Frontend Engineer at Four Kitchens_Evan Willhite is a senior frontend engineer at Four Kitchens with who thrives on creating delightful digital…_www.fourkitchens.com
Join Drupaltwig on Slack!_Edit description_drupaltwig-slack.herokuapp.com
Blog & Digitale News | BUZZWOO!_Willkommen im Blog der Internetagentur BUZZWOO! Hier finden Sie Artikel zu folgenden Themen: Drupal ✓ Wordpress …_www.buzzwoo.de
And other resources suggested in the responses below(here).
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.