Particle

Opinionated tools to build Design Systems
 

Christopher Bloom

Phase2 Technology

http://bit.ly/2DIO6r2

Navigating this deck yourself?

If you're working your way through these slides yourself, note a couple of things to help you along:

 

  1. This presentation has DOWN arrows to navigate, not just left/right arrows. Pay attention to the arrows to the lower right of the slides. You'll miss HUGE parts of the presentation if you don't navigate downward!
  2. The Particle repo is here: https://github.com/phase2/particle

TLDR

  • Some learnin'
  • Some installin'
  • Some codin'

* Codin' subject to bandwidth and technology not explodin'

Prerequisites

PHP 7+

Node

OSX w/ Homebrew

brew update
brew install php
php --version
nvm install v12
nvm alias default v12
node --version

Linux (Debian)

sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install php7.2-cli

OSX w/ NVM

Linux

<-- Use NVM

Install all prerequisites

# 1. Skip steps if you already have the tools listed
# 2. Run source ~/.bashrc or source ~/.zshrc after each step to ensure command is registered

# Install Homebrew, if not installed
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

# Update Homebrew installed packages
brew update && brew upgrade

# Install PHP 7.2, if not installed
brew install php

# Install NVM, if not installed
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash

# Node 10 or 12. Leave off `nvm alias default v12` to prevent setting system wide node version
nvm install v12 && nvm alias default v12

# NPM 6+
npm install -g npm@latest

# Option 1: Get particle via starter script
npm create @phase2/particle particle && cd particle

# Option 2: Get particle via git clone
git clone git@github.com:phase2/particle.git && cd particle

# Install Particle dependencies. Run only once at the start of a project.
npm install && npm run setup

# Start Particle every time you want to work in Pattern Lab
npm start

Scenario

  1. You have to build a thing

  2. There are designs

  3. Those designs have to become code

  4. That code will be consumed by some final system

You are in Frontend Sprint 0

Old Way:

Frontenders couldn't theme before content types and servers and databases and features and designs were done. This meant frontend was usually the frantic end of a project.

New Way:

Frontenders work on design systems and tooling long before backend decisions, working in parallel to the rest of the build. Components are agnostic but "schema-driven".

Modern design implementation starts at the beginning of a project instead of the end.

We're not "Themers".

We're "Design System Appliers"

Design Systems

... a collection of reusable components, guided by clear standards, that can be assembled together to build any number of applications."

Style Guide

  • Colors

  • Typography

  • Spacing

  • Grids

  • Image treatment

  • Iconography

Pattern Library

  • Application of Style Guide to many small UI components

  • Assemble like Lego to build more complex screens

  • Iteratable, evolving

  • REAL CODE (HTML, Twig, React)

  • UI interactive behaviors

+

Atomic Design

  • atomicdesign.bradfrost.com
  • A philosophy about the pieces that make up a design
  • Defines a design language for a site
  • Specifies various levels of complexity of patterns in the UI
  • Helps us answer "How are we going to turn this picture into code?"

We will use the principles of Atomic Design to break up designs into coded Twig files:

  • Atoms
  • Molecules
  • Organisms
  • Templates
  • Pages

Pattern Lab

patternlab.io

 

Simply a tool to apply Atomic Design principles to Twig components.

 

Renders all components to HTML.

 

Provides a UI to navigate the components.

 

Using Pattern Lab Node! (via Twig PHP renderer)

Particle

A bunch of tools to build design systems

https://github.com/phase2/particle

  • Starter-Kit = tools + examples
  • Drupal theme, Pattern Lab app
  • Strict Atomic Design component structure
  • Webpack bundling of all CSS, javascript, font, and static image assets for multiple targets
  • Webpack Dev Server for local hosting and auto asset injection into Pattern Lab and Drupal
  • pa11y accessibility testing
  • VueJS framework integration
  • Twig namespaced paths generated automatically. @atoms/thing/_thing.twig means the same thing to Drupal and Pattern Lab.
  • SVG icon auto-generation
  • Bootstrap 4 integration, used for all starting example components
  • Auto-linting against the AirBnB JS Style Guide and sane Sass standards
  • Prettier auto code formatting
  • All Webpack files are fully configurable
  • Jest unit tests for all components

Particle

  1. Assets
    1. Twig
    2. ​CSS
    3. Javascript
    4. Fonts
    5. Static images
  2. Apps
    1. ​Pattern Lab
    2. Drupal theme

Particle is Design Modules

  1. A folder of Twig, Sass, and Javascript
  2. Tied together with asset dependency via JavaScript modules
  3. All pulled into a single Design System library

Dependency Chain

source/molecules/card/index.js

source/default/index.js

apps/pl

source/

node_modules/bootstrap

Tooling: Node.js!

  • Webpack: Now the heavy-lifter of our toolchain
    • "Bundling"
    • ES6
    • Sass
    • Linting
    • SVG icon generation
    • Fonts
    • Static image processing
    • Static site serving

Webpack

slides.com/illepic/webpack

 

Most of a frontender's job is generating assets.
 

  1. BUNDLES assets
  2. Provides DEPENDENCY MANAGEMENT of assets
  3. Active development server

Webpack Inheritance

webpack.particle.js
source/default/webpack.config.js
apps/drupal/webpack.config.js

DEV

PROD

DEV

PROD

Overall, shared config 

Design System-specific config

("Where are 'atoms'?")

App-specifc overrides

("Where is the bundle output?")

NPM scripts

  • npm run new - Make a new component
  • npm run fmt - Format/lint all SCSS, JS, SVG to standards
  • npm run test - Unit test all JS (updatable to run pa11y and backstop)
  • npm run dev:pl-node - Same as npm start, kicks off localhost dev mode
  • npm run build:pl - Compile all PL assets for static production
  • npm run dev:drupal: A watcher to rebuild assets quickly while working in Drupal
  • npm run build:drupal: Bundle up all assets with production optimization in Drupal

Installation

npm create @phase2/particle particle
cd particle
npm run setup
npm start

Let's make a card!

Build this card: html5up.net/phantom

Deconstruct using

Atomic Design principles

Download the zip and extract:

html5up.net/phantom/download

 

Move html5up-phantom/

to

source/default/tokens/sass/libraries/html5up-phantom/ 

 

Now edit:

source/default/tokens/sass/tokens.scss
////
/// Library printing
////

@use 'libraries/bootstrap';

// Add this
import './html5up-phantom/assets/css/main.css';

// ...

(Sass errors? Delete html5up-phantom/assets/sass/)

Our active Pattern Lab running at http://localhost:8080/app-node-pl/pl should look different!

 

Visit http://localhost:8080/app-node-pl/pl/?p=viewall-molecules-demo-card for a sense of the difference.

 

The new CSS is being compiled in!

 

Now, let's make new molecule called

phantom-card

 

The following file structure is created by running:

npm run new

What's going on here?

  • New molecule component: phantom-card
  • Styles for just this component
  • PURE twig template, usable by PL, Grav, Drupal
  • Javascript module pulling together logic/styles
  • "demo" folder is what PL actually renders
  • Includes and shows off "pure" template
  • Data made available for the demo twig file

Steal card markup from

source/default/tokens/sass/libraries/html5up-phantom/index.html
and paste it into

_phantom-card.twig

<article class="style1">
  <span class="image">
    <img 
      src="https://www.fillmurray.com/353/326" 
      alt="Bill"
    />
  </span>
  <a href="#">
    <h2>Magna</h2>
    <div class="content">
      <p>Sed nisl arcu euismod sit amet nisi
      lorem etiam dolor veroeros et feugiat.</p>
    </div>
  </a>
</article>

It's not pretty, but let's roll with it. Change img src and href to something generic for now.

 

Our card should show up in PL!

This looks gross because the CSS we inherited is ... not good.

<div class="tiles">
  {% include '@molecules/phantom-card/_phantom-card.twig' %}
</div>

In

apps/node-pl/pattern-lab/_patterns/02-molecules-demo/phantom-card/phantom-cards.twig

 surround the include with .tiles:

If we truly want to do this the RIGHT way, we'd

 

  1. BEM the heck out of it
  2. Pull the phantom styles into
    _phantom-card.scss
  3. Rewrite the ugly css to be much more modular, with lower specificity
<article class="phantom-card phantom-card--style1">
  <span class="phantom-card__image-wrapper">
    <img
      class="phantom-card__image"
      src="https://www.fillmurray.com/353/326" 
      alt=""
    />
  </span>
  <a href="#" class="phantom-card__link">
    <h2 class="phantom-card__title">Magna</h2>
    <div class="phantom-card__content">
      <p>Sed nisl arcu euismod sit amet nisi
      lorem etiam dolor veroeros et feugiat.</p>
    </div>
  </a>
</article>
.phantom-card {
  transition: transform 0.5s ease, opacity 0.5s ease;
  position: relative;
  width: calc(33.33333% - 2.5em);
  margin: 2.5em 0 0 2.5em;
}

.phantom-card__image-wrapper {
  transition: transform 0.5s ease;
  position: relative;
  display: block;
  width: 100%;
  border-radius: 4px;
  overflow: hidden;
}

.phantom-card__image {
  display: block;
  width: 100%;
}

// ...

Let's make our Twig files dynamic!

 

Add variables to _phantom-card.twig

 

Update phantom-cards.yml to provide data automatically to twig.

 

Ta da!

 

Variables from .yml files are automatically provided to .twig files of the same base name.

<article class="phantom-card phantom-card--style1">
  <span class="phantom-card__image-wrapper">
    <img
      class="phantom-card__image"
      src="{{ phantom_card.image }}" 
      alt="{{ phantom_card.image_alt }}"
    />
  </span>
  <a href="{{ phantom_card.url }}" class="phantom-card__link">
    <h2 class="phantom-card__title">{{ phantom_card.title }}</h2>
    <div class="phantom-card__content">
      <p>{{ phantom_card.content }}</p>
    </div>
  </a>
</article>
phantom_card:
  image: https://www.fillmurray.com/353/326
  image_alt: Picture of Bill Murray
  url: '#'
  title: This is Bill!
  content: Lorem ipsum dolor sit amet.

Integration to Drupal

1. In Drupal, install and enable Component Libraries module.

2. Enable Particle theme and set as default.

3. See:

apps/drupal/templates/content/node--article--teaser.html.twig
{% set article_card = {
  card_border: 'none',
  card_title: label,
  card_text: content.body,
  button: {
    button_element: 'a',
    button_color: 'secondary',
    button_text: 'View details »'|t,
    button_link: url,
  }
} %}

{% include '@molecules/card/_card.twig' with article_card %}

Drupal-Particle Namespaces

particle.info.yml

 

(No templates or pages namespace due to empty folders blowing up the module)

name: Particle
type: theme
description: A Theme with Pattern Lab
base theme: stable
core: 8.x
libraries:
  - particle/core
libraries-override:
  core/jquery: particle/jquery
# ...
component-libraries:
  protons:
    paths: []
  atoms:
    paths:
      - ../../dist/app-drupal/assets/atomic/_patterns/01-atoms
  molecules:
    paths:
      - ../../dist/app-drupal/assets/atomic/_patterns/02-molecules
  organisms:
    paths:
      - ../../dist/app-drupal/assets/atomic/_patterns/03-organisms
  templates:
    paths: []
  pages:
    paths: []

Integration to Drupal

  1. Node view modes

  2. Views content and fields

  3. Paragraphs

  4. Field templates

  5. Entities

  6. Blocks

  7. Menus

  8. Custom theme hooks

  • MODEL: Drupal data provided to a hook

  • VIEW: The actual Particle twig component

  • PRESENTER: The intermediate Drupal "translator" between Drupal data and the  Particle Twig component, ie: node--article--teaser.html.twig

Drupal hooks

Drupal View of Article Teasers

Drupal Libraries: TNG

# Define Particle theme's library CSS and JS assets along with dependencies
core:
  css:
    theme:
      ../../dist/app-drupal/assets/app.styles.css:
        preprocess: true
  js:
    ../../dist/app-drupal/assets/app.js:
      preprocess: true
  # see all in Drupal's `core/core.libraries.yml`
  dependencies:
    - particle/jquery
    - core/drupal
    - core/drupalSettings

# Create custom jQuery libraries
# that'll override the Drupal core jQuery libraries
# See `libraries-override` in particle.info.yml
jquery:
  js:
    ../../dist/app-drupal/assets/drupal-jquery.js:
      { minified: true, weight: -20 }

particle.libraries.yml

# ...
libraries:
  - particle/core
libraries-override:
  core/jquery: particle/jquery
# ...

particle.info.yml

!!!!!!

Testing

  1. Javascript unit testing with Jest

  2. Accessibility testing with pa11y

  3. Visual regression testing with Backstop (soon)

  4. End-to-end testing with Cypress.io (soon)

Jest Unit Testing

We write A LOT of JavaScript on client projects.

 

NONE OF IT IS TESTED. Until now.

 

Write your JavaScript in such a way that it CAN be tested. Stop storing state in the DOM. Make your functions pure. Use libraries (like Redux) that move logic away from HTML.

Accessibility testing with pa11y

Use pa11y automated accessibility testing against a running Pattern Lab prototype to catch most issues early.

 

Start up your local PL:

 

In another session, install then run pa11y:

 

 

See ./tools/tests/accessibility/pa11y.js:

 

ALL Pattern Lab urls are automatically tested!

npm start
npm install pa11y
npm run test:pa11y

Backstop (coming soon)

VueJS + Particle

  1. "The best parts of React and Angular8 with no boilerplate." 

  2. Industry-leading virtual DOM and Reactivity Engine

  3. Simple to learn, incredible resources

  4. All tooling preconfigured in Particle, use .vue files immediately

  5. Never build another widget in jQuery again

  6. Starter examples and guide at @molecules/vue-widgets

  7. Non-trivial Phase2 client app here.

Current: v10.6.3

Next: v11

  • Monorepo of tools and components
  • NPM installable
  • Particle CLI
  • Vastly easier to upgrade
  • "Starterkits" for design systems and frameworks

Contributors

  • Christopher Bloom

  • Yugi Nali

  • Mike Potter

  • Kenny Black

  • Brigette Eckert

  • Daniel Lemay

  • Frederick Engelhardt

Thank you!

Made with Slides.com