Particle
Opinionated tools to build Design Systems
Christopher Bloom
Phase2 Technology
Navigating this deck yourself?
If you're working your way through these slides yourself, note a couple of things to help you along:
- 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!
- 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+
Composer
Node
OSX w/ Homebrew
brew update
brew install php72
php --version
brew install composer
composer --version
nvm install node
nvm alias default node
node --version
Linux (Debian)
sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install php7.2-cli
OSX w/ Homebrew
Linux
OSX w/ NVM
Linux
<-- Use NVM
Install all prerequisites
# 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
Scenario
-
You have to build a thing
-
There are designs
-
Those designs have to become code
-
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
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)
Particle
A bunch of tools to build design systems
- Starter-Kit = tools + examples
- Drupal theme, Grav 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.twig means the same thing to Drupal theme 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 and Gulp files are fully configurable
- Jest unit tests for all components
Particle
-
Assets
- Twig
- CSS
- Javascript
- Fonts
- Static images
-
Apps
- Pattern Lab
- Drupal theme
- Grav theme
Particle is Design Modules
- A folder of Twig, Sass, and Javascript
- Tied together with asset dependency via Javascript modules
- All pulled into a single Design System library
Dependency Chain
source/molecules/card
source/design-system
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
- Gulp: Down to few TASKS (not asset dependency management)
- Helper tasks
- "app tasks" (Pattern Lab, Drupal namespaces)
Webpack
Most of a frontender's job is generating assets.
- BUNDLES assets
- Provides DEPENDENCY MANAGEMENT of assets
- Active development server
Webpack Inheritance
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?")
Gulp
The rest of a frontender's job is repetitive tasks.
- Run scripts when files change
- Orchestrate multiple scripts together using javascript syntax
Installation
npm create @phase2/particle particle
cd particle
npm install
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:
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
What's going on here?
- New molecule component: phantom-card
- "demo" folder is what PL actually renders
- Includes and shows off "pure" template
- Data made available for the demo twig file
- Styles for just this component
- PURE twig template, usable by PL, Grav, Drupal
- Javascript module pulling together logic/styles
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
- BEM the heck out of it
- Pull the phantom styles into
_phantom-card.scss - 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 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.
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 %}
Namespace Generation
particle.info.yml
- Gulp task reads filesystem on change of twig files and writes out yaml for Drupal (and PL, and Grav, etc)
- Any application that understands Twig namespaces is compatible with some work, ie all Symfony apps.
- Gulp task editable at:
tools/tasks/gulp-twig-namespaces.js
Integration to Drupal
-
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
Drupal hooks
Drupal View of Article Teasers
Drupal Libraries: TNG
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
!!!!!!
Testing
-
Javascript unit testing with Jest
-
Accessibility testing with pa11y
-
Visual regression testing with Backstop (soon)
-
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
-
"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.
Current: v10.1.0
-
VUE!!
-
Instructions:
https://phase2.gitbook.io/frontend/particle/intro -
Multiple Phase2 clients
Next: v10.2.0
-
MULTIPLE DESIGN SYSTEMS for multiple apps
-
Simpler, unified commands
-
Easier to add and remove features
-
Backstop
Contributors
-
Yugi Nali
-
Mike Potter
-
Kenny Black
-
Brigette Eckert
-
Daniel Lemay
-
Frederick Engelhardt
Thank you!
Copy of Particle: Build Your Own Design Systems
By Jorge Ram
Copy of Particle: Build Your Own Design Systems
We'll learn how the following features of the project fit together to build Design Systems that are independent of any application or CMS: Webpack bundling Webpack dev server Gulp Iconfont auto-generation Bootstrap 4 integration Javascript and Sass linting Design systems integration to a Drupal and Pattern Lab "app"
- 662