Purging Design System ‘rot’ from our checkboxes

Accidentally discovering hidden accessibility issues, fixing it heuristically, and a few simple tricks to avoid future rot. Written by Chuck Rice.

Moonpig Group Product
8 min readApr 11, 2024

Chuck Rice, Senior Design Systems Designer at The Moonpig Group.

Two rows of 4 rounded checkbox squares, coloured in a “Pop Art” fashion. Each checkbox coloured different gradients, with contrasting background shades.

If Andy Warhol was also into Design Systems, he might have painted something like this.

Rot is a strong word, but it’s simply another way to frame or think about design debt or tech debt. What do we mean by that? Well these are decisions made long ago that were perfectly appropriate once, but over time fail to serve their purpose.

As an analogy, plant roots tend to rot if they aren’t repotted in the spring, often moving up a pot size to support new growth. Design Systems are similar in the sense that they have cyclic seasons, and need some long-term care to flourish. Lack of care leads to rot.

If left unchecked it can cause headaches for others. The system is one of the last places you want rot to occur, given how ubiquitous it is on a mature product and team. I’ll run you through an example with our checkbox component, and how I’m avoiding future rot.

How rot occurs

It’s a tale as old as time — you fall in love with the problem, use the design tricks you learned at the last conference, and battle test your solution with users and stakeholders. Every single detail is taken care of. It’s sleek, elegant, and it’s proven to solve the problem. It’s your best work yet.

But then comes time to build..

There’s deadlines to wrestle. Dependencies we’re accountable for. It’s tech, so there’s always talk of “POC” (proof of concept) or “MVP” (minimum viable product) first. Design elements we thought would take days, would end up taking weeks.

Quick! Think on your feet.

Now, this is the harsh reality that every designer under the sun faces daily. It happens across every company, industry, and team. Each team spends time making compromises on their designs, using their own version of reality, usually working within their own product space.

Don’t get me wrong, it’s the thrill of this balancing act that keeps me coming for more, and keeps me in the job. But…

There’s got to be a way to see 80% or more of a design make it to production — as a whole, designers became tired of seeing their finely crafted work being watered down into Yet Another SaaS Product.

Queue Design Systems to the rescue.

Design Systems are mainstream today, and it’s much better understood in the business world now than perhaps 5, definitely 10 years ago. Get product in the hands of customers faster than ever before, and at a higher quality to boot. By 2020, it felt like overnight everyone had their own system.

Over time, though, each team lost sight of the whole. Heck, even myself sitting in the Design System seat loses sight of how components are used and which contexts they’re used in. Almost like the Observer effect, there isn’t an issue… until you look for it.

Therein lies the crux of the problem I’m highlighting. One day in the past, our checkboxes used to be perfectly fit for purpose.

But now, they’re not.

Stumbling upon broken checkboxes

Screenshot from Moonpig’s Storybook; list of components on the left, and a checkbox rendered on the canvas to the right.

The checkbox in question, as shown in our Storybook.

Fixing component drift is a work stream I’ve identified and I’m working on here at Moonpig for our Design System. Essentially we’re assessing if components, as understood and used by designers, are compatible with how they’re understood and used by engineers.

“Fit for purpose”, I like to call it.

As a first step, I’ll look at both the code and the designs in Figma to see where they differ. Given I’ve professionally been both an engineer and designer, I can make some quick heuristic assessments of:

  • Comparing props in React, against properties in Figma
  • Design token usage
  • Icon tokenisation
  • Focus states

My most recent task was to assess and fix the checkbox component. With a few small changes, it’d be back to reasonable parity in no time.

Assessing fitness for purpose

Next up is assessing if it’s truly fit for purpose. I needed to find places on the live site they were being used. After some trawling around, I found two cases: edit address, and adding a reminder.

Part of Moonpig’s edit address form on the left, and add a reminder form on the right on white and grey backgrounds. Both have optional checkboxes displayed on a smaller blue background.

The two cases side-by-side.

What stood out to me is that we didn’t use checkboxes on a blank white background, as it is in Storybook, which passes colour contrast checks.

We used it against a blue background.

A quick check confirmed my suspicions — this violates WCAG criteria 1.4.11 on non-text contrast, to AA standard.

Results from assessing the contrast of grey, #a3a3a3, on top of pale blue, #e6eefa, using colourcontract.cc. Result is 2.16, and fails for all text at all sizes for all accessibility levels.

I highly recommend Colour Contrast Checker — it’s so lovely to use!

Fixing the issue

A colour palette spread across two rows showing a scale of 10 different shades of grey, labelled with a token name e.g. colourBlack10, and the hex code.

Thankfully, there’s only 10 shades of grey here.

We have the colour black on a lightness scale with 10 levels, so I thought it’d be as simple as decreasing the lightness of our default state.

Oh how wrong I was.

To illustrate, below is a copy of our checkbox in the default and disabled (or deactivated) state. It wasn’t clear which one was which, should they be side by side even before any changes.

Two large unselected and unlabelled checkboxes, side-by-side, each a different shade of grey.

Can you tell which one is which?

To prove my point and gather some quick data I did a quick demo at our weekly Product Demo session, and asked the audience to guess which was which. Unsurprisingly, the vote fell roughly 50/50.

Our colourBlack60 token meets the correct contrast ratio against all of our background colours. Huzzah! Well, after comparing the different states, I found out afterwards that our disabled state uses that colour. It makes sense, since we’d still want our disabled state to be visually perceptible.

I suspect here’s the order of events that led to this point:

  • Checkbox component was created.
  • State colours were selected against a white background.
  • We later added background colour tokens.
  • Deactivated colour token was selected, with backgrounds in mind.
  • No further work was done to tackle the knock-on effect.

This is just one instance, but it’s easy to see how seemingly small decisions can cause unintended effects throughout the entire product.

To cut a long story short, I looked to other Design Systems such as the Government Design System’s checkbox (GDS) and Nord Health Design System’s checkbox to come up with a “good enough” solution.

Key features I liked or borrowed:

  • Nord Health used a fill for the disabled state, to visually distinguish using more than simply colour.
  • GDS used a stronger colour for default state, as well as larger boxes.
A slide from a presentation, titled “which is disabled?”. Enabled and disabled versions of checkboxes; Nord Health on the left, Government Design System on the right.

Different systems take different approaches to meet AA accessibility.

N.B. borrowing patterns is great, but it’s crucial to do adequate user testing to ensure your system is fit for purpose for your industry, and your customers.

The end result was something like this:

A grid showcasing a checkbox in Figma in default, error, and disabled states, their respective selected versions, as well as focus states. Last updated 12 March 2024.

Our focus state corresponds to a 48x48px hit box — optimal for every device.

Avoiding future rot

To avoid rot and doubt further down the line, I started adding a simple “last updated” label on all our components. It’s a small detail, but as any seasoned designer will know, it’s the sum of all these intricate decisions that makes something truly a pleasure to use.

In addition, we used to store “spec files” generated using the EightShape Spec plugin as separate files, but I’ve started to keep them alongside the actual component. There’s been too many instances of spec files being out of sync, and it’s easy to forget to update it when it’s not right there.

While there’s other elements I’d like to fix like the focus state spacing, ultimately, the goal isn’t perfection — it’s to be better than yesterday.

Beyond component accessibility

So, where does that leave us? Surely the story ends here? Well, it’s not enough if you want to reach AA accessibility for an entire product.

The lesson here is that the checkbox component as dreamed up by our Design System team long before my time here, passed all the accessibility criteria and checks in isolation. In a controlled environment. What wasn’t accounted for later, was how components would be used in the wild.

As I see it, my job is to ensure that we provide a flexible system that lets its users fall into “the pit of success”. Provide a system where given all the sensible combinations of tokens, components, and patterns, you will reach a high standard of quality and accessibility with no extra effort.

The other half, however, is balancing that with creative freedom. By that I mean, we can’t make it so restrictive that our product squads lose the ability to innovate and push the system further in ways we didn’t think of. As the old adage goes — with great power, comes great responsibility.

Designers, engineers, and product managers need some sort of awareness of poor interface composition. Arrangements of tokens, components, and patterns that cause friction and accessibility issues to our customers. Without embedding awareness, you’ll be chasing your proverbial tail.

For example, disabled states aren’t bad, but they’re prone to misuse.

Half the battle is curating high quality components, accessibility out the box, and parity. The other half is treating Design Systems as a practice; one which the users — just like yourself — create more moments that matter.

TLDR;

How to find, fix, and prevent rot in your Design System and Product:

  • Make time for holistic reviews — Design System work is never done, it’s a practice. It keeps evolving and changing because of the people using the system, and experiencing the results.
  • Drive quality through empowerment — to conquer high quality, half of it is with tokens and components ready out of the box; the other half is arming squads with knowledge, guidance, and support.
  • Leave a (lightweight) paper trail — future you will thank you, as well as those not deep in the details, with key info like a RAG status, last updated timestamp, or release notes.

--

--

Moonpig Group Product

We’re a team of problem solvers that combine creativity and user-centric thinking to delight our customers. Join to explore the world of product with us! 🌙🐷