| name | accessibility-reviewer-assessments |
| description | Reviews educational assessment interfaces for WCAG 2.2 Level AA compliance and assessment-specific accessibility needs. Use when implementing new interactions, reviewing UI changes, or conducting accessibility audits of test-taking interfaces. |
Accessibility Reviewer for Assessments
This skill helps review educational assessment component libraries for accessibility compliance, with special focus on K-12 learners, web components/custom elements, and reusable UI interactions distributed as NPM packages.
When to Use This Skill
Invoke this skill when:
- Implementing new interaction types or question formats as reusable components
- Reviewing web components or HTML custom elements
- Conducting accessibility audits of UI component libraries
- Ensuring WCAG 2.2 Level AA compliance for distributed packages
- Reviewing math content (MathML, LaTeX) accessibility
- Evaluating keyboard navigation for educational interactions
- Checking screen reader compatibility across different integration contexts
- Reviewing for K-12 accessibility needs (younger learners, diverse abilities)
- Assessing components that will be consumed as ESM modules or included as source
Component Library Accessibility Considerations
Educational assessment components have unique accessibility requirements beyond standard web content:
Component Integration Context
- Multiple integration patterns: Components may be consumed as ESM modules, web components, or compiled from source
- Shadow DOM considerations: Web components using shadow DOM need careful ARIA and focus management
- Host application context: Components must work accessibly regardless of how clients integrate them
- Style isolation: Ensure accessibility features (focus indicators, contrast) work with or without shadow DOM
- Custom element lifecycle: Proper ARIA updates during connected/disconnected callbacks
K-12 Learners
- Younger students: Simpler language, larger touch targets, forgiving interactions
- Cognitive load: Minimize distractions, clear instructions, consistent patterns
- Reading levels: Support for text-to-speech, simplified language options
- Motor skills: Larger interaction areas, forgiving drag-and-drop, keyboard alternatives
Interaction Types
- Drag-and-drop: Must have keyboard alternatives (arrow keys, Enter/Space to pick/drop)
- Drawing/hotspot: Alternative input methods for motor impairments
- Math input: Accessible equation editors, LaTeX/MathML screen reader support
- Multimedia: Captions, transcripts, audio descriptions where needed
- Web component slots: Ensure slotted content maintains proper accessibility tree
WCAG 2.2 Level AA Review Checklist
1. Perceivable
1.1 Text Alternatives (Level A)
Example Issues to Catch:
<!-- ❌ Missing alt text on question image -->
<img src="diagram.png" />
<!-- ❌ Alt text gives away answer -->
<img src="triangle.png" alt="equilateral triangle" />
<!-- ✅ Descriptive without revealing answer -->
<img src="triangle.png" alt="A triangle with three sides and three angles" />
<!-- ✅ Decorative image properly marked -->
<img src="decorative-border.png" alt="" role="presentation" />
1.2 Time-based Media (Level A)
1.3 Adaptable (Level A)
Example Issues to Catch:
<!-- ❌ Relies on visual position -->
<p>Select the answer in the top-right box</p>
<!-- ✅ Position-independent instructions -->
<p>Select the answer labeled "B"</p>
<!-- ❌ Structure not programmatic -->
<div class="heading">Question 1</div>
<!-- ✅ Semantic structure -->
<h2>Question 1</h2>
<!-- ❌ Instructions rely on color -->
<p>Click the green button to continue</p>
<!-- ✅ Color-independent -->
<p>Click the "Continue" button (highlighted in green) to proceed</p>
1.4 Distinguishable (Level A/AA)
Example Issues to Catch:
.choice-option {
color: #999;
background: #fff;
}
.choice-option {
color: #595959;
background: #fff;
}
.drag-handle {
width: 30px;
height: 30px;
}
.drag-handle {
width: 44px;
height: 44px;
}
2. Operable
2.1 Keyboard Accessible (Level A)
Educational interaction keyboard patterns:
Example Issues to Catch:
<!-- ❌ Click handler without keyboard support -->
<div on:click={selectChoice}>Choice A</div>
<!-- ✅ Keyboard accessible -->
<button on:click={selectChoice}>Choice A</button>
<!-- ✅ Custom keyboard support for drag-and-drop -->
<div
role="button"
tabindex="0"
on:keydown={(e) => {
if (e.key === ' ' || e.key === 'Enter') {
toggleGrab();
}
}}
>
Draggable item
</div>
2.2 Enough Time (Level A)
Example Issues to Catch:
<!-- ❌ Hard time limit without extension -->
<Timer duration={60} onExpire={submitAssessment} />
<!-- ✅ Configurable time with extensions -->
<Timer
duration={timeLimit}
allowExtensions={true}
extensionMultiplier={1.5}
maxExtensions={2}
onExpire={handleTimeUp}
/>
2.3 Seizures and Physical Reactions (Level A)
2.4 Navigable (Level A/AA)
Example Issues to Catch:
<!-- ❌ Missing skip link -->
<nav><!-- Navigation --></nav>
<main><!-- Assessment content --></main>
<!-- ✅ Skip link present -->
<a href="#main-content" class="skip-link">Skip to assessment</a>
<nav><!-- Navigation --></nav>
<main id="main-content"><!-- Assessment content --></main>
<!-- ❌ Focus indicator removed -->
<style>
button:focus { outline: none; }
</style>
<!-- ✅ Clear focus indicator -->
<style>
button:focus-visible {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
</style>
2.5 Input Modalities (Level A/AA)
Example Issues to Catch:
<!-- ❌ Touch target too small: 20×20px -->
<button style="width: 20px; height: 20px;">×</button>
<!-- ✅ WCAG 2.2 compliant: 44×44px -->
<button style="width: 44px; height: 44px;" aria-label="Close">×</button>
<!-- ❌ Drag-only interaction -->
<div draggable="true" on:drag={handleDrag}>
Drag to reorder
</div>
<!-- ✅ Keyboard alternative provided -->
<div
draggable="true"
role="button"
tabindex="0"
on:drag={handleDrag}
on:keydown={handleKeyboardReorder}
>
Drag to reorder or use arrow keys
</div>
3. Understandable
3.1 Readable (Level A/AA)
Example Issues to Catch:
<html>
<html lang="en">
<p>The French phrase "bonjour" means hello.</p>
<p>The French phrase <span lang="fr">bonjour</span> means hello.</p>
3.2 Predictable (Level A/AA)
Example Issues to Catch:
<!-- ❌ Focus triggers navigation -->
<button on:focus={goToNextQuestion}>Next</button>
<!-- ✅ Explicit action required -->
<button on:click={goToNextQuestion}>Next</button>
<!-- ❌ Inconsistent button labels -->
<!-- On item 1: --><button>Continue</button>
<!-- On item 2: --><button>Next</button>
<!-- On item 3: --><button>Proceed</button>
<!-- ✅ Consistent labeling -->
<button>Next Question</button>
3.3 Input Assistance (Level A/AA)
Example Issues to Catch:
<!-- ❌ Vague error message -->
<div role="alert">Invalid input</div>
<!-- ✅ Specific, actionable error -->
<div role="alert">
Please enter a number between 1 and 100. You entered "abc".
</div>
<!-- ❌ Submit without confirmation -->
<button on:click={submitAssessment}>Submit Test</button>
<!-- ✅ Confirmation before irreversible action -->
<button on:click={confirmSubmit}>Submit Test</button>
{#if showConfirmation}
<dialog>
<p>Are you sure you want to submit? You cannot change answers after submitting.</p>
<button on:click={submitAssessment}>Yes, Submit</button>
<button on:click={cancelSubmit}>No, Go Back</button>
</dialog>
{/if}
4. Robust
4.1 Compatible (Level A/AA)
Example Issues to Catch:
<!-- ❌ Custom component without ARIA -->
<div class="checkbox" on:click={toggle}>
{#if checked}✓{/if}
</div>
<!-- ✅ Proper ARIA attributes -->
<div
role="checkbox"
aria-checked={checked}
tabindex="0"
on:click={toggle}
on:keydown={handleKey}
>
{#if checked}✓{/if}
</div>
<!-- ❌ Status update not announced -->
<div>Answer saved</div>
<!-- ✅ Status announced to screen readers -->
<div role="status" aria-live="polite">
Answer saved
</div>
Component Library Patterns
Web Component with Shadow DOM
class ChoiceInteraction extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open', delegatesFocus: true });
}
connectedCallback() {
this.setAttribute('role', 'radiogroup');
this.setAttribute('aria-label', this.getAttribute('label') || 'Select an answer');
this.render();
}
}
Choice Interactions
<!-- ✅ Accessible radio/checkbox group -->
<fieldset>
<legend>Which of the following is a prime number?</legend>
{#each choices as choice, i}
<label>
<input
type="radio"
name="question-1"
value={choice.id}
checked={selected === choice.id}
/>
{choice.text}
</label>
{/each}
</fieldset>
Drag-and-Drop Interactions
<!-- ✅ Keyboard-accessible drag-and-drop -->
<div
role="button"
tabindex="0"
aria-grabbed={isGrabbed}
aria-label="Draggable item: {label}. Press space to pick up."
on:keydown={(e) => {
if (e.key === ' ') {
e.preventDefault();
toggleGrab();
} else if (isGrabbed && e.key.startsWith('Arrow')) {
e.preventDefault();
moveWithKeyboard(e.key);
}
}}
>
{label}
</div>
<!-- Screen reader feedback -->
<div role="status" aria-live="assertive" aria-atomic="true">
{#if isGrabbed}
{label} picked up. Use arrow keys to move, space to drop.
{:else if justDropped}
{label} dropped.
{/if}
</div>
Math Content
<!-- ✅ Accessible math with MathML and fallback -->
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mrow>
<mi>x</mi>
<mo>=</mo>
<mfrac>
<mrow><mo>−</mo><mi>b</mi></mrow>
<mrow><mn>2</mn><mi>a</mi></mrow>
</mfrac>
</mrow>
</math>
<span class="sr-only">
x equals negative b divided by 2a
</span>
<!-- Or with aria-label -->
<div class="math-formula" aria-label="x equals negative b over 2a">
[rendered LaTeX]
</div>
Timer Warnings
<!-- ✅ Accessible time warnings -->
<div role="timer" aria-live="polite" aria-atomic="true">
{#if minutesRemaining <= 5}
<span aria-label="Warning: {minutesRemaining} minutes remaining">
⚠️ {minutesRemaining}:00
</span>
{:else}
{minutesRemaining}:00
{/if}
</div>
<!-- Additional aria-live region for critical warnings -->
{#if minutesRemaining === 1}
<div role="alert" aria-live="assertive">
Warning: Only 1 minute remaining
</div>
{/if}
Review Process
When conducting an accessibility review:
-
Keyboard Navigation Test
- Tab through entire interface without mouse
- Verify all interactions work with keyboard
- Check focus indicators are visible
- Test logical tab order
-
Screen Reader Test
- Use VoiceOver (Mac), NVDA (Windows), or JAWS
- Verify all content is announced
- Check ARIA labels make sense
- Test with eyes closed if possible
-
Color/Contrast Check
- Use browser DevTools or WebAIM contrast checker
- Verify 4.5:1 for text, 3:1 for UI components
- Test with color blindness simulators
-
Touch Target Audit
- Verify all interactive elements are at least 44×44px
- Check spacing between adjacent targets
-
Code Review
- Check HTML semantics (heading hierarchy, landmarks, form structure)
- Review ARIA usage (roles, states, properties)
- Verify alt text and labels
-
Automated Testing
- Run axe-core or similar tool
- Review Playwright accessibility test results
- Check for ARIA violations
Output Format
Provide feedback in this structure:
✅ Accessibility Strengths
- What's working well
- Good patterns to reinforce
🚨 Critical Issues (WCAG Violations)
For each violation:
- WCAG Criterion: e.g., 1.4.3 Contrast (Level AA)
- Severity: Blocker / High / Medium
- Location: File and line number or component name
- Issue: What's wrong
- Example: Code showing the violation
- Fix: Specific solution with code
⚠️ Assessment-Specific Concerns
- Test-taking context issues
- K-12 learner considerations
- Interaction type accessibility
💡 Enhancements
- Optional improvements beyond WCAG AA
- Level AAA considerations
- UX improvements for accessibility
Tool Usage
- Examine Svelte components, CSS files, rendered markup, and Playwright specs.
- Search for ARIA attributes, alt attributes, roles, focus handling, keyboard handlers, and
axe usage.
- Run the repo's relevant Bun or Playwright checks when validation is in scope.
Testing Commands
bun run test:e2e:a11y:critical
bun run test:e2e:section-player
bun run test:e2e:item-player
bun run test:e2e:assessment-player
bun run test
Run Playwright-backed commands outside the sandbox with
required_permissions: ["all"].
Resources