Design tokens can do more: create a single source of information about UI components

The term "design system" in IT has not surprised anyone for a long time. Companies systematize product design by inventing their own or using other people's tools to manage styles, patterns and components. 


Badoo is no exception: with our Cosmos design system, we support general design principles for four applications running on four platforms. 


image


One of the first and main things with which the work on creating a design system begins is tokens (or variables) that determine the values ​​of different entities of the system. 


How it works? For example, you have an application for two platforms. Instead of re-specifying the font size and style in the CSS file for each, you can store these values ​​in a JSON file, which can easily be converted to code for any platform. In the future, this file can be used in other projects with other code bases. 


Despite the potential of design tokens, in many companies their structure remains quite simple, which greatly limits the possibilities for their use. 


(Cristiano Rastelli), - Cosmos. , : . 


— , - Badoo .


, ( ) - , , — , (elevation).


: - - , .
, .


- ,


, - « ». .


, : Design System Playground. , , — . 


- — , «» :



, - designtokens.dev


, - Figma, Sketch Framer. , , . .


- -: , , , , , .


: . , , , - .


, - , :


  1. ;
  2. .

-


- .
- « — », . , , — ( ). 


( - ) (, , ). , , - .


, (, ), , , . , - . , - — . . .


Badoo -


, -, , . -.



- (Lifestyle Badge)


, , JSON- Lifestyle Badge ( Style Dictionary):


{
   "lifestylebadge": {
       "height": {
           "value": "34",
           "type": "size"
       },
       "border_radius": {
           "value": "17",
           "type": "size"
       },
       "padding": {
           "start": {
               "value": "{spacing.md.value}",
               "type": "size"
           },
           "end": {
               "value": "{spacing.md.value}",
               "type": "size"
           }
       },
       "icon_size": {
           "value": "{icon.size.md.value}",
           "type": "size"
       },
       "spacing_icon_text": {
           "value": "{spacing.xsm.value}",
           "type": "size"
       },
       "base": {
           "text_color": {
               "value": "{color.gray_dark.value}",
               "type": "color"
           },
           "background_color": {
               "value": "{color.gray_light.value}",
               "type": "color"
           }
       },
       "selected": {
           "text_color": {
               "value": "{color.white.value}",
               "type": "color"
           },
           "background_color": {
               "value": "{color.primary.value}",
               "type": "color"
           }
       }
   }
}

( , iOS, Android) ( (white label brands)).


, , , -:



Lifestyle Badge Android -


. , «» — — , , .


. Sketch- ( Sympli) , . - /, , . 


, - .



- (Action Sheet). (gravity)!


, , . 


  • - : , - /. , — , .
  • (, ) / (, ), JSON- . : !

- , .


-


- (Theo Style Dictionary) « — ». , - , .


, , , . , , . . , , , .



, - -, «/» («documentation/comment»). , -. documentation, comment, , : , - .


-:


{
   "actionsheet": {
       …
       "item": {
           "height": {
               "value": "48",
               "type": "size",
               "documentation": {
                   "comment": "Notice: this is the 'internal' size, the border will be added as extra"
               }
           },
           …
       }
   }
}

:



— «» ("type"). , . 


, :


{
   "color": {
       "primary": {
           "value": "{color.palette.purple_grape.value}",
           "type": "color"
       }
   },
   "icon": {
       "size": {
           "xsm": {
               "value": "10",
               "type": "size"
           }
       }
   },
   "tooltip": {
       "shadow": {
           "opacity": {
               "value": "0.08",
               "type": "opacity"
           }
       },
       "animation": {
           "timing_bounce": {
               "value": "0.9",
               "type": "time",
               "unit": "s"
           }
       }
   },
   "chat": {
       "bubble": {
           "relative_width": {
               "value": "0.8",
               "type": "ratio"
           }
       }
   },
   "actionsheet": {
       "gravity": {
           "value": "center",
           "type": "string"
       }
   }
}

«» . , XML- Android:



«» , Android


:



Android XML- /, "type"


: «» ("group"). , .



(, ). :



«»


, : «» ("color"), — «» ("alias"). , ( color-palette-purple-grave) , , isAlias.


:



- "type",


, . .



— - .


, «» ("group") , , ( ) .
- :


// color/xxx.json
{
    "color": {
        "primary": {
            "value": "{color.palette.purple_grape.value}",
            "type": "color",
            "group": "brand"
        },
        "generic_red": {
            "value": "{color.palette.pink_salmon.value}",
            "type": "color",
            "group": "generic"
        },
        "gray_dark": {
            "value": "#767676",
            "type": "color",
            "group": "mono"
        },
        "feature": {
            "verification": {
                "value": "{color.palette.blue_neon.value}",
                "type": "color",
                "group": "features"
            },
        },
        "provider": {
            facebook": {
                "value": "#4867aa",
                "type": "color",
                "group": "providers"
            },
            …
        },
        "others": {
            error": {
                "value": "{color.generic_red.value}",
                "type": "color",
                "group": "others"
            },
        }
    }
}

// icon.json
{
    "icon": {
        "size": {
            "xsm": {
                "value": "10",
                "type": "size",
                "group": "size"
            },
            "sm": {
                "value": "16",
                "type": "size",
                "group": "size"
            },
            "md": {
                "value": "22",
                "type": "size",
                "group": "size"
            },
            "lg": {
                "value": "30",
                "type": "size",
                "group": "size"
            },
            "xlg": {
                "value": "36",
                "type": "size",
                "group": "size"
            },
            "xxlg": {
                "value": "46",
                "type": "size",
                "group": "size"
            }
        },
        "jumbo-size": {
            "sm": {
                "value": "{brick.size.sm.value}",
                "type": "size",
                "group": "size"
            },
            "md": {
                "value": "{brick.size.md.value}",
                "type": "size",
                "group": "size"
            },
            "lg": {
                "value": "{brick.size.lg.value}",
                "type": "size",
                "group": "size"
            }
        }
    }
}

// spacing.json
{
    "spacing": {
        "xsm": {
            "value": "4",
            "type": "size",
            "group": "size"
        },
        "sm": {
            "value": "8",
            "type": "size",
            "group": "size"
        },
        "md": {
            "value": "12",
            "type": "size",
            "group": "size"
        },
        "lg": {
            "value": "16",
            "type": "size",
            "group": "size"
        },
        "xlg": {
            "value": "24",
            "type": "size",
            "group": "size"
        },
        "xxlg": {
            "value": "32",
            "type": "size",
            "group": "size"
        },
        "gap": {
            "value": "{spacing.lg.value}",
            "type": "size",
            "group": "size"
        }
    }
}

Sass ( Sass maps, ):


$tokens-color-map: (
    providers: (
        provider-facebook: $token-color-provider-facebook,
    ),
    mono: (
        black: $token-color-black,
        gray-dark: $token-color-gray-dark,
        gray: $token-color-gray,
        gray-light: $token-color-gray-light,
        white: $token-color-white
    ),
    others: (
        error: $token-color-error,
    ),
    brand: (
        primary: $token-color-primary,
    ),
    generic: (
        generic-red: $token-color-generic-red,
    ),
    features: (
        feature-verification: $token-color-feature-verification
    ),
);
$tokens-icon-map: (
    size: (
        size-xsm: $token-icon-size-xsm,
        size-sm: $token-icon-size-sm,
        size-md: $token-icon-size-md,
        size-lg: $token-icon-size-lg,
        size-xlg: $token-icon-size-xlg,
        size-xxlg: $token-icon-size-xxlg,
        jumbo-size-sm: $token-icon-jumbo-size-sm,
        jumbo-size-md: $token-icon-jumbo-size-md,
        jumbo-size-lg: $token-icon-jumbo-size-lg
    ),
);
$tokens-spacing-map: (
    size: (
        xsm: $token-spacing-xsm,
        sm: $token-spacing-sm,
        md: $token-spacing-md,
        lg: $token-spacing-lg,
        xlg: $token-spacing-xlg,
        xxlg: $token-spacing-xxlg,
        gap: $token-spacing-gap
    ),
);
...

:




Sass-, -


, / , — , , , . ., Sass- , , .


Sass- .


. . -.
CSS/Sass. , , JavaScript:



- , , "group"


— CSS--JS. (, ) / « — », -.
"group" TypeScript-. :


declare namespace Tokens {
    namespace Color {
        enum Providers {
            PROVIDER_FACEBOOK = 'provider-facebook',
        }
        enum Mono {
            BLACK = 'black',
            GRAY_DARK = 'gray-dark',
            GRAY = 'gray',
            GRAY_LIGHT = 'gray-light',
            WHITE = 'white'
        }
        enum Others {
            ERROR = 'error',
        }
        enum Brand {
            PRIMARY = 'primary',
        }
        enum Generic {
            GENERIC_RED = 'generic-red',
        }
        enum Features {
            FEATURE_VERIFICATION = 'feature-verification'
        }
        type Color = Providers | Mono | Others | Brand | Generic | Features;
    }
    namespace Icon {
        enum Size {
            XSM = 'xsm',
            SM = 'sm',
            MD = 'md',
            LG = 'lg',
            XLG = 'xlg',
            XXLG = 'xxlg',
            JUMBO_SM = 'jumbo-sm',
            JUMBO_MD = 'jumbo-md',
            JUMBO_LG = 'jumbo-lg'
        }
    }
    namespace Spacing {
        enum Size {
            XSM = 'xsm',
            SM = 'sm',
            MD = 'md',
            LG = 'lg',
            XLG = 'xlg',
            XXLG = 'xxlg',
            GAP = 'gap'
        }
    }
}
export default Tokens;

TypeScript- ( IDE).
- , , . , : font-family, font-size, line-height font-weight. 


-, « H1»? , . , , / ? 


, , , .



:


  • - — , .
  • - -, UI-.
  • - . , « — ».

, :


  • -;
  • ;
  • Sass, JavaScript, TypeScript;
  • ( ) .

, -. - . , ( ) , -, , .


. , , , , .


!


P. S. , -, - , , . W3C, . , Badoo -, : How to manage your Design Tokens with Style Dictionary.


All Articles