← Michael Histen: UX & Product Design Leader

Case Study: Building Scalable Design Systems

When it comes to UX & product design, I am particularly passionate about design systems and libraries. They are a "win" on so many levels — they create a more consistent user experience, they allow designers to scale up new features rapidly, and they translate to more efficient engineering development time as well. A well-maintained design system is an enormous benefit to any organization.

In this case study, I aim to share practical insights and proven strategies for designing scalable, accessible, and efficient design systems.

In my six and a half years as head of design at BondLink, I had the unique opportunity to design and build an entire design system from scratch. This work originally began in Sketch, but we soon migrated our design work to Figma, which allowed for an incredibly robust component library, complete with variables and auto-layout features that enabled us to drag-and-drop elements to create new pages and features.

I’ll walk through some of the design decisions I made across a variety of areas, including:

Colors

Defining a color palette for a design system is a much larger undertaking than it appears. You can think of colors in four major groupings:

When choosing colors, it’s also vital to think about accessibility. Throughout our process of defining colors, we vetted each choice against color contrast checkers to ensure we met WCAG accessibility standards for sufficient contrast. Additionally, when considering colors for our data visualizations, we tested our choices with color blindness tools, to ensure clear differentiation. The end result was a robust color system that was accessible to a wide variety of visual acuity levels.

An example showing the full color palette for our design system.

Brand Colors

Brand colors are where designers typically have the most fun. These are the colors that distinguish you from your competition and become a unique identifier that can unite your designs across every touchpoint. Think of T-Mobile’s magenta color, UPS’s brown, or Tiffany’s blue.

When I started at BondLink, the only major visual element we had for our brand was a logo that incorporated gray, blue, and green. I felt the blue and green seemed too much like standard crayola-style colors, and instead experimented with different shades of blue and green, landing on more vibrant options that would help us stand out in the world of FinTech. It also became clear that our vivid blue and green would be well-balanced with a darker, less bright color, so I introduced a dark teal color to round out our primary color set.

We also associated meaning with each of our colors — we used our blue for interactive elements such as buttons and links, our green to highlight large pull-quotes and other decorative elements, while our teal was used primarily for text and other smaller UI elements intended to differentiate from standard body copy.

Grays

In addition to our brand colors, we established a full scale of grays from black to white to be used throughout the platform. We labeled them in increments of 100 (from 900 to 100), which is a common technique for labeling gradations in CSS.

While many websites default to using black for body copy, we chose our gray-800 (hex value of #333333) as our main body copy color, allowing us to more effectively distinguish important items by only making text black for headlines or other bolded elements. We also set our lightest body copy color option (gray-600, #727272) to have sufficient contrast on both white backgrounds and on our lightest gray (gray-100, #f8f8f8), which we occasionally used as a background color.

This wide variety of grays allowed us to create hierarchies for text and UI elements that imbued meaning, such as indicating the importance of content, distinguishing disabled elements, and creating navigation elements with multiple states.

UI Status Colors

Beyond our primary brand colors and grays, we needed colors that could be used for error/deletion, success, and caution states. Error and success states call for red and green colors respectively. Given that one of our brand colors was a green color, we made sure to choose a "success green" that was clearly distinguished from our brand "lime green" color. For our error red, we went with something bold but not so intense that it would be hard on the eyes. Caution is usually indicated with yellow, but yellow is one of the lowest-contrast colors and thus is very hard to work with, particularly for text. Thus, we shifted our yellow to be a golden-brown color, which gave us a bit more flexibility (and also was less overpowering than something like a bright highlighter yellow).

Data Visualization Colors

Our platform also included a number of data visualizations via line, bar, and pie charts. While our brand colors gave us some options to use, we needed a more robust palette to better distinguish key data. We wanted to keep the "vibrant" feel of our brand colors, so rather than using more typical primary/secondary colors, we explored more vivid options, ultimately choosing magenta, orange, and indigo to fully round out our brand palette. We iterated through several variations of these colors, carefully balancing accessibility needs, including testing them against a variety of types of color blindness.

Shades and Variations

The final step in having a fully defined set of colors was to include various shades of each color that could be used for states such as:

While we established a 10-level scale for grays, we opted to just do a 5-level scale for other colors, labeling them 900, 700, 500, 300, and 100. We chose 700 as the "primary" version of each color, and then scaled each color using HSL values (hue, saturation, lightness) that we then translated into hex values. By keeping hue the same across all levels, we ensured that each color maintained a clear "identity," and then through some experimentation, altered the saturation and lightness levels to create full color scales. We also tested every color for accessibility against white and black, and then against the darker and lighter shades of each color, to allow for using the lighter colors as background colors with darker-colored text.

Setting Figma Variables

Once our full color palette was determined, I created variables for each color within Figma in a shared styles library, ensuring their consistency across products. This also meant that if we ever needed to change a color slightly, we could change it in one place and automatically propagate it across all products. Every element in our designs always used a color variable, never directly typing a hex value into a design, thus ensuring we were always staying on brand.

Suffice it to say, what might seem like a fun exercise of color selection for a brand is actually a very complex process, and requires balancing quite a few factors to ensure colors are legible and accessible and convey the appropriate meaning where necessary.

Typography

Much like color, typography can help reinforce a brand identity. Consistent, well-structured typography is also essential for any user interface. We can break this down into a few major decision points:

An example showing typography components in Figma.

Font selection

For BondLink, we wanted to use a font that seemed professional and business-like, while still having a little more personality than something like Arial. For ease of use (and the fact that they’re free), we looked to the Google Fonts library and chose IBM Plex Sans.

For many brands, you may want to choose 2 or even 3 fonts for your design system, particularly for headlines vs. body copy. I’d say this is more useful for brands that are more playful or in the entertainment realm, as it allows for bolder headline elements. However, we wanted to emphasize a simple, clean aesthetic for BondLink and opted to just stick with IBM Plex Sans.

Text sizing

From here, we chose header sizes for the text and line-height of our H1-H6 headers, in some cases introducing all-caps styling with increased letter-spacing for further distinguishing smaller headers. We also established sizing for body copy, and quickly identified that we’d need some additional body copy variations (including lighter/darker grays) to convey relative importance, which allowed us to emphasize content (such as opening paragraphs on landing pages) or de-emphasize text (such as disclaimer copy or other secondary information).

We also opted on 3 weights for copy — in addition to the standard regular weight (labeled 400) and bold (labeled 700), we included a "medium" weight (500) for when we wanted to give particular words additional emphasis without fully bolding them, and for our smaller header styles. This medium weight became particularly valuable in tables where we wanted to emphasize a key column.

Line-height

One other major consideration for text that often gets overlooked is line-height. Some websites establish a common line-height of something like 1.5 (so for example, a font that is 16px in size would have a line-height of 24px). While this may seem like a simple solution, in reality, it’s much better to explicitly define line-height for each different font size. Large fonts for headers typically look best with much smaller line-height than standard body copy. So rather than using a multiplier, we defined pixel heights for line-height for each size of copy, sticking with multiples of 4px, which allowed greater consistency and also more predictable sizing when text was next to other UI elements such as images.

Mobile & responsive considerations

Speaking of text sizing, we chose 16px as our default body copy size, which is also the default that most browsers use for body copy. This was especially important in our form design for text inputs in our responsive deisgn. Many mobile browsers, such as Safari on iOS, will automatically zoom the screen on form inputs if they are smaller than 16px. Since our design was already optimized for mobile screens, when we experimented with a smaller font size, this had the unintended effect of making forms harder to navigate due to the unexpected screen zooming. Sticking with 16px for inputs allowed enhanced readability and allowed users to easily complete forms.

Conversely, large header fonts that may look great on big screens can be overwhelming on small mobile screens, so we established smaller header sizing for smaller screen sizes as part of our responsive design.

Iconography

First, let me say that there are a number of pre-made icon sets that, for many brands, are probably sufficient to cover the vast majority of your needs. In our case, we wanted to have icons that could relate directly to some key features of our industry that were somewhat atypical from a standard icon set. After initially exploring using icons from The Noun Project on an as-needed basis, it quickly became clear that we’d end up with an icon set that had an inconsistent look and feel, so we decided to create our own BondLink-specific icon set.

An example of the icon set for our design system.

While there are a handful of icons that have become so commonplace that most people know their meaning (such as an envelope for email or a pencil for writing/editing), most icons will require some accompanying text or other additional context to ensure their meaning is clear. Icons also need to be able to scale considerably and be legible even at very tiny sizes.

For our icon set, I decided on using a consistent 32 x 32px canvas for each icon in an Adobe Illustrator file. All shapes within each icon were defined with vectors (using a mix of lines and shapes) to ensure scalability. We also established some rules for our icon creation:

Beyond these general rules for creating icons, we also primarily used icons in conjunction with text to ensure clear meaning. Our major exceptions were in tables in our portals, where space was at a premium. In this scenario, since our users are frequently interacting with this content, they have a greater likelihood of having time to learn the meanings of each icon. We also tried to keep these functional icons to more universal icons, such as a pencil (edit) or trash can (delete), and added table headers to ensure clarity when possible.

Components

Thus far, I’ve talked about the more basic building blocks of a design system. Where a design system really becomes powerful is when you create reusable components. There are a few key aspects to component design:

An example of button components, showing various contexts.

Defining variables

Figma allows you to create numerous variables with each component so that you can adjust them as needed for each context. For example, our basic button design had a number of variables. Our buttons sometimes (but not always) included an icon, so we created a variable that allowed you to show or hide the icon, and then also swap out the specific icon as needed. You can also use variables to establish the various states of a button — such as default, hover, active, and focus.

You can also create variables based on context. We had both primary (solid color) and secondary (white background with a color outline) buttons, as well as alternate button designs to use when a button is overlaid on an image, or when a button is being used to delete (red) or confirm (green) content.

As you can tell, there are a lot of variations here. This is where personal taste comes into play as well with component design. We also had a "small" version of our button, but rather than add yet another variable to our standard button design, we decided the differences were significant enough that we simply made a different component for small buttons. Another design team may have approached this as all part of the same component, however my opinion is that once the number of potential variations of a component starts getting into the dozens, it may be time to consider breaking it up into separate components to reduce complexity.

Creating components

For any website/app, there are going to be a certain number of default components you’ll want to design — such as buttons, form fields, tables, etc. But you can also extend your design system to include larger components more specific to your particular product.

For example, at BondLink, we frequently showed upcoming bond sales by using cards that include multiple data points, so we created a component for bond cards. Each card can have quite a bit of variation, as many data points are optional, so we designed the card with a "kitchen sink" approach, showing the maximum amount of data that could be in any given card. We then used variables to hide or change which data was presented.

Refactoring as needed

Bond cards in particular were a good example of how we refactored our designs to make them more efficient in our design library. As we built out our platform, we eventually had 4 different products that showed bond cards, and as they evolved, each product showed the bonds slightly differently. Many of these differences made sense — for example, when looking at bonds from a single issuer, you don’t need to list the issuer on each card since it’s always the same. But in our investor portal, users were able to save bonds from multiple issuers — thus necessitating showing the issuer name on each bond card.

As it became clear our designs were diverging, we did an audit of all content on each version of the bond card, and then refactored the design to allow it to be the same component, just showing/hiding relevant content based on the product context. This not only improved efficiency on our end by turning 4 disparate components into one, but also ensured that our users were seeing a more consistent experience by ensuring the content of each card was in a familiar, consistent design across our products. This had the added benefit of making our engineering team happy, as it allowed them to also reduce the complexity in their code.

Nesting components

Once you get into the world of components, there is a near endless set of possibilities for how you configure your design library. In Figma, you can also nest components inside other components. Some of you may be familiar with the concept of "atomic design," and you can use a similar set of principles in your Figma files.

For example, a button is a component, but you could also have a card component that includes the button component. In some cases, we continued taking this further to create large chunks of pages as components, particularly when similar page content was being reused across products. This not only sped up feature development, but also made it clearer when we needed to adjust pages or content to ensure greater consistency.

Voice

One often overlooked aspect of a design system is the voice or tone of any text within your designs. This is much harder to standardize than something like a color or font size, but if you come up with some basic principles, it can significantly improve the overall user experience while reinforcing a brand identity.

For BondLink, one of our missions was to make the complex world of municipal bond issuances feel as simple and clear as possible whenever we could. To achieve this, we approached our copy as being plain-spoken, clear, and conversational, avoiding overly technical jargon. We also made a point of clearly explaining the impact of any actions. For example, our websites have the option of a draft mode, where clients can make changes and save them before deciding to publish them to their live sites. Rather than simply give a "save as draft" option, we added copy in a modal dialogue that let users know that their changes were being saved, but that an admin would need to review and approve the content before it was published. If the user in question was an admin, we also provided a link there to directly take them to a change approval screen. Our goal was to add enough information to avoid any guess work, and to anticipate any questions or next possible actions.

There are a number of other stylistic considerations to make about voice. Do you want to personify the brand, and use copy like "We’ll save this for you so you can come back later and approve when you’re ready" (making the brand the "we")? Or do you want the brand to be a bit more dry, emphasizing functionality rather than personality, by using copy like "These changes will be saved and can be later approved by an admin." Whatever voice you choose for your brand, what matters most is consistency of tone throughout your products.

Additional Guidelines

A well-maintained, comprehensive design library makes creating new features much more efficient. But it also requires a certain level of rigor in how you use the design library. Below are a few guidelines that I highly recommend:

Summary

A well-structured design system is more than a collection of components — it’s a strategic tool that drives consistency, accessibility, and efficiency across teams. Design systems empower organizations to innovate and grow by enabling the rapid development of new features. Whether you’re building from scratch or refining an existing library, the principles and practices shared here can help create a foundation for success.

← Back to my full portfolio