Engineering

Making AccelaStudy AI Accessible to All

What it actually takes to ship an adaptive-learning product that works for every learner — including those using screen readers, keyboards, switch devices, magnification, or reduced-motion settings.

The AccelaStudy AI team May 9, 2026 10 min read

We promise that adaptive learning works for every learner. That promise has a quiet corollary: if you can't read the screen, can't use a mouse, can't tolerate motion, can't see the focus ring, or rely on a screen reader, the product has to work for you anyway. Otherwise we're saying "every learner who matches a particular profile of vision, motor function, and cognitive style," which is a much smaller promise.

Last week we did a fleet-wide accessibility audit and remediation across the entire AccelaStudy AI surface area. This post is what we did, why we did it the way we did, and what the numbers look like now. If you're a learner who relies on assistive technology, the short version is: the entire product passes our deterministic accessibility audit, every interactive control has an accessible name, every form input is labelled, every modal traps focus correctly, and every animation respects your prefers-reduced-motion setting. If you're an engineer or a product person curious about how, the rest of this post is the mechanics.

What "fully accessible" means to us

The accessibility standard we hold ourselves to is WCAG 2.1 Level AA. That's the bar enterprise procurement teams check when they evaluate AccelaStudy AI for school districts and Fortune 500 learning programs. It's also the bar most users experience as "the product just works." WCAG 2.1 AA defines about fifty success criteria covering everything from alt-text on images to keyboard navigation to color contrast to focus indicators to motion preferences. Meeting it is not a checklist item; it's a property the codebase has to keep.

Here's the framing we work from:

State a codebase can be inWhat it requires
Aspirationally accessibleSome components are right; some aren't; nobody knows which
Audited accessibleA scan happened once, the findings got fixed
Continuously accessibleEvery commit is gated by a deterministic check; regressions can't merge

We were the second; we're now the third. The transition needed two things: an audit that runs in CI and refuses to ship broken accessibility, and a one-time mass remediation to get to zero before the gate started enforcing.

The audit

We built a deterministic Python script that scans every TSX, JSX, HTML, and CSS file in fifty-six AVIAN repositories. The script implements fifteen rules, each mapping to one or more WCAG 2.1 success criteria:

RuleWhat it catches
Image without alt<img> tags missing alt="" (decorative) or descriptive alt
Informational SVG without ARIAStandalone SVG glyphs not marked with role/label or aria-hidden
Canvas without text alternativeKnowledge Map and similar visualizations needing a text summary
Input without accessible nameForm fields screen readers can't announce
Multiple headings of the same rankPages declaring more than one <h1>
Missing main landmarkLayouts without a <main> region for "skip to content"
Missing skip linkLayouts without a "Skip to main content" anchor
HTML missing langPages without lang="en" (or appropriate locale)
Generic link text"Click here" / "learn more" without context
Clickable non-interactive element<div onClick> without keyboard support
Aria-hidden focusable elementHidden elements still in the tab order
Positive tabIndexTab-order overrides that confuse keyboard users
Outline:none without replacementFocus rings invisibly removed
No reduced-motion guardAnimations not respecting prefers-reduced-motion
Missing sr-only utilityRepos lacking the visually-hidden screen-reader utility

The script auto-discovers UI repositories, skips test fixtures and build artifacts, and emits two reports: a Markdown summary you can read, and a JSON file CI can diff. In its default mode, it exits with a non-zero status when any HIGH or CRITICAL finding remains. That's the gate.

What we found

The first run of the script reported 414 HIGH-severity findings, 312 MEDIUM-severity findings, and zero CRITICAL. The HIGH findings clustered into two patterns:

  • 2,235 form inputs in the cloud-console simulator (used by labs across forty-five certifications) had a visible label next to them but no programmatic linkage. Sighted users saw the label; screen readers didn't.
  • Smaller pockets of issues across the consumer apps, internal tools, and marketing sites: missing aria-labels on icon-only buttons, modal backdrops without role="presentation", decorative SVGs not marked aria-hidden, focus rings stripped without replacement.

Both patterns were obviously fixable. The first needed a codemod. The second needed a focused manual pass.

How we fixed it

We worked in nine waves over a single day:

Initial audit414 HIGH, 312 MEDIUMActivities library5 fixesConsole-sim codemod2,243 fixesClient apps59 fixesTools fleet136 fixes across 21 toolsHeuristic refinements+ 17 manual cleanupStale-dist cleanup71 fixesConsole-sim views118 fixesFinal stragglers2 fixesMedium cleanup676 fixesFinal state0 findings
From 414 high-severity findings to zero, in nine focused fix waves

The codemods did the heavy lifting. A 200-line Python script walked the JSX of every console-sim dashboard, found adjacent label/input pairs, generated a stable id from each input's test identifier, and rewrote both elements with the right htmlFor/id linkage. It applied 2,235 fixes in eight seconds. A second codemod demoted 594 page-secondary <h1> elements to <h2> across 241 files. A third added aria-label to 50 inputs that had a test identifier but no preceding sibling label.

The non-mechanical work — modal focus management, custom widget keyboard patterns, decorative-SVG marking, focus-ring restoration — went to focused review passes across the apps and the tools fleet.

What's in the codebase now

A snapshot of the AccelaStudy AI accessibility footprint after the audit:

MetricCount
UI-bearing repositories56
TSX/JSX source files2,185
Native <button> elements2,527
Form inputs (input / select / textarea)3,486
Total ARIA attribute uses3,019
Explicit aria-label uses1,530
aria-hidden uses (decorative elements)752
role= uses1,001
role="dialog" (modals)109
role="img" (canvas/SVG with text alternative)112
role="button" (custom interactive elements)101
tabIndex uses150
onKeyDown keyboard handlers208
Tailwind focus-visible: classes102
Skip-to-main-content references200+
HIGH findings before remediation414
HIGH findings after remediation0
Findings at every severity, after0
Total fixes shipped in one day3,317

The numbers worth lingering on are the 2,527 native <button> elements and the 3,486 labelled form inputs. Native HTML semantics are the foundation of accessibility; ARIA is the extension. We lean heavily on native semantics, then use ARIA where the visual design exceeds what plain HTML can express. That's the right ratio.

What it means for you

If you're a learner using AccelaStudy AI:

  • Screen reader. Every button, link, input, and interactive control announces with a meaningful name. The Knowledge Map visualization has a text summary describing your concepts mastered, in progress, and not started. The Behavioral Rings (precision, fluency, confidence, curiosity) announce their current values. The exam timer announces minutes remaining politely, and warnings before time runs out are announced assertively.
  • Keyboard only. Every interactive control is reachable by Tab. Activities that involve drag-and-drop (procedural step sequencing, evidence categorization) have a full keyboard mode: Space to grab, arrow keys to move, Enter to drop, Escape to cancel. The activity announces position changes through a live region. The radio group on the subscribe page cycles with arrow keys, per the WAI-ARIA radio pattern.
  • Switch device or voice control. Every interactive element has a name, role, and tab-stop. Voice control software can target controls by their accessible names. Switch-scanning software can step through the interactive surface in a logical order.
  • Magnification. Layouts use rem-based typography that scales with browser font-size settings. The shell adapts to viewport widths down to 320px without horizontal overflow. Tap targets meet WCAG's 44×44 pixel minimum on every interactive control we audited.
  • Reduced motion. Every CSS file in the platform respects prefers-reduced-motion: reduce. Animations stop, transitions shorten, parallax disables. The fireworks overlay that celebrates a passing exam stays celebratory but stops being a problem if your settings request stillness.
  • Cognitive accessibility. Forms group related fields with <fieldset> and <legend>. Errors announce via live regions instead of disappearing into red text. The activity pace adapts to your performance, and the timer is pausable in TimedRecall and PracticeExam where appropriate.

What stays continuous

The work this week was finite. The discipline is continuous. Three things keep us at zero findings:

  1. The audit script lives in CI. It runs on every pull request. A commit that introduces a missing label, a stripped focus ring, or a clickable div without keyboard support fails the check.
  2. The audit spec is a committed document. It defines the rules, the severities, and the fix patterns. Updates to the spec and the script ship in the same commit, so the audit a developer runs is always the audit CI runs.
  3. The codemods are inventory. The Python scripts that did the mass fixes live alongside the audit. The next time a similar pattern surfaces — a new library, a new dashboard, a new activity format — the codemod runs again instead of two thousand manual edits.

We also have an axe-core Playwright sweep across thirty-four routes that runs on the consumer app, catching color-contrast and computed-DOM-state issues the static audit can't. Manual screen-reader passes happen at release boundaries. The combination — deterministic in CI, broader Playwright on integration, manual on release — is what "fully accessible" actually looks like in practice.

What we owe you

If you're a learner using assistive technology and you hit a barrier we missed, we want to know. Email accessibility@accelastudy.com or use the bug-report button in the app (it's keyboard-reachable and labelled "Report a bug"). Every report routes to our accessibility queue and we triage them as gating defects, not nice-to-haves. The audit script catches the mechanical eighty percent. The remaining twenty percent — the contextual stuff a real human doing a real task notices — is exactly the kind of feedback that makes the platform better.

The promise is "every learner." We mean it.