Decouple your Pattern Library from your Theme.

sf.gov

I am Israel Morales

and I work in Chapter Three

as Front End Developer

Remotely

:)

Benefits

the same pattern library can be used by other projects.

 

Requirements:

the use of twig

Usually:

The pattern library lives inside your Drupal theme... most of the time:

Pattern lab drupal themes or starter kits:

A list of features:

Client Requirements!

  • We need a Pattern library
    • we don't care which one is
  • We want to implement uswds (for fast prototyping) but we want our own custom PL
  • We want to develop the Pattern lab independently of Drupal, so our developers don't require to have knowledge of Drupal
  • We need it fast

uswds

Pros

  • Fractal 
    • not well maintained
  • SASS super opinionated
    • https://www.bourbon.io
    • https://neat.bourbon.io
  • no use of flexbox or css grid
  • not compatible with twig :(
  • lacking of components, mostly basic components were available.

Cons

  • Fractal
    • easier than PL
  • If used as framework can do stuff fast.

USWDS

I actually tried to refactor all the tamplates to twig and I failed miserably :(

I even tried to use many of the Drupal theme solutions...

and then just override with my stuff.... but...

In my mind:

  • USWDS should be included as library
    • meaning that we will be able to use USWDS classes and JS
  • SFGOV PL should be clean from other frameworks/pattern libraries
  • SFGOV PL should have a class identifier to avoid class collisions or overlaping so all classes would start with `.sfgov`
  • USWDS JS should work along side SFGOV.

 

So I started fresh.

Steps to decouple your pattern library:

1.- Choosing the breed

there are a lot of options for pattern lab out there but in my case non of them matched my expectations

1.- Edition php twig standar means:

means that this edition is bare, with no additions, just the basic stuff.

  • composer to install all the required libraries
  • core has some PHP scripts for after composer install
  • public is were your compiled PL is going to live
  • source is were your components and other stuff is going to be.

1.- how to start with the standard edition.

  • comes with a watcher and other commands you can use for example:
composer create-project pattern-lab/edition-twig-standard badcamp-2018

1.- Edition php twig standar also means:

  • no SASS or SCSS watcher
  • no JS compiler
  • only PHP watcher and compiler

2.- Add Watchers so, we can compile:

  • For this specific project I used Gulp
  • But you can use webpack, or whatever tool you can use to compile JS and CSS. 

2.1 - For this project I used Gulp

  • because I was familiar with it.
  • But you can use webpack, or whatever tool you can use to compile JS and CSS. 

2.2- Watchers for everything:

// Watchers for everything:

gulp.task('watch', function () {
    gulp.watch(config.js.src, ['legacy:js']);
    gulp.watch(config.css.src, ['pl:css']);
    gulp.watch(config.pattern_lab.src, ['generate:pl']);
    gulp.watch(config.pattern_lab.javascript.src, ['generate:pl']);
});
// pl:php

gulp.task('pl:php', shell.task('php pattern-lab/core/console --generate'));

Example of PHP watcher:

2.3- Watcher for SCSS and JS output two single files.

// CSS

/dist/css/components.css

// JS

/dist/pl/js/components.js

3 .- Generate a single CSS and a single JS

so we can use our pattern library as a framework like bootstrap or zurb foundation etc...

3.1 - creating a dist folder with the single CSS and single JS

I committed those files directly to the repo.

But... if you can avoid committing the compiled code and manage the releases with Tag or branches, please do it...

3- Edit Pattern Lab head file.

Editing Pattern Lab head file will include the previously mentioned files, so we can preview our pattern library in the pattern lab PHP server.

// File

/pattern-lab/source/_meta/_00-head.twig

3.1- Edit Pattern Lab head file.

// File

/pattern-lab/source/_meta/_00-head.twig
<!DOCTYPE html>
<html class="{{ htmlClass }}">
<head>
    <title>{{ title }}</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width"/>

    <link rel="stylesheet" href="../../css/pattern-scaffolding.css?{{ cacheBuster }}" media="all"/>

    <link rel="stylesheet" href="../../css/components.css" media="all">
    <script src="../../js/dist/pl/components.js"></script>

    <!-- Begin Pattern Lab (Required for Pattern Lab to run properly) -->
    {{ patternLabHead | raw }}
    <!-- End Pattern Lab -->

</head>
<body class="{{ bodyClass }}">

4 - creating a Drupal theme

Just create a standard Drupal theme.

5 - Enable the component libraries

The Component Libraries module was especially important because it allowed me to map the Pattern Lab components easily into my theme. Then I had to map my Pattern Lab components with the Drupal theme:

6 - Map your PL to Drupal

Once your Twig templates in your pattern library are working you might want to reference them with the component library and custom Twig namespaces.

6.1 - mapping PL to Drupal

// sfgovpl.info.yml

component-libraries:
  protons:
    paths:
      - ../../../libraries/sfgov-pattern-lab/pattern-lab/source/_patterns/00-protons
  atoms:
    paths:
      - ../../../libraries/sfgov-pattern-lab/pattern-lab/source/_patterns/01-atoms
  molecules:
    paths:
      - ../../../libraries/sfgov-pattern-lab/pattern-lab/source/_patterns/02-molecules
  organisms:
    paths:
      - ../../../libraries/sfgov-pattern-lab/pattern-lab/source/_patterns/03-organisms
  templates:
    paths:
      - ../../../libraries/sfgov-pattern-lab/pattern-lab/source/_patterns/04-templates
  pages:
    paths:
      - ../../../libraries/sfgov-pattern-lab/pattern-lab/source/_patterns/05-pages

libraries:
  - sfgovpl/sfgov-pattern-lab

I'm using the ../../../ to reference the libraries forlder in the root of my Drupal install

7 - Using the single CSS and JS via libraries

// sfgovpl.libraries.yml

sfgov-pattern-lab:
  css:
    base:
      '/libraries/sfgov-pattern-lab/dist/css/components.css': {}
  js:
    '/libraries/sfgov-pattern-lab/dist/pl/js/components.js': {}

// sfgov.info.yml

libraries:
  - sfgovpl/sfgov-pattern-lab
  - sfgovpl/sfgov-drupal-specific-styles
  - sfgovpl/google-fonts
  - sfgovpl/resize-disable
  - sfgovpl/sfgov-drupal-search
  - sfgovpl/fontawesome

8 - Using composer to require our external PL

 

This plugin allowed me to put the pattern library in a folder different than vendor

Then I added some configuration to the composer.json

 

I used the following composer plugin:



composer require oomphinc/composer-installers-extender

8.1 - Editing the composer.json

Under extra I specified where composer should install the repository of type github:

 


"extra": {
       "installer-paths": {
           "web/libraries/{$name}": ["type:github"],
         }

8.2 - Editing the composer.json

Then under repositories I set the type:github

 

 


"repositories": {
        "github": {
            "type": "package",
            "package": {
                "name": "sf-digital-services/sfgov-pattern-lab",
                "version": "master",
                "type": "drupal-library",
                "source": {
                    "url": "https://github.com/SFDigitalServices/sfgov-pattern-lab.git",
                    "type": "git",
                    "reference": "master"
                }
            }
        }
    }

8.3 - Editing the composer.json

and required the package under require: As you can see the name matches the name in the previously declared github repo:

 

 

 

A composer update should clone the github repo and place the Pattern Lab inside relative to the Drupal web folder:

/web/libraries/sfgov-pattern-lab

 


"require": {
  "sf-digital-services/sfgov-pattern-lab": "dev-master",
}

9 - Using the PL templates with Drupal.

// node--topic--search-index.html.twig

<div class="topic-search-result">
  <div class="topic-search-result--container">
    <div class="content-type">
        <i class="sfgov-icon-filefilled"></i>
        <span>{{ content_type }}</span>
    </div>
    <a class="title-url" href="{{ url }}"><h4>{{ title }}</h4></a>
    <p class="body">{{ body|striptags('<a>')|raw }}</p>
  </div>
</div>

9.1 - Using the PL templates with Drupal.

{# Set variables to use in the component. #}
{% set url = path('entity.node.canonical', {'node': elements['#node'].id()  }) %}
{% set description = node.get('field_description').getValue()[0]['value'] %}
{% set type = node.type.entity.label %} {# content type #}

{# Icluding the molecule in our Pattern Lab.#}
{% include "@molecules/08-search-results/03-topic-search-result.twig" with {
  "content_type": type,
  "url": url,
  "title": elements['#node'].get('title').getString(),
  "body": description
} %}

Drupal template:
The following example calls the Pattern lab molecule originally located at:

web/libraries/sfgov-pattern-lab/pattern-lab/source/_patterns/02-molecules/08-search-results/03-topic-search-result.twig

but Instead we use:

@molecules/08-search-results/03-topic-search-result.twig

10 - Profit

11 - QA

12 - Thank you

 

Decouple your Pattern Library from your Theme.

By Israel Morales

Decouple your Pattern Library from your Theme.

  • 852