Automated Accessibility Scanner (Premium) # Automated Accessibility Scanner (Premium) Premium accounts get a client-side accessibility scanner available from two places: the **Run Accessibility Scan** button in a course's admin preview ([player.php](../../../player.php)), and the same button inside the packager tool's Live Preview modal. It checks the content currently on screen and reports issues directly in your browser — nothing is uploaded anywhere. This is a different thing from the human-reviewed **Accessibility Review** add-on described in [Accessibility Review Definitions & Scopes](accessibility-reviews.md). The scanner is automated, instant, and free with your Premium plan; the Review add-on is a paid, human-reviewed audit. Use the scanner for day-to-day authoring checks, and the Review add-on when you need a professional sign-off. ## What it checks - **Color contrast** — flags text under the WCAG AA threshold (4.5:1 for normal text, 3:1 for large text). - **Touch target size** — flags interactive elements smaller than 44×44 pixels. - **Alt text** — flags `<img>` elements with no `alt` attribute (unless marked `aria-hidden`). - **Heading hierarchy** — flags a heading level that skips over one (for example, an `<h2>` followed directly by an `<h4>`). ## Highlighting and the findings list Clicking **Highlight Issues in Content** wraps each flagged element in a labeled region right where it lives on the page — a colored outline for sighted admins, and a named landmark ("Violation: text contrast is 1.61:1...") for anyone navigating by landmark (for example NVDA's `D` key). This isn't a separate visual-only layer sitting on top of the accessible version — it *is* the accessible version, discoverable however you navigate. Next to it, the **findings list** gives you a quick-scan overview: each issue is a focusable list item that jumps you to the offending element, states which WCAG success criterion it relates to, why it matters, and how to fix it. Jumping to an element also drops a **"Back to results list"** button right next to it, so you're never stuck re-navigating from scratch to pick the next issue — the findings list itself is also a landmark, so landmark-cycling gets you there too. ## Fixing what it finds: Copy Fix Prompt and Find in Module Every finding has a **Copy Fix Prompt** button. Click it, and a ready-to-paste prompt is copied to your clipboard — hand it to whichever LLM you already use (ChatGPT, Claude, Gemini, whatever you have open) to write the fix. The prompt includes: - The WCAG issue and why it matters - The exact measured problem (the real contrast ratio, the real pixel size — not a vague description) - The exact HTML of the flagged element, plus its surrounding parent element for context - An instruction to rewrite only that snippet and return the corrected HTML, nothing else There's no AI built into Superable Learning itself, and this doesn't require an API key of your own (BYOK) either — everything in the prompt comes from measurements the scanner already made when it scanned your content. You're free to use whatever LLM you're already comfortable with, the same way you'd paste a code snippet into a chat and ask for help. Once your LLM hands back a fix, you still need to get it into your course. That's what **Find in Module** is for — it only appears in the **packager's** Live Preview (not the read-only admin preview in the course player, since that one has no source to edit). Click it, and the packager closes the preview, jumps to the right module, and — when it can find a match — selects the exact text of the flagged element in that module's content box, ready for you to type or paste your fix directly over the selection. Clicking a finding's module pointer from the course player's admin preview (rather than clicking Find in Module directly) takes you straight into the Packager, opens that exact module's Live Preview, and re-runs the scan automatically — you land right where you'd have ended up clicking through by hand. **A few honest limits, on purpose:** - **Nothing is changed for you.** Find in Module only locates and selects; you still do the actual edit. Nothing gets rewritten automatically. - **It works best on modules authored as plain HTML.** If a module was written in STF or pasted in as LC-JSON, the raw text you're editing isn't the same as the rendered HTML the scanner saw, so an exact match isn't always possible. When that happens, Find in Module says so and shows you the specific text to search for yourself instead of guessing at the wrong spot. - **Findings from inside a component (`<sl-accordion>`, `<sl-tabs>`, and the like) don't get a fix prompt at all.** Those elements' internal markup — a heading, a button, whatever the scanner flagged — is generated by the component's own code at render time, not written in your module. There's nothing there for an LLM to rewrite and nothing to paste back. When this happens, the scanner tells you plainly instead of sending you on a round trip to nowhere: "This comes from the `<component>` component's own generated markup... this is a limitation of the component itself." (A fixed heading level inside a component like this is a known, accepted tradeoff — common in other course-authoring tools too — not something you can fix per-course.) ## Screen Reader Mode — read this before you rely on it **Screen Reader Mode is an approximation, not a certified screen reader test.** (It's called Screen Reader Mode, not "NVDA Mode" — it was never NVDA-specific, and that name overstated a precision it doesn't have.) It has two parts: - **Live bubble**: turning it on shows a floating label as you tab through content, approximating the accessible name, role, and state a screen reader might announce for whatever's currently focused — useful for a real-time "does this match what my own AT just said" comparison. If you're running a real screen reader while this is on, it also announces its guess through your AT directly (prefixed "Simulated:"), specifically so you can judge the guess against what you actually heard, not just read it on screen. - **Accessibility Transcript** (separate button, doesn't require running a scan first): a document-order, plain-text walk of the whole visible page — headings, landmarks, images, links, buttons, form fields, lists, and paragraphs, one line each, the way a screen reader's browse mode would encounter them reading straight through. Unlike the live bubble, this is just a real semantic list once it's generated — read it with your own screen reader at your own pace, nothing simulated at that point. Neither one does the following, in either mode: - Replicate NVDA, JAWS, or VoiceOver's actual announcement wording or timing - Cover everything a real screen reader does (table navigation and some ARIA roles aren't walked yet) - Substitute for real screen reader testing before publishing content that matters A disclaimer banner stays on screen the entire time the live bubble is active, for exactly this reason. For real verification, test with an actual screen reader, or use the human-reviewed **Full WCAG Audit** add-on. ## What it doesn't do (yet) The scanner doesn't store scan history or compare a course against a previous baseline — there's no automated regression testing across course versions today. Each scan reflects only what's currently rendered on screen.