Marcelo Paiva
Saturation
Theme
Two people lean toward a wall mounted touchscreen as one points at it with a stylus.

WCAG Plugin for Figma

A free, open-source Figma plugin that puts WCAG guidance, annotation cards and accessibility utility tokens inside the file where design decisions actually get made. 10,500 users on Figma Community, and one feature they could not find.

Role
Designed, built and shipped
Year
2024
Built with
TypeScript, Figma Plugin API, Design tokens

Accessibility guidance loses every argument it has to win somewhere else. By the time a designer opens the WCAG spec in another tab, the layout is already built and the question has become how much rework it is worth. The plugin exists to move that question earlier — into the file, while the decision is still cheap.

It does three things:

  • Guideline search — find the relevant success criterion without leaving Figma.
  • Notation cards — annotate a frame with the guideline it has to satisfy, so the handoff carries the reasoning and not just the spec.
  • Utility tokens — import accessibility tokens as Figma variables, so the accessible choice is the default one rather than a thing we remember to check.

Why tokens, not a linter

A linter finds a violation after somebody has made it. That is useful, and it is late: by the time a check fires, the layout exists, someone is attached to it, and the question has turned back into how much rework it is worth.

A token works the other end of the same problem. WCAG 2.5.5 says a pointer target should be at least 44 CSS pixels. As a line in a document, that is something a designer has to remember, look up, and apply correctly every time. As a variable sitting in the file, it is simply the number that is already there when they reach for a size.

The difference is who carries the requirement. A linter leaves it with the person and then checks their work. A token moves it into the material, where getting it right is the path of least resistance. Neither is sufficient on its own — this site runs contrast checks that fail its own build — but only one of them is cheap at the moment the decision is actually made.

What changed after it shipped

10,500 users and 653 likes on Figma Community. Those are facts and they are the only ones I have. I cannot tell you whether a single interface shipped more accessibly because of this plugin, and I am not going to imply it.

What I can tell you is what people did with it, because they wrote it down.

There are three comments. Two ask the same question: what are these tokens, and where do they go after I import them? The feature I argued hardest for — the one meant to make the accessible choice the default rather than something you remember to check — is the feature nobody could find. One person imported the tokens, was told the import had succeeded, and had no idea what had just happened to their file.

The honest reading is that I shipped the value and left the vocabulary behind. Forty-four pixels means nothing as a Figma variable until somebody knows it is the minimum a pointer needs to land on. I had put the number in the file and kept the reason in my head, which is the same failure the plugin exists to fix, committed one level up.

The two releases after launch went somewhere else entirely — into search. Version 3 put WCAG version information into the results and onto the cards; version 4, three weeks later, added filtering by version and by conformance level. That is a reasonable thing to have learned, because people were using it as a lookup far more than as a source of tokens. It is also where my attention went instead.

What I would do differently is ship the explanation with the variable. The statusline tool I built later gets this right, though not on purpose: a criterion arrives with its own sentence already attached, so there is nothing to look up and nothing to misread. Same argument, learned here first.

About the drawing

The drawing for this piece was generated, not chosen. Hashing the piece’s name fixes one point on the color wheel; the other two follow from it. The same name always gives the same three colors.

#c93daa#76ae60#5aa880

How this drawing was made