#javascript#testing

Building Forms That Don't Fight the Browser

· 3 min read

A colleague asked me last week why our team cares so much about design tokens. I gave a rambling answer, so here is the longer, more organized version.

Most of the complexity was accidental. Over the years we'd layered three different approaches to design tokens 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 44% of the time spent on a typical change went into working around design tokens rather than building anything.

The first symptom was subtle. Nothing failed outright, but design tokens kept drifting in the wrong direction, and every fix seemed to make the next one harder.

What we changed

The fix turned out to be smaller than expected. Instead of adding another layer, we removed one and leaned on what Svelte already gives you out of the box.

The core of it looks like this:

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);
  };
}

It's tempting to generalize this into a library. Resist that urge until you've needed it in at least three places.

A few things that helped along the way:

  • Pair on the first few changes so the knowledge doesn't live in one head.
  • Agree on what "done" means before the first pull request.
  • Write the migration guide before writing the migration.
  • Measure before and after, even if it's just a rough number in a spreadsheet.

Trade-offs

None of this is free. The new approach is a bit more verbose, and newcomers occasionally ask why we don't just use Playwright for everything. That's a fair question with a boring answer: we tried, and it made design tokens harder to reason about.

We still haven't solved container queries. That's a post for another day, and honestly, I'm not sure we'll get it right the first time either.

Takeaways

If you take one thing away from this, let it be this: design tokens is a design decision, not a cleanup task. Make it early and make it on purpose.

OP
Owen Patel
Frontend engineer in Austin. Writing about frontend engineering.