Slide 1

Slide 1 text

Design Systems: Developer Point of View Yael Balla @ YGLF, April 2019

Slide 2

Slide 2 text

Hello! I am Yael Balla You can find me at [email protected] www.linkedin.com/in/yael-oshri-balla-6b56686 2

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Design Systems? What’s in it for me? 4

Slide 5

Slide 5 text

So, Let’s start with some definitions 5

Slide 6

Slide 6 text

“ the complete set of design standards, documentation, and principles along with the toolkit (UI patterns and code components) to achieve those standards 6

Slide 7

Slide 7 text

https://uxdesign.cc/can-design-systems-fix-the-relationship-between-designers-developers-eb12fc9329ab Design System Structure

Slide 8

Slide 8 text

Design Systems Examples ▪ Salesforce - Lightning ▪ IBM - Carbon ▪ Google - Material Design ▪ Shopify - Polaris And many others… https://designsystemsrepo.com/design-systems/ 8

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

“ Before this ... Designers and developers were trying their best to make good decisions about which components or patterns to use, but their main reference point was the existing product — which was decidedly inconsistent. Giorgio Lefeber, Xebia Studio

Slide 16

Slide 16 text

Step #1 Conceptual change

Slide 17

Slide 17 text

Work together Design Dev Product 17

Slide 18

Slide 18 text

Understand the rules behind the design And how it affect visual layer 18

Slide 19

Slide 19 text

Atomic Design Atoms Font Color Spacing Molecules Button Input Combo Box Organisms Search Box Table Date Picker

Slide 20

Slide 20 text

Step #2 Design Tokens

Slide 21

Slide 21 text

Meaningful CSS Variables My green -> success My grey -> body font color $color-pink: #f36; $color-green: #09baa6; $color-yellow: #ffb631; $color-gray: #dee0e4; $color-success: $color-green; $color-warning: $color-yellow; $color-brand: $color-pink;

Slide 22

Slide 22 text

Meaningful CSS Variables $xxs: 4px; $xs: 8px; $s: 16px; $m: 24px; $l: 32px; $xl: 48px; $xxl: 64px;

Slide 23

Slide 23 text

Utilities CSS classes $sizes: (xxs:$xxs, xs:$xs, s:$s, m:$m, l:$l, xl:$xl, xxl:$xxl); @each $size, $value in $sizes { .u-m-#{$size} { margin: #{$value}; } .u-m-#{$size} { margin: #{$value}; } .u-mt-#{$size} { margin-top: #{$value}; } .u-mr-#{$size} { margin-right: #{$value}; } .u-mb-#{$size} { margin-bottom: #{$value}; } .u-ml-#{$size} { margin-left: #{$value}; } .u-mx-#{$size} { margin-left: #{$value}; margin-right: #{$value}; } .u-my-#{$size} { margin-top: #{$value}; margin-bottom: #{$value}; } ...

Slide 24

Slide 24 text

Utilities CSS classes I have a text with small margin

Slide 25

Slide 25 text

What is the best way to define these variables? It doesn’t matter - any technique that works for you ▪ CSS-in-JS ▪ SASS Variables ▪ React Components (like , )

Slide 26

Slide 26 text

No more ‘one ofs’ You have a signed contract with designers 26

Slide 27

Slide 27 text

Step #3 Define Visual Components

Slide 28

Slide 28 text

Seperate Your Visual Layer Let’s look on some example 28

Slide 29

Slide 29 text

class List extends Component { componentDidCatch(error, info) { redirectToErrorPage(error, info); } render() { const { items, user } = this.props; reportMetrics(`items rendered`); const showDelete = isAuthorised(user); return (
    {items.map((item) => (
    { item.type === 'text' ? :

Slide 30

Slide 30 text

class List extends Component { componentDidCatch(error, info) { redirectToErrorPage(error, info); } render() { const { items, user } = this.props; reportMetrics(`items rendered`); const showDelete = isAuthorised(user); return (
    {items.map((item) => (
    { item.type === 'text' ? :

Slide 31

Slide 31 text

class List extends Component { componentDidCatch(error, info) { redirectToErrorPage(error, info); } render() { const { items, user } = this.props; reportMetrics(`items rendered`); const showDelete = isAuthorised(user); return (
    {items.map((item) => (
    { item.type === 'text' ? :

Slide 32

Slide 32 text

class List extends Component { componentDidCatch(error, info) { redirectToErrorPage(error, info); } render() { const { items, user } = this.props; reportMetrics(`items rendered`); const showDelete = isAuthorised(user); return (
    {items.map((item) => (
    { item.type === 'text' ? :

Slide 33

Slide 33 text

class List extends Component { ... render() { ... return (
    {items.map((item) => (
    { item.type === 'text' ? : } { showDelete && deleteItem(item)}> Delete }
    ))}
)

Slide 34

Slide 34 text

class List extends Component { ... render() { ... return (
    {items.map((item) => (
    { item.type === 'text' ? : } { showDelete && deleteItem(item)}> Delete }
    ))}
)

Slide 35

Slide 35 text

class List extends Component { ... render() { ... return (
    {items.map((item) => (
    { item.type === 'text' ? : } { showDelete && deleteItem(item)}> Delete }
    ))}
)

Slide 36

Slide 36 text

Let’s start Separate between design system and application code 36

Slide 37

Slide 37 text

import React, { Component } from 'react'; import redirectToErrorPage from "./errors" class ErrorBoundary extends Component { componentDidCatch(error, info) { redirectToErrorPage(error, info); } render() { return this.props.children; } } ErrorBoundary Parent Component

Slide 38

Slide 38 text

Metrics Higher Order Component

Slide 39

Slide 39 text

const metrics = (metric, WrappedComponent) => class MetricReport extends Component { render() { reportMetrics(metric); return ; } }; Metrics Higher Order Component

Slide 40

Slide 40 text

Render Props

Slide 41

Slide 41 text

class List extends Component { render() { const { items, itemRenderer } = this.props; return (
    {items.map((item, index) => itemRenderer(item, index))}
) } } export default List; Render Props

Slide 42

Slide 42 text

export const Item = ({ item }) => { return item.type === 'text' ? : }; Item code is part of Library

Slide 43

Slide 43 text

Application List const ItemsList = (props) => { ... return ( ); }; export default metrics('items rendered', ItemsList);

Slide 44

Slide 44 text

Application List const itemRendererCreator = (showDelete, onItemDelete) => (item) => { return
{ showDelete && onItemDelete(item)}> Delete }
}; const ItemsList = (props) => { const { items, user } = props; const showDelete = isAuthorised(user); const itemRenderer = itemRendererCreator(showDelete, deleteItem); return (

Slide 45

Slide 45 text

Result

Slide 46

Slide 46 text

Customization? How to make our component reusable 46

Slide 47

Slide 47 text

Customizing Visual Components Styles Props Render

Slide 48

Slide 48 text

Customizing Visual Components Styles Props Render

Slide 49

Slide 49 text

Customizing Visual Components Styles Props Render

Slide 50

Slide 50 text

Customizing Visual Components Styles Props Render

Slide 51

Slide 51 text

51 Not every shared component should be part of the design library

Slide 52

Slide 52 text

Step #4 Shared Library

Slide 53

Slide 53 text

webpack.config.js module.exports = { … output: { path: path.resolve(__dirname, './dist/lib'), filename: 'index.js', library: 'MyDesignSystem', libraryTarget: 'commonjs' },

Slide 54

Slide 54 text

webpack.config.js module.exports = { … output: { path: path.resolve(__dirname, './dist/lib'), filename: 'index.js', library: 'MyDesignSystem', libraryTarget: 'commonjs' },

Slide 55

Slide 55 text

package.json { "name": "MyDesignSystem", "version": "1.0.0", "description": "Sample Design System lib", "main": "dist/lib/index.js", "scripts": { ... },

Slide 56

Slide 56 text

package.json { "name": "MyDesignSystem", "version": "1.0.0", "description": "Sample Design System lib", "main": "dist/lib/index.js", "scripts": { ... },

Slide 57

Slide 57 text

webpack.config.js const nodeExternals = require('webpack-node-externals'); module.exports = { ... output: { ... }, externals: [nodeExternals()], ... }

Slide 58

Slide 58 text

Linking Repository $ cd ~/workspace/my-app $ npm link ../shared-lib

Slide 59

Slide 59 text

Version Management

Slide 60

Slide 60 text

Version Management with semantic-release package, releases are handled by commit messages. Examples: “fix(button): change over color“ => Patch Release “major(button): change property name“ => Major Release And you can also integrate it into your CI...

Slide 61

Slide 61 text

Step #5 Sharing and Visibility

Slide 62

Slide 62 text

If a tree falls in a forest and no one is around to hear it, does it make a sound?

Slide 63

Slide 63 text

Website A simple static website that includes: - Design Principles - What resources provided - Real live components

Slide 64

Slide 64 text

Storybook is a UI component development environment Allows you to define ‘stories’ for your components Generate static website with live components

Slide 65

Slide 65 text

Getting Started > cd my-shared-lib > npx -p @storybook/cli sb init > npm run storybook

Slide 66

Slide 66 text

Static Site Script to publish storybook as a static site is already added to your project "scripts": { … "build-storybook" : "build-storybook" }, package.json

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

What is a story? Each story represent one state But it is all up to you ▪ Render one component ▪ Combine few states for comparison ▪ Build a form

Slide 69

Slide 69 text

Let’s now add a story import React from 'react'; import { storiesOf } from '@storybook/react '; import { action } from '@storybook/addon-actions '; import { Button } from '../index'; storiesOf('Button', module) .add('with default theme and some text' , () => ( Hello Button )) .add('with green theme' , () => ( Hello Button )) stories/button.stories.js

Slide 70

Slide 70 text

Let’s now add a story import React from 'react'; import { storiesOf } from '@storybook/react '; import { action } from '@storybook/addon-actions '; import { Button } from '../index'; storiesOf('Button', module) .add('with default theme' , () => ( Hello Button )) .add('with green theme' , () => ( Hello Button )) stories/button.stories.js

Slide 71

Slide 71 text

Default is nice but ... By default Storybook arrive very thin. To add functionality need to enable some add-ons

Slide 72

Slide 72 text

Recommended Add-on Info - generate readme for each component Knobs - allow the user to edit in live mode Options - control the storybook default UI settings

Slide 73

Slide 73 text

React components for the Carbon Design System http://react.carbondesignsystem.com

Slide 74

Slide 74 text

React components for the Carbon Design System http://react.carbondesignsystem.com

Slide 75

Slide 75 text

React components for the Carbon Design System http://react.carbondesignsystem.com

Slide 76

Slide 76 text

React components for the Carbon Design System http://react.carbondesignsystem.com

Slide 77

Slide 77 text

Code as source of truth Convert React to sketch https://github.com/airbnb/react-sketchapp Convert HTML to sketch https://github.com/brainly/html-sketchapp

Slide 78

Slide 78 text

Visual Tests as part of your CI /CD

Slide 79

Slide 79 text

Design Ops? Tools and processes for managing and scaling the design workflow 79

Slide 80

Slide 80 text

Design Ops Tools for design, collaboration, developer hands off Assets management Training and onboarding Research & user testing [ Program managers ]

Slide 81

Slide 81 text

No content

Slide 82

Slide 82 text

Useful links ▪ Design Systems: ▫ https://www.carbondesignsystem.com ▫ https://www.lightningdesignsystem.com ▫ https://material.io/design/introduction/# ▪ Extra reading: ▫ https://uxdesign.cc/can-design-systems-fix-the-relationship-between-designers-developers-eb12fc9329ab ▫ https://medium.com/@nthgergo/lessons-learned-from-working-on-a-design-system-as-an-engineering-mana ger-2f199cd4aac2 ▫ http://bradfrost.com/blog/post/atomic-web-design/ ▫ https://www.designbetter.co/design-systems-handbook/introducing-design-systems ▫ https://medium.com/amplify-design/operationalizing-design-operations-7846a23bc99b 82

Slide 83

Slide 83 text

Thanks!! Any questions? You can find me at [email protected] www.linkedin.com/in/yael-oshri-balla-6b56686 83