Building Consistent Cross-Platform Interfaces

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

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

Consistent ≠ Exact

Be a good platform citizen

Design Tokens

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

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

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

  1. Canonical

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>

  1. Agnostic

  1. Structured

Kingdom Phylum Class Order Family

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

  1. Relational

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

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

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

Design Options Design Decisions

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

Consistent Resilient Flexible

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”

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

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

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

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); });

Style Dictionary amzn.github.io/style-dictionary

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. }

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. }

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()

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. }

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;

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;

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>

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

  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

  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’) ) });

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

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

Thank You!

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