Building Consistent Cross-Platform Interfaces

A presentation at Codemotion Amsterdam in April 2019 in Amsterdam, Netherlands by Danny Banks

Slide 1

Slide 1

Building Consistent Cross-Platform Interfaces

Slide 2

Slide 2

https://bit.ly/codemotion-2019-cross-platform https://bit.ly/codemotion-2019-cross-platform-pdf @dbanksdesign

Slide 3

Slide 3

Slide 4

Slide 4

Slide 5

Slide 5

Consistent experiences help users build trust with the organization. Each interaction is part of the overall user experience with a company. If the user experience isn’t consistent across channels, users will question the organization’s credibility. - Jakob Nielsen Cross Channel Consistency

Slide 6

Slide 6

Consistent ≠ Exact

Slide 7

Slide 7

Be a good platform citizen

Slide 8

Slide 8

Slide 9

Slide 9

Slide 10

Slide 10

Design Tokens

Slide 11

Slide 11

Design tokens are the visual design atoms of the design system — speci cally, they are named entities that store visual design attributes - Lightning Design System

Slide 12

Slide 12

Design tokens are variables that codify every aspect of a design in a platform-independent format that is readable by both humans and machines. - Elliot Dickison, Amazon

Slide 13

Slide 13

Cr Tp Ic Color Typography Iconography Mn Dm Ev Motion Dimension Elevation

Slide 14

Slide 14

  1. Canonical

Slide 15

Slide 15

primary brand color scss $color-brand-primary-base: #0fb7b0; iOS/Objective-C UIColor *brandPrimaryBase = [UIColor colorWithRed:0.06f green:0.72f blue:0.69f alpha:1.00f]; Android Resource XML <color name=”color_brand_primary_base”>#ff0fb7b0</color>

Slide 16

Slide 16

  1. Agnostic

Slide 17

Slide 17

Slide 18

Slide 18

  1. Structured

Slide 19

Slide 19

Kingdom Phylum Class Order Family

Slide 20

Slide 20

time color size border background font button alert overlay danger success warning

Slide 21

Slide 21

  1. Relational

Slide 22

Slide 22

color.core.teal.100 #0fb7b0 color.brand.primary.base color.core.teal.100 color.background.button color.brand.primary.base color.font.link color.brand.primary.base

Slide 23

Slide 23

color.core.orange.100 #fa953c color.brand.primary.base color.core.orange.100 color.background.button color.brand.primary.base color.font.link color.brand.primary.base

Slide 24

Slide 24

color.background.button color.brand.primary.base color.core.teal.100 #0fb7b0 color.core.purple.100 #6a5096 color.brand.primary.base color.core.teal.100 color.brand.secondary.base color.core.purple.100 color.font.link color.brand.secondary.base

Slide 25

Slide 25

Design Options Design Decisions

Slide 26

Slide 26

Core color palette Text color palette Specific uses grey 140 #191926 base grey-120 input grey 120 #252535 secondary grey-80 heading-1 text-secondary grey 100 #2e2e46 tertiary grey-60 nav-item text-secondary grey 80 #48485e grey 60 #81818e grey 40 #c2c2cc grey 20 #dadae6 grey 10 #f2f2f7 disabled-input text-base text-tertiary

Slide 27

Slide 27

Consistent Resilient Flexible

Slide 28

Slide 28

Slide 29

Slide 29

JSON { “color”: { “core”: { “grey”: { “20”: “#f3f1f1”, “40”: “#888888”, “60”: “#4d4d4d”, “80”: “#323232”, “100”: “#262626” } } } } YAML color: core: grey: 20: “#f3f1f1” 40: “#888888” 60: “#4d4d4d” 80: “#323232” 100: “#262626”

Slide 30

Slide 30

{ … } Transform Format CSS { … } Transform Format Objective C

Slide 31

Slide 31

Custom Build Script Eight Shapes YAML + custom build script FirefoxUX Design Tokens Nested JSON objects + custom build script

Slide 32

Slide 32

Theo JSON, JSON5, or YAML based token les CLI as well as node module based Transforms and formats with customization Has a great community

Slide 33

Slide 33

Theo # aliases.yml aliases: primary_color: value: “#0070d2” # buttons.yml props: button_background: value: “{!primary_color}” imports: - ./aliases.yml global: type: color category: buttons const theo = require(‘theo’); theo .convert({ transform: { type: ‘web’, file: ‘buttons.yml’ }, format: { type: ‘scss’ } }) .then(scss => { // $button-background: rgb(0, 112, 210); });

Slide 34

Slide 34

Style Dictionary amzn.github.io/style-dictionary

Slide 35

Slide 35

con g.json 1. { 2. “source”: [“properties/**/*.json”], 3. “platforms”: { 4. “web”: { 5. “transforms”: [“attribute/cti”,”name/cti/kebab”,”color/hex”], 6. “buildPath”: “dist/web/”, 7. “files”: [{ 8. “destination”: “_variables.scss”, 9. “format”: “scss/variables” 10. }] 11. }, 12. “android”: { 13. “transformGroup”: “android”, 14. “buildPath”: “dist/android/”, 15. “files”: [{ 16. “destination”: “style_dictionary_colors.xml”, 17. “format”: “android/colors” 18. }], 19. “actions”: [“copyImages”] 20. } 21. } 22. }

Slide 36

Slide 36

Design Token File 1. { 2. “size”: { 3. “font”: { 4. “small” : { “value”: 0.75 }, 5. “medium”: { “value”: 1 }, 6. “large” : { “value”: 1.25 }, 7. “xl” : { “value”: 1.75 }, 8. “xxl” : { “value”: 2.5 }, 9. “base” : { 10. “value”: “{size.font.medium.value}”, 11. “comment”: “All about that base” 12. }, 13. “heading”: { 14. “1”: { “value”: “{size.font.xxl.value}” }, 15. “2”: { “value”: “{size.font.xl.value}” } 16. } 17. } 18. } 19. }

Slide 37

Slide 37

Building the Style Dictionary 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. const StyleDictionary = require(‘style-dictionary’); // If you want to add custom transforms or formats StyleDictionary.registerTransform({ // … }); // Same as running style-dictionary build —config config.json StyleDictionary.extend(‘config.json’).buildAllPlatforms() // You can also pass in an object rather than a JSON file StyleDictionary.extend({ // … }).buildAllPlatforms()

Slide 38

Slide 38

Design Token File 1. { 2. “size”: { 3. “font”: { 4. “small” : { “value”: 0.75 }, 5. “medium”: { “value”: 1 }, 6. “large” : { “value”: 1.25 }, 7. “xl” : { “value”: 1.75 }, 8. “xxl” : { “value”: 2.5 }, 9. “base” : { 10. “value”: “{size.font.medium.value}”, 11. “comment”: “All about that base” 12. }, 13. “heading”: { 14. “1”: { “value”: “{size.font.xxl.value}” }, 15. “2”: { “value”: “{size.font.xl.value}” } 16. } 17. } 18. } 19. }

Slide 39

Slide 39

Output Web: SCSS 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. // variables.scss $size-font-small: 0.75rem; $size-font-base: 1rem; $size-font-large: 1.25rem; $size-font-xl: 1.75rem; $size-font-xxl: 2.5rem; $size-font-base: 1rem // All about that base $size-font-heading-1: 2.5rem; $size-font-heading-2: 1.75rem;

Slide 40

Slide 40

Output iOS: Static Constants 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. // StyleDictionarySize.m float float float float float float float float const const const const const const const const SizeFontSmall = 12.0f; SizeFontMedium = 16.0f; SizeFontLarge = 20.0f; SizeFontXl = 28.0f; SizeFontXxl = 40.0f; SizeFontBase = 16.0f; // All about that base SizeFontHeading1 = 40.0f; SizeFontHeading2 = 28.0f;

Slide 41

Slide 41

Output Android: Resource XML 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

<!— dimens.xml —> <dimen <dimen <dimen <dimen <dimen <dimen <dimen <dimen

name=”size_font_small”>12.00sp</dimen> name=”size_font_base”>16.00sp</dimen> name=”size_font_large”>20.00sp</dimen> name=”size_font_xl”>28.00sp</dimen> name=”size_font_xxl”>40.00sp</dimen> name=”size_font_base”>16.00sp</dimen> <!— All about that base —> name=”size_font_heading_1”>40.00sp</dimen> name=”size_font_heading_2”>28.00sp</dimen>

Slide 42

Slide 42

{ … } Transform Format CSS { … } Transform Format Objective C

Slide 43

Slide 43

  1. Transforms 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. const StyleDictionary = require(‘style-dictionary’); const Color = require(‘tinycolor2’); const _ = require(‘lodash’); StyleDictionary.registerTransform({ name: ‘color/rgbString’, type: ‘value’, matcher: (prop) => prop.attributes.category === ‘color’, transformer: (prop) => Color(prop.value).toRgbString() }); // #06a39c => rgb(6, 163, 156) StyleDictionary.registerTransform({ name: ‘name/snake’, type: ‘name’, transformer: (prop) => _.snakeCase(prop.path.join(’ ‘)) }); // size_font_base

Slide 44

Slide 44

  1. Formats 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. const StyleDictionary = require(‘style-dictionary’); const Handlebars = require(‘handlebars’); const fs = require(‘fs’); StyleDictionary.registerFormat({ name: ‘scss/variables’, formatter: (dictionary) => ( dictionary.allProperties.map((prop) => ( $${prop.name}: ${prop.value} )) ) }); StyleDictionary.registerFormat({ name: ‘scss/variables’, formatter: Handlebars.compile( fs.readFileSync(‘./myTemplate.hbs’) ) });

Slide 45

Slide 45

Demo Time! light base dark light base dark #40c7c2 #8f6ccc #0fb7b0 #06a39c #6a5096 #553c80 Button Button Heading 1 Heading 2 Heading 3

Slide 46

Slide 46

Resources Awesome Design Tokens Design Systems Handbook How to manage your Design Tokens with Style Dictionary design.systems #tool-style-dictionary #tool-theo #topic-design-tokens

Slide 47

Slide 47

Thank You!

Slide 48

Slide 48

Style Dictionary My Info amzn.github.io/style-dictionary dbanksdesign.com github.com/amzn/style-dictionary @dbanksdesign style-dictionary@amazon.com @dbanksdesign Slides https://bit.ly/codemotion-2019-cross-platform https://bit.ly/codemotion-2019-cross-platform-pdf