AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Accessibility Audit

skill-nordic-ai-production-readiness-skills-accessibility-audit · by Nordic-AI

Reviews web and application accessibility against WCAG 2.2 AA and the European Accessibility Act (EAA, enforceable June 2025). Covers semantic HTML, ARIA usage, keyboard navigation, focus management, color contrast, screen-reader compatibility, form labels and errors, alternative text, motion and animation preferences, internationalization and localization quality, and testing tool integration (a…

No reviews yet
0 installs
15 views
0.0% view→install

Install

$ agentstack add skill-nordic-ai-production-readiness-skills-accessibility-audit

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access Used
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-nordic-ai-production-readiness-skills-accessibility-audit)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Accessibility Audit? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Accessibility Audit

You review the application's accessibility — whether people with disabilities can use it. The standard is WCAG 2.2 Level AA; for products sold in the EU, the European Accessibility Act (EAA) makes this legally required from June 2025 for a broad category of products and services.

This skill follows the library-wide rules in [docs/CONVENTIONS.md](../../docs/CONVENTIONS.md). Read that first.

Scope

Applies whenever the application has a user interface — web, mobile web, desktop Electron, native mobile if the codebase is visible. Does not apply to backend-only services or internal CLIs (but see release-readiness for operator tooling).

Inputs

From orchestrator: scope_tier, jurisdiction, stack_summary, gitnexus_indexed. Plus:

  • ui_framework: react | vue | angular | svelte | ember | plain-html | ios-native | android-native | flutter | other
  • target_wcag_level: A | AA | AAA (default AA)
  • eaa_in_scope: true | false — does the product fall under the EAA? (e-commerce, banking, transport tickets, e-books, computing hardware + OS, telecoms, AV media services, ATMs, etc.)

If not provided, ask.

Finding ID prefix

A11Y — see CONVENTIONS.md §4.

Tier thresholds

| Tier | WCAG A | WCAG AA | EAA applicable | Auto-testing | Manual screen-reader testing | |---|---|---|---|---|---| | prototype | advisory | advisory | advisory | optional | optional | | team | required | required for user-facing flows | required if applicable | required in CI | recommended | | scalable | required | required everywhere | required if applicable + audited | required with zero-regression gate | required per major release |

Review surface

1. Semantic HTML

Semantic elements carry accessibility for free. Misused `/` is the most common accessibility failure.

  • ` for clickable actions, not `. The former is keyboard-focusable, has proper role, fires on Enter/Space.
  • ` for navigation, not or with onClick={() => navigate(...)}`.
  • Landmark elements: `, , , , — one ` per page.
  • Heading hierarchy `` with no skips.
  • Form structure: ` tied to , + ` for grouped inputs.
  • Lists: ` / for lists, not series of `.
  • Tables: ` with , , ` for data tables. Never for layout.
  • ` for modal dialogs (or well-implemented ARIA dialog pattern), not just a styled `.

2. Keyboard navigation

Every interactive element must be reachable and operable by keyboard.

  • Tab order follows visual order (no surprising jumps).
  • All custom interactive components (role="button", role="menuitem", etc.) handle keyboard — Enter/Space for activation, Arrow keys for navigation in composite widgets, Escape for dismissal.
  • Focus visible — no outline: none without a replacement focus style (WCAG 2.4.7 Focus Visible).
  • No keyboard traps — can always Tab out of every component.
  • Skip links — "Skip to main content" for repetitive navigation.
  • Modal dialogs trap focus inside while open and restore focus on close.
  • Drag-and-drop has a keyboard-accessible alternative (WCAG 2.5.7).

Grep for anti-patterns:

  • tabindex="-1" on things users need to interact with.
  • tabindex="99" etc. — positive tabindex disrupts natural order.
  • onClick on ` / without corresponding onKeyDown and role="button" + tabindex="0"`.
  • outline: none / outline: 0 without :focus-visible replacement.

3. ARIA usage

ARIA is a prosthesis, not an enhancement. Rule of ARIA: "No ARIA is better than bad ARIA."

  • First rule: if you can use a native HTML element, use it — don't reach for ARIA.
  • aria-label / aria-labelledby for elements that need a label but can't have a visible one (icon buttons).
  • aria-describedby for supplementary info (e.g. form hints, error messages).
  • aria-live regions for dynamic updates — polite for most, assertive only for interruptions.
  • aria-hidden="true" only for decorative content; never on focusable elements (breaks the accessibility tree relationship).
  • aria-expanded, aria-selected, aria-checked states on composite widgets.
  • Complex widgets follow the WAI-ARIA Authoring Practices patterns (combobox, tabs, accordion, menu, treeview).

Common anti-patterns:

  • aria-label repeating visible text verbatim (redundant announcement).
  • Missing role on custom widgets.
  • aria-hidden on the entire page / `` while a modal is open (should only hide siblings).
  • Applying role="button" without full keyboard support.

4. Color and contrast

  • WCAG 1.4.3 — text contrast ratio at least 4.5:1 (AA) or 7:1 (AAA) for normal text; 3:1 (AA) or 4.5:1 (AAA) for large text (≥18pt or 14pt bold).
  • WCAG 1.4.11 — non-text UI component contrast at least 3:1 (borders of inputs, icons conveying meaning, focus indicators).
  • Color not the only channel of information (WCAG 1.4.1) — don't rely on red/green alone for error/success. Pair with icon, text, shape.
  • Dark-mode parity — contrast checked in both themes.
  • Tools: axe-core, Chrome DevTools contrast checker, Stark, WebAIM contrast checker.

5. Text and content

  • Resizable to 200% (WCAG 1.4.4) without loss of functionality — avoid fixed pixel sizes on text / container dimensions that clip text.
  • Reflow at 320 CSS pixels width (WCAG 1.4.10) — layouts must adapt, no horizontal scrolling for body content.
  • Line height ≥ 1.5× font size; paragraph spacing ≥ 2× font size; letter spacing ≥ 0.12× font size; word spacing ≥ 0.16× font size — when user adjusts text spacing (WCAG 1.4.12).
  • Plain language where possible; reading level disclosed for complex content.

6. Images, icons, media

  • Alt text on images:
  • Informative images: describe the information the image conveys.
  • Decorative images: alt="" or CSS background + role="presentation".
  • Functional images (image-only buttons, links): describe the action, not the picture.
  • Complex images (charts, diagrams): longer description available via aria-describedby or adjacent text.
  • Avoid alt="image of ..." — screen readers already announce it's an image.
  • Icons: aria-label for standalone icon buttons; aria-hidden="true" on decorative icons accompanied by visible text.
  • SVG: ` inside for accessible name, or aria-label on ` if appropriate.
  • Video:
  • Captions for all pre-recorded audio (WCAG 1.2.2).
  • Audio description for visual information in video (WCAG 1.2.3 / 1.2.5).
  • Transcripts for audio-only media.
  • Controls are keyboard-operable.
  • Autoplay muted or user-initiated; auto-playing audio longer than 3s has a mechanism to pause/mute (WCAG 1.4.2).
  • Live media: captions (WCAG 1.2.4) for live audio at AA.

7. Forms

  • Every input has a ` — not just placeholder` text (disappears on input, low contrast).
  • Required fields marked visually and programmatically (aria-required="true" or required).
  • Error messages:
  • Announced to screen readers (aria-live="polite" region or aria-invalid + aria-describedby pointing to the error).
  • Associated with the failing input.
  • Clear and actionable — "Please enter a valid email address" not "Invalid input".
  • Preserved across submits — don't clear the field the user mistyped in.
  • autocomplete attributes for common fields (WCAG 1.3.5) — name, email, tel, street-address, etc.
  • Input types appropriate — type="email", type="tel", type="date" for better mobile keyboards + semantics.
  • Error prevention for critical actions (WCAG 3.3.4) — confirm, review, or undo for legal / financial submissions.
  • Focus moves to first error on submit failure.

8. Dynamic content

  • Content changes announced via aria-live, not requiring users to detect them.
  • Loading states communicated (aria-busy, loading indicators with accessible names).
  • Toast notifications use role="status" or role="alert" depending on severity, and don't auto-dismiss before slow readers can process them.
  • Infinite scroll has a "load more" fallback or proper virtualization that doesn't break screen readers.

9. Motion and sensory

  • Prefers-reduced-motion respected (WCAG 2.3.3 AAA, but broadly expected at AA level of polish):

``css @media (prefers-reduced-motion: reduce) { ... } ``

  • No content flashes more than 3 times per second (WCAG 2.3.1) — photosensitive epilepsy trigger.
  • Parallax / scroll-linked animations have a preference-based opt-out.
  • Autoplay animations / carousels have pause/stop/hide controls (WCAG 2.2.2).
  • No information conveyed by sound / motion alone.

10. Time limits

  • Session timeouts: user warned before, given time to extend (WCAG 2.2.1).
  • Re-authenticate preserves user's in-progress work.
  • Time-limited interactions (e.g. checkout with limited-duration cart) provide extension / disable option.

11. Navigation and orientation

  • Page title unique and descriptive (WCAG 2.4.2).
  • Multiple ways to reach a page (WCAG 2.4.5) — nav, search, sitemap.
  • Focus order meaningful (WCAG 2.4.3).
  • Link text descriptive out of context (WCAG 2.4.4) — "Read more about X" not "click here".
  • Current location indicated in nav.
  • Breadcrumbs for deep hierarchies.
  • Language declared at document level (`) and on lang-switching elements (bonjour`) — WCAG 3.1.1 / 3.1.2.

12. Mobile / touch

  • Target size ≥ 24×24 CSS pixels (WCAG 2.5.8 AA in WCAG 2.2, ≥ 44×44 advisory).
  • Tap targets with adequate spacing.
  • No drag-only interactions without alternative (WCAG 2.5.7).
  • Pointer cancelation (WCAG 2.5.2) — down-event alone shouldn't trigger critical actions; allow cancel on up-event.
  • Orientation not locked (WCAG 1.3.4) — works in both portrait and landscape unless essential.

13. Authentication

WCAG 2.2 added 3.3.8 Accessible Authentication (Minimum) at AA:

  • Don't require a cognitive function test (memorizing a string, transcribing from an image) unless there's an alternative (e.g. copy-paste allowed, password managers allowed, third-party auth).
  • CAPTCHAs have an alternative form — or, where possible, replace with hCaptcha/Turnstile silent challenges.

14. Screen reader experience

Auto-testing catches maybe 30% of issues. Manual screen reader testing is required at team+ tier for user-facing flows.

  • Tools: NVDA (Windows, free), JAWS (Windows, commercial), VoiceOver (macOS, iOS, built-in), TalkBack (Android, built-in), Narrator (Windows).
  • Flows to test:
  • Signup / login
  • Core transaction (purchase, submit, send)
  • Error paths
  • Modal dialogs
  • Dynamic content updates
  • What to listen for:
  • Announcements make sense out of visual context.
  • No "unlabeled button" / "link".
  • Reading order matches logical order.
  • Focused element's state communicated (expanded/collapsed, selected, disabled).

15. Internationalization (i18n) accessibility

  • Strings externalized, not baked into JSX/HTML as literals that block translation.
  • RTL support (Arabic, Hebrew) — dir="rtl", logical CSS properties (margin-inline-start not margin-left).
  • Plurals / gender handled by the i18n library, not string concatenation.
  • Date / number / currency formatting locale-aware.
  • Icon and imagery culturally appropriate.

16. Testing tooling

  • Automated in CI:
  • axe-core (via jest-axe, @axe-core/playwright, cypress-axe, pa11y).
  • Lighthouse accessibility score as a CI gate (target ≥ 95 AA).
  • eslint-plugin-jsx-a11y for React projects.
  • Framework-specific: @angular-eslint/eslint-plugin-template, Vue a11y eslint plugins.
  • Manual at team+ tier:
  • Keyboard-only pass per release.
  • Screen reader pass per release.
  • Zoom to 200% / 400% pass.
  • User testing with disabled users at scalable tier.

17. Accessibility statement and feedback

  • Accessibility statement published (required under EAA and many public-sector procurement rules). Describes: conformance level, known issues + remediation timeline, alternative access routes, contact for accessibility feedback, date of last review.
  • Feedback channel monitored — users can report barriers.

Category enum (for findings)

  • semantic-html
  • keyboard
  • aria
  • contrast
  • text-scaling
  • media
  • forms
  • dynamic-content
  • motion
  • time-limit
  • navigation
  • mobile-touch
  • authentication
  • screen-reader
  • i18n
  • tooling
  • statement

Severity guidance

| Level | Examples | |---|---| | critical | Critical flow (signup, checkout, submit) impossible with keyboard or screen reader. No alt text on functional images in primary flows. Color the only channel for a critical distinction (e.g. error vs success) in a payment flow. | | high | Form errors not announced. Contrast failing AA on interactive elements. Focus indicator missing. Modal missing focus trap. | | medium | Alt text present but unhelpful. Headings not hierarchical. Language attribute missing. Autoplay carousel without pause. | | low | Minor ARIA redundancy. Decorative icons without aria-hidden. | | info | Observations or WCAG AAA items not targeted. |

Example findings

Example 1 — Keyboard-inaccessible card with click handler

- id: A11Y-003
  severity: high
  category: keyboard
  title: "Product card uses div+onClick, unreachable by keyboard"
  location: "src/components/ProductCard.tsx:24"
  description: |
    ProductCard wraps its content in a `` that navigates
    to the product detail page on click. The element has no tabindex, no
    role, and no keyboard handler. Keyboard users cannot open product
    details, which blocks the core browse-to-purchase flow. VoiceOver
    reports the element as a group, so screen reader users also cannot
    activate it.
  evidence:
    - |
      // src/components/ProductCard.tsx:24
      return (
         navigate(`/p/${slug}`)}>
          
          {title}
          {price}
        
      );
  remediation:
    plan_mode: |
      Replace the click-on-div with a semantic ``
      wrapping the card content. Adjust CSS so the link doesn't inherit
      default underline behavior but retains focus-visible styling. Also
      fix the empty-alt image: provide product name alt, or keep empty if
      the title beneath is sufficient (prefer the latter to avoid repeat).
    edit_mode: |
      Proposed diff replaces div+onClick with ; adjusts card CSS;
      removes redundant onClick handler. Safe — purely structural change.
  references:
    - "WCAG 2.1.1 Keyboard"
    - "WCAG 4.1.2 Name, Role, Value"
    - "WAI-ARIA Authoring Practices — don't use div for navigation"
  wcag_success_criterion: "2.1.1"
  blocker_at_tier: [team, scalable]

Example 2 — Error messages not associated with inputs

- id: A11Y-008
  severity: high
  category: forms
  title: "Signup form errors displayed visually but not announced to screen readers"
  location: "src/components/SignupForm.tsx:55-80"
  description: |
    The signup form shows validation errors in a red box next to each field,
    but the errors aren't associated with their inputs: no `aria-invalid`,
    no `aria-describedby` link, no live region. Screen reader users submit,
    hear nothing, and have no way to discover why submit failed. Testing
    with VoiceOver confirms: focus stays on the Submit button, which is now
    disabled, with no announcement.
  evidence:
    - |
      // src/components/SignupForm.tsx:66
      
      {errors.email && {errors.email}}
  remediation:
    plan_mode: |
      1. Add `aria-invalid={!!errors.email}` to each input.
      2. Give each error `id="email-error"` and add
         `aria-describedby="email-error"` to the input when error exists.
      3. Add a top-of-form `` that summarizes errors on
         submit failure; move focus to this region or to the first
         errored input.
      4. Keep visual red styling — it still serves sighted users.
    edit_mode: |
      Proposed: refactor input component to accept error prop and wire
      aria attributes automatically. Changes apply to all for

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Nordic-AI](https://github.com/Nordic-AI)
- **Source:** [Nordic-AI/production-readiness-skills](https://github.com/Nordic-AI/production-readiness-skills)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.