How to Consolidate Designs at a Fortune 500 Company
By: Ken Bigler
Tags: Design, Intuit, Design Systems, Software Development, Design Thinking

Four components + seven business units + tons of plugin applications = One Design System

At Intuit, we have seven main business units (BUs or product themes) that we design and develop for, both internally and externally. Many of these product themes all use one central design system, but a few still have their own design systems, creating conflicting components and styles across the various BUs.

My team’s goal is to combine all of the various design systems into one Intuit Design System (IDS) that is available to the entire company. My most recent project was to take four fairly different components, all used by different teams, and merge them into one unified component that all teams could access.

What is a Design System?

A design system contains various components which work a lot like building blocks; they are used together to create larger applications. A design system in our case includes a component library that follows a set of standards compiled by Intuit designers so that all components across all our applications have a familiar look and feel. These standards can include design data, such as colors, spacing, fonts, and even component functionalities. You can think of Google’s Material Design system, IBM’s Carbon Design System, and Adobe’s Spectrum design system as good examples of this.

Figure 1 — Intuit’s Strategy: One Intuit Ecosystem

How do we operate at Intuit?

At Intuit, the engineering department has committed to “Tech Bets,” or large goals that we as an engineering department want to achieve. One of these tech bets is to “Power our vision with One Intuit Services Platform.” In other words, we are trying to have one platform, with a clear Application Programming Interface (API) architecture and clean data model, as well as enabling easy setup on this new and centralized system. I work as a part of the Intuit Platform organization that aims to do just that. Specifically, I am on the Intuit Design System (IDS) team and we create components to be used across all of Intuit’s applications.

When we are creating a new component, we follow an in-depth process.

Product designers, subject matter experts, and user-experience designers conduct extensive interviews to understand how teams want to use the component in their product. User experience designers then incorporate design and usability best-practices, along with platform-specific knowledge. When teams agree on how a component should look and function, IDS designers create specifications for colors, spacing, and overall look and feel of any base component used in our applications. Those specifications then go to the software engineers (me and eight others), and we turn them into functioning components. We standardize the API to be used based on the needs of the various business units. Finally, the component goes to the internal accessibility champions for review, where they verify that all of our components comply with the needs of all users, making sure we hold ourselves to the highest standards.

What did the process look like coordinating with all these teams?

Previously, we had dozens of badge components across many feature-based applications used in all of our Intuit products, both internally and externally. This was causing code repetition, code bloat, inconsistency in usage and features, and styling nuances from every business unit, which led to an inconsistent and unpleasant experience for the users. These components had been consolidated into four main design systems, which is when I entered into the process. This was already great progress from where we started a few years ago, but there was still room for improvement.

I was given these four different implementations, each with varying degrees of use across all seven business units. All of these components had some similarities in them, and without going into too much detail, you can see in [Figure 2] that they all had some core set of features that overlapped, with a few things missing from each. That being said, it looked like the first option (the CGDS Badge) had the most features that I needed in my end product (and it was on the new tech stack I was aiming to move to), so I used it as the base for my development.

Figure 2 — Existing functionalities already existing on components

So what did we do first? We decided to throw out most of the fourth component, as it was using a very outdated tech stack and it was 100% covered in the second component. Next, we merged the first two components as they had a lot of overlap. Together, these two components end up covering about 90% of the overall functionality needed in our final component. After a few styling changes and some code refactoring (and a lot of learning the new tech stack), I had a product that was ready to be reviewed by both the design team as well as the accessibility team.

After many iterations and trying to find the optimal component that both teams would approve, we had an almost finished product. At last, the final element could be put in, which would add the needed functionality for the third component. This brought about a few interesting technical dilemmas which you can read about in the next section, but overall the process went smoothly with immediate design and accessibility approval. TLDR: We gathered all of the head designers together across all seven BUs, put them all in a meeting together, and told them “We have 90% alignment, we just need to work our way to 100%.” After some time, we achieved 98% alignment on styling and 100% alignment on the functionality. The teams agreed that the final two percent of styling differences could be resolved by allowing certain aspects (colors and icons) to be customizable through product themes.

In the end, seven different BUs, using four different badge components, are now collectively using one badge in one design system. When anyone asks for help or support, we no longer have to say “Which badge are you using? Oh no we don’t support that component. Ask another team.” Everyone now has one badge to use that is easy to support and in one main location shared with all future components.

So we went through all this effort, what were our overall improvements?

The final component has, on average, a 50% reduction in the bundle size

The final component has, on average, a 30% reduction in the number of lines of code

The final component had 100% test coverage (up from ~5%–80%)

Subcomponents are now customizable

Missing design requirements are now met

Missing functionality from each badge is now available

Better documentation

Moved to new CLI and from JavaScript to TypeScript

The new component is now strongly typed with autocomplete

Aligned seven BUs on colors, styles, & icons, configurable with product themes

The final component is accessibility compliant (only two were before)

Tech Section

Theming

So now let’s get to the interesting part, at least for us developers. What were some of the technical decisions that we made? Well for starters, did I mention we have seven business units to take into consideration, each with their own product themes? How did we take care of this?

The short answer is that we used PostCSS, and an amazing theming library called postcss-themed. The team that creates this plugin also created the CGDS (Consumer Group Design System) version of the above badge component, they are an amazing team and I greatly appreciate their help! Anyway, back to theme-ing. In each of our components we have a theme.ts file, which basically has the following this structure:

export default () => ({

businessUnit1: {

light: {

backgroundColor: BU1ColorLightTheme

},

dark: {

backgroundColor: BU1ColorDarkTheme

}

},

businessUnit2: {

// has no light or dark theme, this applies to both types

backgroundColor: BU2Color

}

…

})

And then we consume the configuration in our CSS files like this:

.some-class {

Background-color: @theme backgroundColor;

...

}

Postcss-themed, using PostCSS, looks for the @theme tag, and then substitutes the required variable based on our provided object! It works amazingly well to keep our CSS clean and readable, without worrying about adding too many classes and conditions in our code.

Improved Code Quality

A big part of moving to our new Tech stack was to improve overall code quality. Let’s start with the new design-system-cli created by one of our Intuit teams (the CGDS team). It creates a design system, or a project that will plug into our design system, within minutes, comes with TypeScript, CSS, and styled-components support out of the box, outputs CJS and MJS, and there is no tooling configuration required. It is a lot like Intuit’s version of create-react-app. The new CLI has better built-in linters (eslint and stylelint), and I added the eslint plugin prettier/recommended as well as made sure our code is more readable and follows a more strict visual guideline. We moved to a 1 file per component rule so that the code is more maintainable and easier to comprehend. The new tech stack is on TypeScript, so we have pre-compilation type checking (vs. what prop-types does with post-compilation checking), as well as autocomplete for developers also using TypeScript.

As part of this move to TypeScript, we started using base element typing, so our components extend their base elements. We use an internal library for this, so if my component wraps a <div> then that component will extend Element<'div'> which means that all of the properties a div will accept, my component will accept as well. As we are a design system, and we create many low-level components, often just extending a base HTML element, this helps significantly. We also updated the naming of a prop we pass to most of our top-level components, from: …restProps to: …html . Now the code makes it clear that HTML attributes are being passed down, plus, TypeScript helps with autocomplete more completely. Rather than just displaying our custom API, it also displays native element attributes.

For the badge component specifically, this TypeScript conversion had a neat trick to add. We had what was called a numeric badge which, if the badge was a number, it would display slightly differently. This was previously done with a prop shape="numeric" but now we can just check the typeof our value prop, and if it is a number, provide the specific styling needed.

Going Forward

Going forward, our technical section benefits will remain, as well as the bulleted list of improvements above, but the scope of impact is much larger. All the components in our new design system are well documented, fully tested, accessibility approved, company-supported components that work for all our product themes. Designers and developers can use these components with peace of mind, knowing they are well-supported and well-used components.

This was the fourth component added to our new design system, but the first component migrated with the intention of combining overlapping components (there are about 50 components across the four main design systems with significant overlap). We are intending to have a little over 30 components in the new design system (some components are still fairly product-specific, and do not need to be shared over other products). Now, we have a process to follow for future components, and a clear path going forward.