What is a design system? Is it just hype?

A design system is an amorphous thing. One definition I like, and there are several (1, 2), is that it's an ecosystem of tools, guidelines, and shared values and principles that helps teams more efficiently ship consistent design (3). Similar to how different ecosystems emerge from the interactions of its communities, a design system varies from one business to the next, according to the needs and interactions of its teams. With that in mind, it's just not possible to define a specific set of artifacts that should make up every design system, nor should we try to.

At core, a design system allows us to manage the complexity of building user interfaces by establishing a shared, global context for design.

How we build web applications is changing. With the shift from waterfall to Agile practices, the componentization of React, Vue and Angular javascript frameworks, and the growing popularity of micro frontends, we are increasingly building piecemeal instead of in whole pages at a time (4). The fragmentation creates a need for practices that manage the "big picture" by acting as a Single Source of design Truth. A shared global context for design not only helps ensure a consistent user experience, but also improves team efficiency. By sharing design artifacts we avoid "reinventing the wheel", and because design and code reuse can result in significant time savings, we want to set the stage for as much reuse as possible. In short, design systems are not just hype, but an increasingly useful way of managing the complexity intrinsic to how we build software today.

Examples of design systems

What should be part of a design system ultimately depends on the size and permanence of the team, the number and maturity of the applications consuming the design system, and the needs of the business. A few examples:

Ahead I will look at design systems from the developer’s perspective and consider what artifacts can be built to support a design system, make recommendations for how to build them, and describe how to get started. While developers should be involved in all aspects of setting up a design system, the pieces that would specifically need to be coded are 1) a component library, 2) design tokens, and 3) a documentation website. Keep in mind that these three things are just a few of the possible pieces that can make up your business' design system.

1️⃣ Component library / UI library / component explorer

A component library is a common first step towards establishing a design system. A component library consists of a core set of reusable components that can be shared broadly. The components should only be concerned with presenting the UI and should not contain any business logic. Ideally the library enables the simulation of all possible states a component might take in the application. A component library also serves as a "workshop" (5) where developers can build, test, and iterate on components in isolation.

Tools: Storybook, Pattern Lab, Fractal (Storybook is the industry standard for component libraries)

Tested (required)

Because design systems are a single source of design truth they can also be a single point of failure. You’ll want to set up an automated test suite to prevent breaking changes and regressions. Standard unit tests are not effective for that purpose, since most components contain little logic and code snapshots are not effective for detecting visual regressions.

Instead, prefer to set up an automated visual test suite that can assert that a component appears visually as expected. There are a number of tools that can help with this, their main difference being whether they do a 1:1 pixel comparison (more brittle), or not (6).

An even more robust visual test setup also generates and tests all variants of a component a.k.a cartesian components (7) to ensure all possible visual states are covered. Finally, judicious use of an E2E testing tool for interaction testing of some components might also be helpful for interactive components, e.g. tabs and accordions.

Tools:
Visual testing: jest-image-snapshot, Chromatic, Applitools
Cartesian components: Storybook Cartesian
Interaction testing: CypressJS

Versioned (required)

To consume the component library in another application it should be packaged, versioned, and distributed via a package manager. There are two approaches to versioning a component library. The first is to version it globally where every commit increments the version number. The second is to package and version each component individually, enabling more granular adoption of updated components. The latter requires more upfront setup however. For either approach, each new release should follow SemVer and have release notes. Keep in mind that some consider color, font and spacing to be a breaking or major change (8).

Self-documenting (required)

By all accounts self-documentation is essential for ensuring that the design system remains relevant. Tools like Storybook can auto-generate basic component documentation from code comments.

Accessible (required)

Ensure that the foundations of your application are accessible by baking it into your component library. This can be done by basing components off an existing, accessibly designed component library like Reakit. Helpfully, Storybook has an accessibility add-on that shows the accessibility level of DOM elements, what rules are violated, and what rules pass.

Exportable (nice-to-have)

Ideally we would be able to export the components from the library to Sketch, InVision, or Figma so that designers could sync and use the latest components in their designs. Airbnb created a tool, React Sketch.app, that could be used for this purpose, but it is unclear what, if any, similar flows are available for InVision or Figma.

Interactive (nice-to-have)

The ability to dynamically set properties and design tokens used by a component make it easier to develop and test components. Storybook enables this through its knobs addon.

2️⃣ Design tokens

Design tokens are entities that store design decisions. They are a "set of core design properties of an application" (9), such as typefaces, colors, and spacing, that are stored as key/value pairs. Design tokens typically follow a naming convention, e.g. t-shirt sizes xl, l, m, s, xs, for numeric tokens (10), and descriptions like "primary, secondary, brand, generic, light and dark" for colors, that make it easy to tweak exact values later.

Design tokens can not only be used for storing information, but also for conveying it (9). For example, in addition to a key of grayDark and a value of #767676, metadata can be stored on the token that adds context about its usage

{
    colour: {
        grayDark: {
            value: "#767676",
            type: "border", // elsewhere in a documentation site, we can filter tokens for the type, "border" and display them together
            group: "mono" // elsewhere in the ui library, we can filter and create a theme with only the "mono" values
        },
    }
}

Finally, two levels of design tokens can be created. A global set with all the available design options, and a component-level set with the design decisions (9). The component level tokens define the allowable subset of global tokens that should be used for a particular component.

Tools: Theo, Style Dictionary, Design Tokens (not available yet), or a plain ol’ javascript object

Exportable (required)

The ability to export design tokens for use throughout the product(s), including in the format required by the component library is imperative. If the tokens need to be used on multiple platforms, e.g. web, android, and iOS, tools like Theo can be useful for facilitating conversion to these formats. Design tools like InVision and Sketch enable export of tokens into different formats.

Available (required)

All team members should be able to easily lookup the global set of tokens used by the application. If metadata, such as comments, type, and group information is provided, it can be used for organizing and filtering tokens in a documentation site (9).

Synced (nice-to-have)

Setting up "integrations" between design and development tools that make token export and incorporation into component libraries more efficient can accelerate the design process by uncovering problems more quickly. Here are couple ideas:

  1. Store tokens in a format like markdown or YAML that is easy to read and edit by the whole team.
  2. Use scripts and git hooks to automate syncing from design to development tools. Libraries like figmagic, for example, can be added to a development process to generate raw token output in code from living Figma documents. Unfortunately, integrations that directly sync tokens between design tools like InVision and development tools like GitHub are not yet available (11).

3️⃣ Documentation site / user manual

A documentation site acts as the entry point and source of truth for the UI. It can include:

  • Styles: colours, typography, icons, and anything that helps define how the brand is applied to the UI
  • Layout: spacing and grid system
  • Components: component API documentation, usage examples, code snippets, common component patterns (organisms), and implementation guidelines to assist component usage such as when and where a component should be used
  • Content: voice and tone guidelines
  • UI governance model: how the team will collaborate together to build and maintain the UI

Tools: Styleguidist, InVision DSM, zeroheight, or a custom static website, e.g. Gatsby/MDX/Netlify

Contributable (required)

Provide templates, boilerplate and usage examples so that others can easily add their own documentation. Use familiar writing formats such as markdown. For React, MDX allows you to include React components within a markdown file.

Available (required)

Everyone working on the design system and applications consuming the design system needs to able to view the documentation at all times.

Versioned (nice-to-have)

Including version information on a documentation site is a boon to developers using older versions of a component library. The documentation site itself can be versioned and tied to a specific release of the component library, or another approach is to list changes to a component and the version they were made in, in documentation for that component itself.

How to start

Many design systems are created after the product is built. In that case, starting with an "interface inventory" of the existing application can provide insights about what should be added to the component library (4). Record every design instance including typography, colour, layout and, of course, the components. Using the inventory as a guide, decide on an initial subset of components to build. As a component is built, publish the work-in-progress in order to get feedback from stakeholders and iterate (4).

If, on the other hand, the design system precedes the product, draw on branding decisions to lay a the foundation of the design system with the smallest units of design: the design tokens and base HTML elements. As elements are combined to make components in the application (or in the mocks) and patterns start to emerge, consider extracting them to a component library.

For the design system itself, starting with an all-in-one, component, token, and documentation site monorepo is probably the easiest to manage. At the very least, you won't need to yarn link repositories. Monorepos can scale too. In fact, IBM moved their design system, Carbon, to a monorepo this year (12). After creating the repository, setting up the component library is the common next step, including establishing a CI pipeline for running automated tests.

Introducing components into an application is best done incrementally (4). There are two possible strategies: replacing one element throughout the entire application, or going section-by-section, replacing each element in a section before moving on to the next. The importance of doing this incrementally is to set a regular and maintainable cadence of adding a component to the component library, swapping it into the application, getting feedback, and iterating (4). Establishing a design system is a marathon not a sprint.

In conclusion

This review focussed on the basics of what a developer needs to know to start building a design system, specifically the component library, design tokens and documentation website. Ensuring that the system is adopted by the team(s) is another discussion. For a start, check out Brad Frost's post on "A design system governance process". These two aspects of a design system, its governance and the artifacts developers create along the way, are both necessary for ensuring the success of a design system project within an organization.

To learn more about design systems, check out our other blog post, What is a design system?

References

  1. https://publication.design.systems/distilling-how-we-think-about-design-systems-b26432eefef9
  2. https://medium.com/eightshapes-llc/defining-design-systems-6dd4b03e0ff6
  3. https://medium.com/eightshapes-llc/a-design-system-isn-t-a-project-it-s-a-product-serving-products-74dcfffef935#.4umtnfxsx
  4. "Building Design Systems: Unify User Experiences through a Shared Design Language" Sarrah Vesselov, Taurie Davis
  5. https://blog.hichroma.com/storybook-vs-styleguidist-2bd93d6dcc06
  6. https://storybook.js.org/docs/testing/automated-visual-testing/#libraries-and-services-with-storybook-integration
  7. https://medium.com/@jondot/boost-your-design-system-with-storybook-cartesian-ac5e48c27d9c
  8. https://medium.com/eightshapes-llc/visual-breaking-change-in-design-systems-1e9109fac9c4
  9. https://badootech.badoo.com/design-tokens-beyond-colors-typography-and-spacing-ad7c98f4f228
  10. https://rangle.io/blog/mixin-design-tokens/
  11. https://uxdesign.cc/design-tokens-for-dummies-8acebf010d71
  12. https://medium.com/carbondesign/carbon-is-moving-to-a-monorepo-c6bfcbe87de0