• Stars
    star
    537
  • Rank 82,293 (Top 2 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created about 7 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

πŸ‘©β€πŸŽ¨ Access your design tokens with ease

πŸ‘©β€πŸŽ¨
Design System Utils

npm npm bundle size (minified + gzip) Travis CI Build PRs Welcome

Design System Utils is a micro framework that standardises your design-system tokens & provides helpful utility functions to access the information. It can be used with styled-components, emotion, glamorous or any other CSS-in-JS framework.

Install

yarn add design-system-utils

# or

npm install --save design-system-utils

Size

$ size-limit

  build/cjs.js
  Package size: 814 B
  Size limit:   1 KB

  es/index.js
  Package size: 806 B
  Size limit:   1 KB

  With all dependencies, minified and gzipped
πŸ€“ Table of contents

Usage

First create your design system file, this contains all your design tokens that your app or site will use; things like font-sizes, color palette, spacing etc (kind of like a Sass/Less variables file).

For example you can create a top-level directory named tokens, theme or designsystem, and add an index.js inside, like so:

./tokens
└── index.js

A simple version of a tokens file with Design System Utils:

// ./tokens/index.js
import DesignSystem from 'design-system-utils'

// your design tokens object goes here, see below for further details
const designTokens = {...}

export default new DesignSystem(designTokens)

Setup

The "shape" and structure of your design tokens object can actually be anything you want, however, if you want to make use of the shortcut/helper methods like tokens.fontSize|bp|z|color|brand|spacing etc, there is a particular shape that your data will need to follow, see below:

(πŸ€” the below code snippet includes some psuedo types for the values that occur in the different parts of the tokens object)

{
  type: {
    // this should be set as a px value if you have `options.fontSizeUnit` set
    // to 'rem' or 'em' so that the lib can convert the values properly
    baseFontSize: '' // string,

    // used with `tokens.fs('size')` or `tokens.fontSize('size')`
    sizes: {
      key: '' // <number | string>,
    },
  },

  // Color palette
  // Each object needs to have the same shape
  // Each color object needs a `base` value to be the default
  // Have as many color objects as you like
  colors: {
    // Used with `ds.color('colorName')`
    colorPalette: {
      colorName: {
        base: '' // <string>, // base is the default
      },
    },

    // Used with `ds.brand('colorName)`
    brand: {
      colorName: '' // <string>, base is the default
    }
  },

  // Breakpoints
  // Used with `ds.bp()`
  // Keys can be anything you like
  // Have as many breakpoints as you like
  // Values can be use any unit you like
  breakpoints: {
    key: '' // <number | string>,
  },

  // Z-index
  // Used with `ds.z()`
  zIndex: {
    key: 10 // <number>
  },

  // Spacing
  // Used with `ds.spacing()` or `ds.space()`
  spacing: {
    scale: [] // <array>[<number | string>, ...], <object>
  },
}

Below is an excerpt from the example design-system. See a more complete version in the /example directory or some that are used in the design-system-utils tests: 1 & 2.

const designTokens = {
  type: {
    baseFontSize: '20px',

    sizes: {
      xs: '16px',
      s: '20px',
      base: '30px',
      m: '36px',
      l: '42px',
      xl: '50px',
      xxl: '58px',
    },

    fontFamily: {
      system:
        '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans"',
      sans: '"Helvetica Neue", Helvetica, Arial, sans-serif',
      serif: 'Georgia, "Times New Roman", Times, serif',
      mono: 'Menlo, Monaco, "Courier New", monospace',
    },

    lineHeight: {
      headings: 1.1,
    },

    fontWeight: {
      normal: 300, // Useful to set here if using anything other than `normal`
      bold: 'bold', // Useful to set here when bold webfonts come as 400 font-weight.
      headings: 'bold', // instead of browser default, bold
    },
  },
}

Initialise the design system framework

// myDesignSystem.js
import DesignSystem from 'design-system'
const designTokens = {...}
export default new DesignSystem(designTokens)

Accessing the design system data in yourΒ app

To access your design system, you just need to import it to the current file, like so:

import tokens from './tokens' // assuming you exported `default` from your design system file

Here is a very simple component using styled-components and some values from the tokens, you should be able to see how easy it is to pull information from the design system.

// Example using styled-components
import styled from 'styled-component'
import tokens from './tokens'

export const Box = styled.div`
  font-family: ${tokens.get('type.fontFamilyBase')};
  background-color: ${tokens.brand('primary')};
  margin: ${tokens.space(2)} 0;
`

Options

There is only one option that can be passed to your design system class, it relates to font-sizing:

// Use default options. do not convert the font-sizes to rems or ems
export default new DesignSystem(myDesignSystem)

// OR: with custom options
export default new DesignSystem(myDesignSystem, {
  // this is used to convert your `type.sizes` values from one unit to another
  // e.g. to convert all `px` sizes  to `rem`, set this option:
  fontSizeUnit: 'rem',
  // this means you can define values using px and use rems in your app
})

Basic API methods

tokens.get() - Get a token value

The tokens.get() function can be used to get any value from the design-system. Use object dot notation to find the value you need from your design system object.

// with the system setup, as above
tokens.get('lineHeight.headings') // 1.1
tokens.get('a.really.deeply.nested.value')

tokens.set() - Set a token value

The tokens.set() function can be used to set tokens values. This means you can overwrite existing items, or create new items that are specific to your application.

Like the .get() method, use object dot notation to find the value you need from your design system object.

This method uses dset under the hood, so please read the docs there for more info.

// with the system setup, as above
tokens.set('forms.inputBackground', '#fff')

// then use it later like so:
tokens.get('forms.inputBackground')

API helper methods

The helper methods make getting values much more simple.

tokens.fontSize() or tokens.fs() - Get font-size values

The tokens.fontSize() method is a short-hand for the tokens.get() method. It can be used to get a value from the type.sizes object.

The type.sizes object’s values can be formatted in a few ways:

  • as a string with any unit of measurement, e.g. s: '13px' / px, rem or em
  • as a template string using another function to calculate font-sizes, for example a modular-scale, e.g. ${ms(0, modularscale)}px. Note: this uses an external package, modularscale-js
// define some values// type.sizes object
sizes: {
  xs: '16px',
  s: '20px',
  base: '30px',
  m: '36px',
  l: '42px',
  xl: '50px',
  xxl: '58px',
},

// retrieve some values
tokens.fontSize('xl')
tokens.fs('xl') // `tokens.fs()` is a short-hand alias for `tokens.fontSize()`
tokens.fs('xl', true) // return font-size in px regardless of `option.fontSizeUnit` value

Modular scale

Note: v0.x.x had modular scale functionality built-in, in v1.x.x, this has been removed to reduce file-size for those that don't need a modular scale.

To make use of a modular scale, there are a few things that need to be done:

  • install a modular scale converter package, like modularscale-js
  • define your modular scale options outside of your design-system object
  • add the modular scale values to the type.sizes object
const modularscale = {
  base: [30],
  ratio: 1.5,
}

// design system
...
sizes: {
  xs: `${ms(-2, modularscale)}px`,
  s: `${ms(-1, modularscale)}px`,
}
...

Testing and remembering the values from your modular scale can be tricky, there are two options that can be used, either:

  • visit modularscale.com and enter your settings, you can then view all the type sizes on the scale you specified
  • or, add the below snippet to your code to print out the values of your scale:
const sizes = tokens.get('type.sizes')
Object.keys(sizes).forEach(item => {
  console.log(item, ':', sizes[item]) // e.g. `base : 20px`
})

Color palette

There are two possible ways to access color information: the color palette and the brand colors.

The color palette is intended to contain all the colors (and their shades) that your app will use, and the brand palette should contain the specific colors that your brand uses.

Two methods can be used to retrieve the values, these are: tokens.color() and tokens.brand(), below is what the data looks like for them:

colors: {
  // With a color palette like this:
  colorPalette: {
    bright: {
      base: '#F9FAFB',
      dark: '#F4F6F8',
      darker: '#DFE4E8',
    },

    dark: {
      base: '#212B35',
      light: '#454F5B',
      lighter: '#637381',
    },
  },

  // With a brand palette like this:
  brand: {
    red: '#e82219',
    deeporange: '#ff7200',
    orange: '#ff9500',
    green: '#c4d000',
    teal: '#1aa5c8',
    navy: '#0052da',
  }
},

tokens.color() - Get color palette values

The tokens.color() function gets values from the colorPalette object. It assumes every color has a base property and other properties for different shades of the same color. This is a short-hand for the tokens.get() function.

// Get values like this:
tokens.color('bright') // #F9FAFB - the `base` key is the default, so it is not needed
tokens.color('bright', 'dark')
tokens.color('background.extra.dark') // Accepts a path (in this case the second `variant` argument is ignored)

tokens.brand() - Get brand palette values

The tokens.brand() function gets values from the colors.brand object. This is a short-hand for the tokens.get() function.

// Get brand values like this:
tokens.brand('orange')
tokens.brand('pink')
tokens.brand('primary.blue') // it is possible to nest this object as much as you like

tokens.bp() - Get responsive breakpoint values

The tokens.bp() method is a short-hand for the tokens.get() method. It can be used to get a breakpoint from the breakpoints object.

tokens.bp('m')

tokens.z() - Get z-index values

The tokens.z() method is a short-hand for the tokens.get() method. It can be used to get a breakpoint from the zIndex object.

tokens.z('low')

tokens.spacing() or tokens.space() - Get spacing values

The tokens.spacing() method returns a value from your spacing.scale definition. The spacing data could either be an array, or an object.

  • If an array, it takes an index (number) for that array e.g. tokens.space(2). This variant adds px to the end of the string, this will be deprecated in v2.0.0.
  • If an object, it takes a key (string) for the item in that object e.g. tokens.space('m')

Array example:

scale: [0, 8, 16, 24, 32, 40]

tokens.spacing(2) // '16px'
// Note: `tokens.space(2)` can also be used

Object example:

scale: {
  s: '10rem',
  m: '100rem',
  l: '1000rem',
}

tokens.spacing('m') // '100rem'
// Note: `tokens.space('m')` can also be used

Calculations

The framework currently provides a few calculation functions, multiply, toPx and pxTo:

tokens.multiply()

tokens.multiply(10, 2) // 20

// you can pass in another value from the system
tokens.multiply(tokens.get('spacing.baseline'), 2)

// or just use the key from the system
// the initial value will always be run through `parseFloat()`
tokens.multiply('spacing.baseline', 2)

pxTo()

Converts px to rem or em

import { pxTo } from 'design-system-utils'
// pxTo(fontSize, baseFontSize, unit - 'rem'/'em')
pxTo(12, 20, 'rem') // 0.6rem
pxTo(12, 20, 'em') // 0.6em

toPx()

Converts rem or em value to px

import { toPx } from 'design-system-utils'
// toPx(fontSize, baseFontSize)
toPx('1.875rem', 16) // 30px
toPx('1.875em', 16) // 30px

parseUnit()

Parses a number and unit string, and returns the unit used

import { parseUnit } from 'design-system-utils'
parseUnit('1.875rem') // 'rem'
parseUnit('18px') // 'px'

Usage with Typescript

Typescript types and interfaces should be imported as named imports.

See all the type definitions in the types.ts file. Here are all the exported types that can be extended:

{
  System,
  SystemOptions,
  SystemBreakpoints,
  SystemZIndex,
  SystemFontSizes,
  SystemSpacing,
  SystemScale,
  SystemColorPalette,
  SystemBrandPalette,
  SystemType,
  SystemOptionalKey,
}

Below is an example where a new item (baseline) is added to the spacing object.

import DesignSystem, { System, SystemOptions, SystemSpacing } from '../index'

interface MySystemSpacing extends SystemSpacing {
  baseline: number
}

interface MySystem extends System {
  spacing: MySystemSpacing
}

const Tokens: MySystem = {
  ...
  ...

  spacing: {
    scale: [0, 8, 16, 24, 32, 40],
    baseline: 20,
  },
}

export default new DesignSystem<MySystem, SystemOptions>(Tokens)

Aliases

If you'd prefer to rename the above methods, or even add your own getter methods, to access your design tokens, it is very simple. See below for an example:

export tokens from './tokens' // import your design tokens

// create new alias functions

// this renames .bp()
export const breakpoints = bp => tokens.bp(bp)

// this adds a new alias that doesn't already exist in Design System Utils
export const fontWeights = weight => tokens.get('type.fontWeights')

// the aliases can also be for specific values
export const baseFontSize = ds1.get('type.baseFontSize')
export const brandPrimary = ds1.brand('red')

Then use them like so:

import { breakpoints, fontWeights, baseFontSize, brandPrimary } from './tokens'

breakpoints('m')
fontWeights('normal')

Take a look at alias.ts and alias.test.ts to see working examples and their usage.

Demo & examples

I created a demo on codesandbox.io, it includes examples of using the design-system utils with emotion, styled-components and glamorous. There is also a basic example here.

Licence

MIT Β© Zander Martineau

More Repositories

1

gatsby-theme-code-notes

A Gatsby theme for publishing code-related notes to your website
TypeScript
470
star
2

SublimeTextSetupWiki

Enable people to get started with Sublime Text 2 much more quickly
JavaScript
463
star
3

awesome-web-dev-resources

πŸ‘Œ My collection of go-to web development resources
224
star
4

Placeholders

Placeholder HTML & content (lorem ipsum) package for Sublime Text 2
143
star
5

trak.js

Universal analytics event tracking API
JavaScript
134
star
6

HTML5-Coda-Clips

A selection of HTML5 snippets for use in Panic's Coda web dev app
87
star
7

SimpleSharing

Twitter, Facebook, Google+, Instapaper & LinkedIn social link that do not rely on Javascript
CSS
56
star
8

webpack-recipes

πŸ†˜ A collection of webpack configurations
JavaScript
48
star
9

Otter

Otter is a self-hosted bookmark manager made with Next.js and Supabase with Mastodon integration.
TypeScript
47
star
10

react-design-system-boilerplate

At the moment this project is out-of-date and unmaintained. I hope to revisit it soon though... This is a boilerplate for you to create your own design system in React. It has everything setup to allow you to focus on what it is you care about: creating awesome, reusable components.
TypeScript
46
star
11

SublimeText3UserSettings

My personal Sublime Text 3 User Settings
43
star
12

notes.zander.wtf-gatsby

Notes on code. My memory bank.
TypeScript
40
star
13

Boost

Boost is now Kickoff, see adjacent link
CSS
38
star
14

xkcd-api

πŸ’ͺ CORS enabled version of the XKCD API
JavaScript
37
star
15

stitches-ui

A minimal implementation of Theme UI using Stitches
TypeScript
25
star
16

scriptable-widgets

JavaScript
24
star
17

snippet-generator

⚑ Sublime Text, Atom & VS Code snippet generator
JavaScript
24
star
18

ZM-Resources

List of all scripts & resources I use on a regular basis
23
star
19

Coda-Blackboard-Seestyles

Syntax highlighting themes for Coda
18
star
20

gatsby-starter-code-notes

JavaScript
17
star
21

prismic-reactjs-custom

This is an opinionated fork of prismic-reactjs that allows you to use custom React components instead of standard HTML tags
TypeScript
15
star
22

depdoc

Auto-generate markdown documentation using your package.json's dependencies
JavaScript
13
star
23

Choreographic-Grid

Not ready for prime-time yet, but I hope this could help solve lots of responsive content choreography problems
CSS
13
star
24

pinboard-chrome-extension

This Chrome extension improves the design and UX of Pinboard.in
CSS
12
star
25

zander.wtf-2020

πŸ‘± My personal website
CSS
11
star
26

SublimeText2UserSettings

My personal Sublime Text 2 User Settings
Ruby
11
star
27

SASS-Snippets

A collection of Sublime Text 2 snippets & functions to be used with SASS. Most snippets are to be used specifically with .scss
8
star
28

cloudflare-worker-scraper

Page Metadata Scraper with Cloudflare workers
TypeScript
7
star
29

notes.zander.wtf

TILs, snippetsβ€”my digital code garden 🌱
CSS
7
star
30

cloze-test

Simple Cloze test generator
JavaScript
6
star
31

zander.wtf-2019

πŸ‘± My personal website
JavaScript
6
star
32

Sketch-website-template

Responsive website design template for Sketch 3
6
star
33

pinboard-api

A free, CORS-enabled version of the Pinboard public feeds API
JavaScript
5
star
34

feeds.zander.wtf-svelte

My feeds, built with Svelte, Tailwind, Vite
Svelte
4
star
35

frontmatter-date-setter

JavaScript
4
star
36

alfred-npm-versions

Lookup the latest 15 versions for an npm package
JavaScript
4
star
37

zander.wtf-2017

My old personal portfolio and blog
CSS
4
star
38

programmers-clipboard

πŸ‘Œ Copy unicode characters to your clipboard for use in different programming languages: CSS, Javascript, HTML & plain text
JavaScript
4
star
39

refined-prismic

Browser extension that simplifies the Prismic interface and adds useful features
JavaScript
3
star
40

the-unit

Parses a number and unit string, and returns the unit used
JavaScript
3
star
41

react-npm-package

A base for an npm package that uses React, Vite, Storybook and Vitest
TypeScript
3
star
42

feeds.zander.wtf-nextjs

TypeScript
3
star
43

pinboard-api-cache

A free, CORS-enabled version of the Pinboard public feeds API, but with a one hour cache
JavaScript
3
star
44

rigel-vscode

Port of Rigel theme for VS Code
3
star
45

InteractionCheck.js

Prompt users if they have not interacted with your page for a given amount of time
JavaScript
3
star
46

front-end-vscode-extensionpack

A collection of extensions for working with Front-end Applications in VS Code
3
star
47

fish

My fish shell dotfiles
Shell
2
star
48

scrollObserver

Add class to element when a specific scroll value has been reached
JavaScript
2
star
49

isDateValid

Validate a date
TypeScript
2
star
50

zander.wtf

my site
XSLT
1
star
51

journal

A personal journalling app built with SvelteKit, Supabase & little bit of AI
Svelte
1
star
52

gh-release-experiments

1
star
53

coding-standards

Coding standards and resources
1
star
54

Stacey-Bundle

Textmate bundle for the brilliant Stacey CMS (http://staceyapp.com/)
1
star
55

social-homepage

My social homepage, MrMartineau.co.uk.
CSS
1
star
56

githubwatched

Simple app to show a user's watched & owned repos
JavaScript
1
star
57

zander-react-contentful

JavaScript
1
star
58

issue-templates

1
star
59

HTMLPrototype

My basis for HTML/PHP prototypes
JavaScript
1
star
60

mrmartineau

1
star
61

zander.wtf-after.js

experimental after.js version of my next.js website
JavaScript
1
star
62

gitmoji-alfred-snippets

Gitmoji snippets for Alfred
1
star
63

scripts

Shareable config scripts
JavaScript
1
star
64

grunt-filesizegzip

Grunt plugin to output file size information
JavaScript
1
star
65

raycast-extensions

TypeScript
1
star
66

rollup-routes-test

JavaScript
1
star
67

unsplash-search

Simple Unsplash search
JavaScript
1
star
68

CSSOff2013

My submission for the 2013 CSSOff competition. Unfortunately I was not able to finish due to lack of available time
CSS
1
star
69

rsstojson

Simple API to convert RSS feeds to JSON
TypeScript
1
star
70

KOglossaryLinks

KOglossaryLinks is a jQuery plugin that shows tooltips of glossary terms, from a JSON feed, when hovered (or tapped on touchscreen devices)
CSS
1
star
71

Boost-Snippets

Sublime Text 2 package for my Boost front-end framework
1
star