By Drew Loomer
Here at projekt202, we’ve spent a lot of time crafting design systems. We love them. They provide several tangible benefits. They enforce visual and interaction consistency and let software teams focus on tough problems instead of the small stuff.
They also help save time and money. Just by eliminating code redundancy, more than 20% of a developer's time can be regained. For a team of 100 developers, this means about $2,000,000 per year. There are also substantial savings in the time spent on design, not to mention the sizable monetary benefits of having a consistent experience across all user touchpoints.
In short, they’re a solid investment and a great way to visually unite disparate products.
They’re also very easy to build incorrectly.
As with many things in life (and especially software), there are an almost infinite number of ways to approach building a design system. It’s impossible to say what is definitively “the right way” to structure such a project; what makes sense for Project X may be wrong for Project Y. But after running a number of programs with clients, here are what we’ve found to be effective guidelines for building a design system.
First, what is a design system?
At a high level, a design system is a set of principles and UI component patterns that define how a product or set of products should look and behave. It highlights how and when to use each component, provides examples for how animations should behave, and defines accessibility targets. It can also include brand guidelines, such as how to integrate with existing standards and the proper voice and tone for content.
A design system should be derived from observing real user needs. Without research, the components designed will likely miss the mark. Keep in mind that the “users” of a design system are both the end-user as well as the design and development teams.
To be successfully adopted, an effective design system should include a working implementation of all components. That implementation could take many forms, but we’ll focus on building for the web. That means HTML/CSS/JS.
What should an implementation do?
Provide a functional set of UI components
These components don’t need to be exhaustive in their functionality, but they should lay the visual and interactive groundwork. This is the first step toward creating a “consistent look and feel” across an application or suite of applications. Include documentation for how and when to implement.
Follow UX best practices for accessibility
If this isn’t made a priority and baked into the implementation from the beginning, you’ll end up spending a lot of time making breaking changes to your code. The best way to satisfy accessibility in color and keyboard interaction is to write semantic markup. It’s amazing how little extra work it takes to make your components accessible if you use HTML the way it was designed to be used.
Enable faster development
Make your components easy for developers to understand and integrate. Allow for easier updates by properly versioning your code and storing it in a central repository. Additionally, offer multiple ways to consume the design system. Make it available to teams using package managers that make sense for your organization: private npm registry, Bower, NuGet, etc.
Encourage contribution and governance
Involve internal development teams. Run the design system implementation like an open source project. Allow for bug reports, feature requests and code submissions via pull requests. The long-term health of the implementation hinges on buy-in from your developers.
Allow for configuration
The components of a design system are simple building blocks that will likely be used many different ways. Allow for configuration of each component and provide a consistent API for interacting with them. For companies that resell their software, it’s important to also make it easy to theme or white label the design system. Reskinning a product with new brand colors should be as easy as changing a few SASS variables.
What should an implementation not do?
Don't make technology assumptions
How applications will integrate the design system today may change tomorrow. New pieces of software may be developed or acquired that operate completely differently from what currently exists. Just because your application is written using Rails doesn’t mean you should couple your design system to the Asset Pipeline. Make technology-agnostic architecture decisions to the degree that is possible.
Don't build for a specific framework or library
You'll regret it. Building on something like Angular or Ember would add significant file weight and would be functionality overkill for the low-level problems a design system aims to solve. Also, it would suffer from the same technology coupling issues as outlined above. Additionally, framework trends change and can be very polarizing. Stay above the fray. Consider providing secondary libraries that integrate the design system into particular frameworks if your organization has that need.
Don't solve only for best-case scenarios
It’s expected that the design system guidelines will highlight best practices for when and how to use a component. For example, a menu may work best with fewer items in it, so the design system suggests using no more than five. There is a lot of value in this kind of recommendation, but it should be treated as such. Don’t solve only for best-case scenarios, as not all applications will be able to change their structure to fully comply with such best practices. Having a myopic view of how components will or can be used is dangerous to the design system’s success. Create rules that can be followed, otherwise the design system may be viewed as a bane and not a boon.
*Hourly rate assumptions: Ratio = 2:1:1 (2 offshore : 1 onshore employee : 1 onshore contractor) Offshore rate = $18/hr x 50 devs = $900/hr Onshore FTE rate = $48/hr x 25 devs = $1,200/hr Onshore contractor rate = $78/hr x 25 devs = $1,950/hr Avg. rate = $40.50/hr x 100 developers = $4,050/hr Annual resource cost per 100 resources @ 40 hours * 48 weeks = $7,776,000