Small

Design Systems

for Developers

Alex Riviere

Senior Front-end Developer

What is a
Design System?

Dan Mall

A set of connected patterns and shared practices, coherently organized to serve the purposes of a digital product.

— Alla Kholmatova, Design Systems

Design systems bring order and consistency to digital products. They help to protect the brand, elevate the user experience, and increase the speed and efficiency of how we design and build products.

— Andrew Couldwell, Laying the Foundations

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

— Marco Suarez, Design System Handbook

The components are the trees. The design system is the forest.

— Jeremy Keith, Design systems

The official story of how your organization designs and builds digital interfaces.

— Brad Frost, Design systems are for user interfaces

Any set of decisions governed across an organization.

— Hayley Hughes, Trust Between Teams

A library of visual style, components, and other concerns documented and released by an individual, team, or community as code and design tools so that adopting products can be more efficient and cohesive.

— Nathan Curtis, Defining Design Systems

Design

System

A set of things—people, cells, molecules, or whatever—interconnected in such a way that they produce their own pattern of behavior over time.

— Donella Meadows Thinking in Systems

Types of
Design Systems

Brand Identities
Visual Language

Tools as Design Systems

Products as Design Systems

Process as Design Systems

Photo by Kaleidico on Unsplash

Design System as a Service

Design system as a practice

Thank you.

WAIT. NO.

How do I
implement this?

Smallest use case:
Colors.

PHP

JS

CSS

PHP

JS

CSS

PHP

JS

CSS

JSON

PHP

JS

CSS

JSON
--color

PHP

JS

CSS

JSON
--color

Design Tokens

PHP

JS

CSS

JSON
--color

???

Design Tokens

Design Token Code Generators

  • Dragoman

  • Theemo

  • Mole

  • Theo

  • Style-Dictionary

{
  "colors": {
    "red": {
      "value": "#FF0000"
    },
    "blue": {
      "value": "#0000FF"
    },
    "green": {
      "value": "#00FF00"
    }
  }
}

A design token file

{
  "colors": {
    "black": { "value": "#000000" },
    "traina-purple-400": {  "value": "#8875e2" },
    "traina-purple-300": { "value": "#A897F8" },
    "traina-pink-400": { "value": "#DE706F" },
    "traina-pink-300": { "value": "#F98989" },
    "traina-green-400": { "value": "#5D9E70" },
    "traina-green-300": { "value": "#82C596" },
    "traina-gray-900": { "value": "#151515" },
    "traina-gray-800": { "value": "#232323" },
    "traina-gray-700": { "value": "#454545" },
    "traina-gray-600": { "value": "#636363" },
    "traina-gray-500": { "value": "#727272" },
    "traina-gray-400": { "value": "#8e8e8e" },
    "traina-gray-300": { "value": "#D0D0D0" },
    "traina-gray-200": { "value": "#e8e8e8" },
    "traina-gray-110": { "value": "#f5f5f5" },
    "traina-gray-100": { "value": "#fafafa" },
    "white": { "value": "#ffffff" },
    "error-red": { "value": "#852323" }
  }
}

tokens/colors.json

{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "scss": {
      "transformGroup": "scss",
      "buildPath": "build/",
      "files": [{
        "destination": "_vars.scss",
        "format": "scss/map-deep"
      }]
    },
    "json": {
      "transforms": [
        "attribute/cti", 
        "name/cti/pascal", 
        "color/hex", 
        "size/rem"
      ],
      "buildPath": "build/",
      "files": [{
        "destination": "tokens.json",
        "format": "json/nested"
      }]
    }
  }
}

config.json

npx style-dictionary build

Build the files

/**
 * Do not edit directly
 */

$colors-black: #000000 !default;
$colors-traina-purple-400: #8875e2 !default;
$colors-traina-purple-300: #A897F8 !default;
$colors-traina-pink-400: #DE706F !default;
$colors-traina-pink-300: #F98989 !default;
$colors-traina-green-400: #5D9E70 !default;
$colors-traina-green-300: #82C596 !default;
$colors-traina-gray-900: #151515 !default;
$colors-traina-gray-800: #232323 !default;
$colors-traina-gray-700: #454545 !default;
$colors-traina-gray-600: #636363 !default;
$colors-traina-gray-500: #727272 !default;
$colors-traina-gray-400: #8e8e8e !default;
$colors-traina-gray-300: #D0D0D0 !default;
$colors-traina-gray-200: #e8e8e8 !default;
$colors-traina-gray-110: #f5f5f5 !default;
$colors-traina-gray-100: #fafafa !default;
$colors-white: #ffffff !default;
$colors-error-red: #852323 !default;

$tokens: (
  'colors': (
    'black': $colors-black,
    'traina-purple-400': $colors-traina-purple-400,
    'traina-purple-300': $colors-traina-purple-300,
    'traina-pink-400': $colors-traina-pink-400,
    'traina-pink-300': $colors-traina-pink-300,
    'traina-green-400': $colors-traina-green-400,
    'traina-green-300': $colors-traina-green-300,
    'traina-gray-900': $colors-traina-gray-900,
    'traina-gray-800': $colors-traina-gray-800,
    'traina-gray-700': $colors-traina-gray-700,
    'traina-gray-600': $colors-traina-gray-600,
    'traina-gray-500': $colors-traina-gray-500,
    'traina-gray-400': $colors-traina-gray-400,
    'traina-gray-300': $colors-traina-gray-300,
    'traina-gray-200': $colors-traina-gray-200,
    'traina-gray-110': $colors-traina-gray-110,
    'traina-gray-100': $colors-traina-gray-100,
    'white': $colors-white,
    'error-red': $colors-error-red
  )
);

build/_vars.scss

{
  "colors": {
    "black": "#000000",
    "traina-purple-400": "#8875e2",
    "traina-purple-300": "#A897F8",
    "traina-pink-400": "#DE706F",
    "traina-pink-300": "#F98989",
    "traina-green-400": "#5D9E70",
    "traina-green-300": "#82C596",
    "traina-gray-900": "#151515",
    "traina-gray-800": "#232323",
    "traina-gray-700": "#454545",
    "traina-gray-600": "#636363",
    "traina-gray-500": "#727272",
    "traina-gray-400": "#8e8e8e",
    "traina-gray-300": "#D0D0D0",
    "traina-gray-200": "#e8e8e8",
    "traina-gray-110": "#f5f5f5",
    "traina-gray-100": "#fafafa",
    "white": "#ffffff",
    "error-red": "#852323"
  }
}

build/tokens.json

Recap

  • Created a version we can use in PHP and JS

  • Created a version that can be used in CSS or JS in the browser 

  • More export options available!

But wait!

There's more....

Let's make a
WordPress plugin

<?php

// Set this once here, so we can cache this value for later.
$__DESIGN_TOKENS = null;

function tcp_return_design_tokens()
{
    global $__DESIGN_TOKENS;
    if (!is_null($__DESIGN_TOKENS)) {
        return $__DESIGN_TOKENS;
    }
    $plugin_dir = WP_PLUGIN_DIR . '/traina-color-picker';
    $__DESIGN_TOKENS = json_decode(
        file_get_contents($plugin_dir . '/build/tokens.json'), 
        true
    );
    return $__DESIGN_TOKENS;
}


// gutenberg custom color palette
function tcp_change_gutenberg_color_palette()
{
    $design_tokens = tcp_return_design_tokens();

    // creates an array to store our color variables from css file
    $color_palette = [];

    foreach ($design_tokens['colors'] as $color_slug => $color_hex){
        $color_name = trim(
            ucwords(
                str_replace('-', ' ', $color_slug)
            )
        );
        $color_palette[] = [
            'name' => $color_name,
            'slug' => $color_slug,
            'color' => $color_hex
        ];
    }

    if ($color_palette) {
        add_theme_support('editor-color-palette', $color_palette); 
    }
}
add_action('after_setup_theme', 'tcp_change_gutenberg_color_palette');

traina-color-picker.php

@use "./build/vars" as v;
@use "sass:map";


@each $name, $color in map.get(v.$tokens,colors){
    .has-#{$name}-color{
        color: #{$color};
    }
}

main.scss

<?php

function tcp_enqueue_styles(){
	wp_enqueue_style('tcp_styles', plugins_url().'/traina-color-picker/build/main.css');
}

add_action('init', 'tcp_enqueue_styles');
add_action('admin_enqueue_scripts', 'tcp_enqueue_styles');


// Set this once here, so we can cache this value for later.
$__DESIGN_TOKENS = null;

function tcp_return_design_tokens()
{
    global $__DESIGN_TOKENS;
    if (!is_null($__DESIGN_TOKENS)) {
        return $__DESIGN_TOKENS;
    }
    $plugin_dir = WP_PLUGIN_DIR . '/traina-color-picker';
    $__DESIGN_TOKENS = json_decode(
        file_get_contents($plugin_dir . '/build/tokens.json'), 
        true
    );
    return $__DESIGN_TOKENS;
}


// gutenberg custom color palette
function tcp_change_gutenberg_color_palette()
{
    $design_tokens = tcp_return_design_tokens();

    // creates an array to store our color variables from css file
    $color_palette = [];

    foreach ($design_tokens['colors'] as $color_slug => $color_hex){
        $color_name = trim(
            ucwords(
                str_replace('-', ' ', $color_slug)
            )
        );
        $color_palette[] = [
            'name' => $color_name,
            'slug' => $color_slug,
            'color' => $color_hex
        ];
    }

    if ($color_palette) {
        add_theme_support('editor-color-palette', $color_palette); 
    }
}
add_action('after_setup_theme', 'tcp_change_gutenberg_color_palette');

traina-color-picker.php

Thank you.

Questions?

  • Slides: slides.com/fimion/magnoliajs-2023
  • Code: github.com/fimion/traina-color-picker

 

  • Twitter: @fimion
  • Mastodon: @fimion@notacult.social
  • Blog: alex.party