Opinionated tools to build Design Systems
Christopher Bloom
Phase2 Technology
If you're working your way through these slides yourself, note a couple of things to help you along:
* Codin' subject to bandwidth and technology not explodin'
brew update
brew install php72
php --version
brew install composer
composer --version
nvm install node
nvm alias default node
node --version
sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install php7.2-cli
<-- Use NVM
# 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 php72
# Install Composer 1.6+, if not installed
brew install composer
# Install NVM, if not installed
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
# Modern Node
nvm install node && nvm alias default node
# NPM 6+
npm install -g npm@latest
# Get particle via starter script
npm create @phase2/particle particle && 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
You have to build a thing
There are designs
Those designs have to become code
That code will be consumed by some final system
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.
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".
... a collection of reusable components, guided by clear standards, that can be assembled together to build any number of applications."
Colors
Typography
Spacing
Grids
Image treatment
Iconography
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
+
We will use the principles of Atomic Design to break up designs into coded Twig files:
Simply a tool to apply Atomic Design principles to Twig components.
Renders all components to HTML.
Provides a UI to navigate the components.
Built on PHP (for now)
A bunch of tools to build design systems
source/molecules/card
source/design-system
apps/pl
source/
node_modules/bootstrap
Most of a frontender's job is generating assets.
webpack.particle.js
webpack.design-system.js
webpack.drupal.js
DEV
PROD
DEV
PROD
Overall, shared config
Design System-specific config
("Where are 'atoms'?")
App-specifc overrides
("Where is the bundle output?")
The rest of a frontender's job is repetitive tasks.
npm create @phase2/particle particle
cd particle
npm install
npm run setup
npm start
Build this card: html5up.net/phantom
Deconstruct using
Atomic Design principles
Download the zip and extract:
Move html5up-phantom/
to
source/_patterns/00-protons/html5up-phantom/
Now edit:
source/_patterns/00-protons/index.js
import './_base.scss';
// 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/pl/ should look different!
Visit http://localhost:8080/pl/?p=molecules-cards for a sense of the difference.
The new CSS is being compiled in!
Now, let's make new molecule called
phantom-card
Create the following folder structure and empty files by running:
npm run new
Steal card markup from
source/_patterns/00-protons/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=""
/>
</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 demo/phantom-cards.twig, surround the include with .tiles:
If we truly want to do this the RIGHT way, we'd
<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 demo/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: PNWDS2018!
content: Lorem ipsum dolor sit amet.
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 %}
particle.info.yml
Node view modes
Views content and fields
Paragraphs
Field templates
Entities
Blocks
Menus
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
core:
css:
theme:
/themes/particle/dist/assets/app-drupal.styles.css:
preprocess: true
js:
/themes/particle/dist/assets/app-drupal.js:
preprocess: true
dependencies:
- particle/jquery
- particle/lodash
- core/drupal
- core/drupalSettings
jquery:
js:
/themes/particle/dist/assets/drupal-jquery.js: {
minified: true, weight: -20
}
lodash:
js:
/themes/particle/dist/assets/drupal-lodash.js: {
minified: true, weight: -20
}
particle.libraries.yml
# ...
libraries:
- particle/core
libraries-override:
core/jquery: particle/jquery
core/underscore: particle/lodash
# ...
particle.info.yml
!!!!!!
Javascript unit testing with Jest
Accessibility testing with pa11y
Visual regression testing with Backstop (soon)
End-to-end testing with Cypress.io (soon)
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.
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
"The best parts of React and Angular6 with no boilerplate."
Industry-leading virtual DOM and Reactivity Engine
Simple to learn, incredible resources
All tooling preconfigured in Particle, use .vue files immediately
Never build another widget in jQuery again
Starter examples and guide at @molecules/vue-widgets
Non-trivial Phase2 client app here.
VUE!!
Instructions:
https://phase2.gitbook.io/frontend/particle/intro
Multiple Phase2 clients
MULTIPLE DESIGN SYSTEMS for multiple apps
Simpler, unified commands
Easier to add and remove features
Backstop
Yugi Nali
Mike Potter
Kenny Black
Brigette Eckert
Daniel Lemay
Frederick Engelhardt