The Accessibility Bugs Our Test Suite Never Caught
For a long time I treated accessibility as something to worry about later. Then a small change to our Vue setup turned into a week of debugging, and "later" arrived all at once.
Most of the complexity was accidental. Over the years we'd layered three different approaches to accessibility on top of each other, and each one made sense at the time.
Where we started
When we finally measured, the numbers were worse than anyone guessed. Around 35% of the time spent on a typical change went into working around accessibility rather than building anything.
The setup was ordinary: Vue at the edges, TypeScript doing most of the heavy lifting, and a handful of scripts nobody wanted to own. It worked well until usage roughly doubled over a single quarter.
How it works
The fix turned out to be smaller than expected. Instead of adding another layer, we removed one and leaned on what Vue already gives you out of the box.
Here's a trimmed-down version of what we ended up with:
export function debounce<T extends (...args: any[]) => void>(fn: T, wait = 200) {
let timer: ReturnType<typeof setTimeout> | undefined;
return (...args: Parameters<T>) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), wait);
};
}
This alone let us delete a surprising amount of code elsewhere in the project.
A few things that helped along the way:
- Write the migration guide before writing the migration.
- Pair on the first few changes so the knowledge doesn't live in one head.
- Measure before and after, even if it's just a rough number in a spreadsheet.
Where this breaks down
We still haven't solved hydration. That's a post for another day, and honestly, I'm not sure we'll get it right the first time either.
The biggest cost was social, not technical. Changing how people think about accessibility takes much longer than changing the code.
What's next
I don't think there's a universal answer here, but I hope this gives you a few ideas to try on your own project. If you do, I'd love to hear how it goes.