a11y Companion
Accessibility review inside Figma and FigJam, with canvas audits, Dev Mode handoff, and sign-off that tracks the reviewed checklist state.
When sign-off stops matching the design
I created and maintain a11y Companion, an accessibility review widget for Figma and FigJam. Version 3.0.0 brings The A11Y Project Checklist together with canvas audits, contrast inspection, reviewer sign-off, and handoff records.
The first version let teams complete an accessibility checklist in the design file, but a signed section could not flag that changed items needed another review. In v3.0.0, a named reviewer's signature records item ids, completion state, and checklist revision. A change to that evidence turns the stamp amber and marks the section for re-review.
- Touch targets
- 50 targetsPage scan
- Text readability
- 41 layersPage scan
- Token contrast
- 120 pairsPage scan
- Text
- #92400E
- Background
- #FEF3C7
Ready for handoff
- Checklist
- 64 / 64
- Sign-offs
- 16 / 16
- Evidence
- Complete
The checklist is complete, sign-offs are current, and all three page audits are recorded.
Checklist, evidence, sign-offs, and contrast are ready for handoff.
Ready: Ready for handoff. The checklist is complete, sign-offs are current, and all three page audits are recorded.
In this case study
Follow a finding back to the layer
Version 3.0.0 adds the canvas checks and native Dev Mode annotations that the first version lacked. Three audits run against the selected canvas scope, sharing a capped 25-finding slot with failures sorted ahead of warnings. Counts include findings beyond the display cap.
- Targets: fails below 24px per WCAG 2.5.8, warns below 44px, with a 2000-node traversal budget
- Text: per-segment font size, line height, justification, line length, and all-caps checks
- Tokens: local variable collections across modes, alias chains resolved to depth 10, alpha-composited ratios
- Per-finding Jump to select and zoom the offending layer
- Severity glyphs that never rely on color alone
Contrast inspection re-checks the selected layer in Watch mode. A keep-alive bridge responds to selection changes, and shared ownership with last-writer-wins takeover shows the team who is driving.
- Thresholds evaluated at full precision before rounding for display
- A failing pair keeps the measured colors in the specimen while a separate line states the verdict
- Color vision preview for protanopia, deuteranopia, and tritanopia, labeled as simulation
- WCAG contrast stays the normative result; the preview never issues a second grade
- Explicit notices for pattern, shader, and video fills instead of a silent failure
What the Geist file exposed
Early token pairing matched on names containing "text" and "bg". Testing
against Vercel's Geist file exposed a limit: ramp-named systems use
gray/100 through gray/1000, and the audit was
checking roughly twelve pairs. It now infers role from the trailing numeric
step, reading high steps as ink and pairing them against low steps and
explicit surfaces in the same family, with the pair cap raised to 800.
State has to survive the widget runtime
The widget runtime clears module memory between interactions. Watch ownership therefore needs state that survives those resets:
- Watch ownership uses the durable
sessionId - Export and clipboard access run through a hidden iframe bridge, since the widget sandbox has neither
- Empty spacer AutoLayouts default to 100px tall; explicit
height=0keeps them from inflating badge and chip rows
A review record the team can hand off
Native Dev Mode annotations keep findings attached to the affected layers. Canvas Record gathers review progress and evidence in one Figma frame. Both need to remain useful when the review runs again.
- Audit findings promote to Figma Dev Mode annotations, individually or in bulk
- Read-modify-write preserves existing annotations and stays idempotent on re-run
- Annotations link the relevant WCAG Understanding page and cite the properties that failed
- Canvas Record compiles progress, sign-offs, audit summaries, and priority findings into one Figma frame
- Re-running Record refreshes the same widget-owned frame instead of creating duplicates
Markdown, CSV, and JSON exports carry run owner and time, scope, full counts, grouped evidence, and an explicit disclosure when rows are representative rather than complete.
The widget has 400+ users on Figma Community and supports twenty locales. The v3 workflow can be reviewed through its audit findings, Dev Mode annotations, Canvas Record, and Markdown, CSV, or JSON exports.
Design-system checks, translation, and demo parity
Design system checks
Scripts in lint check the widget's token architecture, AA contrast, theme drift, and bundle size.
- Variable architecture and design-system conformance checks
- Automated AA contrast verification across the token set with shade-step suggestions
- Theme baseline snapshots that fail on unreviewed drift
- Bundle size budgets, kept under ceiling by minifying syntax while preserving identifiers
Checkboxes meet WCAG 1.4.11 non-text contrast, severity uses glyphs alongside color, and WCAG references render in both themes.
Translation
Twenty locales are generated through a pipeline that shields WCAG codes and inline markup from machine translation. Missing keys fall back to English per key, so a newly shipped command renders in English rather than as a blank menu item while its translations are reviewed.
Product site parity
The product site is statically prerendered and gated by a Chrome-based check that exercises audit interactions and control geometry at 390, 768, 1000, and 1440px. The site's inspector demo is held to the production widget's exact specimen size, card inset, and vision grid.
Project notes
400+
Users on Figma Community
20 locales
Checklist and interface translated through a term-protected pipeline
v3.0.0
Audit platform, native annotations, and evidence-bound sign-off