Loading...
Loading...
Audit and fix RGAA 4.1.2 accessibility issues in any web framework that outputs HTML: React, Vue, Svelte, Astro, Angular, Next.js, Nuxt, SvelteKit, plain HTML, Handlebars, ERB, Nunjucks, and similar. Activates proactively whenever a developer writes, modifies, generates, or refactors any component or template — even without explicit mention of accessibility. Triggers on: "create a component", "add a form", "refactor this header", "add a data table", "add a nav", "build a layout", "audit accessibility", "check a11y", "RGAA", "is this accessible", "make WCAG compliant", "fix accessibility issues", or any request to write/review .jsx/.tsx/.vue/.svelte/.astro/.html files. Covers static code only: images alt text, colors, tables, links, mandatory elements, information structure, forms, navigation landmarks.
npx skill4agent add clubmediterranee/ai-core a11y-web.jsx.tsx.vue.svelte.astro.html.htm.erb.njk.hbs| Concept | React/JSX | Vue / Svelte / Astro / HTML |
|---|---|---|
| Label association | | |
| CSS class | | |
| Autocomplete | | |
| ARIA attributes | | same in all frameworks |
| Event handlers | irrelevant (static only) | irrelevant (static only) |
# Discover component/template files
Glob: src/**/*.{jsx,tsx} # React
Glob: src/**/*.vue # Vue
Glob: src/**/*.svelte # Svelte
Glob: src/**/*.astro # Astro
Glob: **/*.{html,htm} # Plain HTML / Angular templates
Glob: **/*.{erb,njk,hbs} # Server-side templates
# Root layout / app shell — check for Topic 8 and landmarks
Glob: src/App.{jsx,tsx,vue,svelte}
Glob: src/app/layout.{jsx,tsx} # Next.js App Router
Glob: src/routes/+layout.svelte # SvelteKit
Glob: src/layouts/*.{astro,html,vue}.jsx.tsx.vue.svelte.astro.htmlreferences/rgaa-static-criteria.md# 1.1 img without alt attribute
Pattern: <img(?![^>]*\balt=)
Files: *.{jsx,tsx,vue,svelte,astro,html,htm,erb,njk,hbs}
# 1.2 Decorative img: alt="" but missing aria-hidden="true" or role="presentation"
Pattern: alt=""
→ On same element, verify aria-hidden="true" OR role="presentation" is present
# 1.1 SVG without accessible name
Pattern: <svg(?![^>]*aria-label)(?![^>]*aria-labelledby)
→ Check if a <title> child exists inside the SVG block
# 1.6/1.7 Complex images (charts, infographics)
Pattern: <img
→ Flag imgs appearing to be charts/diagrams without aria-describedby or figcaption# 3.1 Color-only information
Pattern: style=.*color
→ Flag for manual review: verify information is not conveyed by color alone[MANUAL]# 5.3 Layout table without role="presentation"
Pattern: <table(?![^>]*role=)
# 5.4 Table without <caption>
Pattern: <table
→ Check for <caption> as first child
# 5.6/5.7 th without scope
Pattern: <th(?![^>]*\bscope=)# 6.1 Empty link text
Pattern: <a\b[^>]*>\s*</a>
# 6.1 Ambiguous link text (case-insensitive)
Pattern: >click here<|>read more<|>learn more<|>here<
# 6.2 Image link: verify img has non-empty alt
Pattern: <a\b[^>]*><img
→ Verify the img has a non-empty alt describing the destination# 8.3/8.4 html element without lang
Pattern: <html(?![^>]*\blang=)
Files: **/*.{html,htm,jsx,tsx,vue,svelte,astro}
# 8.5/8.6 Page title
Pattern: <title → in HTML files, verify non-empty
Pattern: <Helmet|<Head → React / Next.js
Pattern: <svelte:head → SvelteKit
Pattern: <head> → Astro/Vue layouts
→ Check for <title> inside
# 8.1 Charset
Pattern: <meta\s+charset
Files: **/*.{html,htm}# 9.1 Heading inventory
Pattern: <h[1-6]
→ Count h1 occurrences (flag if 0 or >1 in main layout)
→ List all levels found; flag skipped levels
# 9.3 Presentational elements
Pattern: <b>|<i>
→ Suggest <strong>/<em> if semantic meaning is intended[MANUAL][MANUAL]# 11.1 Input/select/textarea without label
Pattern: <input(?![^>]*type="hidden")(?![^>]*aria-label)(?![^>]*aria-labelledby)
Pattern: <select(?![^>]*aria-label)(?![^>]*aria-labelledby)
Pattern: <textarea(?![^>]*aria-label)(?![^>]*aria-labelledby)
→ Cross-check: does a <label for/htmlFor="id"> exist with matching id?
# 11.2 Placeholder without label
Pattern: placeholder=
→ Verify a <label> also exists for the same field
# 11.5/11.6 Radio/checkbox without fieldset+legend
Pattern: type="radio"|type="checkbox"
→ Check for wrapping <fieldset> with <legend>
# 11.10 Required field not indicated
Pattern: required
→ Verify visible text/symbol AND aria-required="true"
# 11.13 Personal data fields without autocomplete
Pattern: type="email"|type="tel"|name="email"|name="phone"|name="firstname"|name="lastname"
→ Verify autocomplete / autoComplete attribute present# 12.6 Landmark presence
Pattern: <main
Pattern: <nav
Pattern: <header
Pattern: <footer
→ Flag if absent from app/layout component
# 12.6 Multiple nav without accessible name
Pattern: <nav(?![^>]*aria-label)(?![^>]*aria-labelledby)
→ Flag if more than one <nav> found without labels
# 12.7/12.8 Skip link
Pattern: skip|eviter|aller.au.contenu (case-insensitive)
→ Flag if absent, pointing to #main-content## RGAA Accessibility Audit — [filename or "Project"]
Framework: [React | Vue | Svelte | Astro | HTML | ...]
Date: YYYY-MM-DD
### Topic 1 — Images
[FAIL] RGAA 1.1 — src/components/Hero.tsx:14
<img src="..." /> is missing an alt attribute.
Fix: alt="Descriptive text" (informative) or alt="" aria-hidden="true" (decorative)
### Topic 3 — Colors
[MANUAL] RGAA 3.2 — Contrast ratios cannot be verified statically.
Action: Run axe-core, Lighthouse, or check via DevTools > Accessibility.
---
Summary: X violations (Y FAIL, Z WARN, W MANUAL)
Reference: https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/[FAIL][WARN][MANUAL][FAIL][WARN]HTML / Vue / Svelte / AstroReact (JSX)<!-- Informative image — all frameworks -->
<img src="chart.png" alt="Bar chart: revenue grew 12% in Q3" />
<!-- Decorative image — all frameworks -->
<img src="divider.svg" alt="" aria-hidden="true" />
<!-- Informative SVG — all frameworks -->
<svg aria-label="Bar chart: revenue grew 12%" role="img" viewBox="0 0 100 100">
<title>Bar chart: revenue grew 12%</title>
</svg>
<!-- Decorative SVG — all frameworks -->
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">...</svg><!-- Ambiguous text — HTML/Vue/Svelte/Astro -->
<a href="/article/123" aria-label="Read full article: Paris Resort Review">Read more</a>
<!-- Image link — all frameworks -->
<a href="/home"><img src="logo.png" alt="Club Med — Home" /></a><label for="email">Email address</label>
<input id="email" type="email" name="email" autocomplete="email" />
<!-- Required field -->
<label for="name">Full name <span aria-hidden="true">*</span></label>
<input id="name" type="text" required aria-required="true" />
<!-- Radio group -->
<fieldset>
<legend>Preferred contact method</legend>
<label><input type="radio" name="contact" value="email" /> Email</label>
<label><input type="radio" name="contact" value="phone" /> Phone</label>
</fieldset>// React uses htmlFor and autoComplete (camelCase)
<label htmlFor="email">Email address</label>
<input id="email" type="email" name="email" autoComplete="email" />
<label htmlFor="name">Full name <span aria-hidden="true">*</span></label>
<input id="name" type="text" required aria-required="true" /><!-- First element in DOM -->
<a href="#main-content" class="skip-link">Skip to main content</a>
<header>
<nav aria-label="Main navigation">...</nav>
</header>
<main id="main-content">
<h1>Page title</h1>
</main>
<aside aria-label="Related resources">...</aside>
<footer>...</footer>
<!-- Multiple navs — each needs a unique aria-label -->
<nav aria-label="Main navigation">...</nav>
<nav aria-label="Footer links">...</nav><table>
<caption>Hotel rates by season — 2025</caption>
<thead>
<tr>
<th scope="col">Hotel</th>
<th scope="col">Low season</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Punta Cana</th>
<td>1 200€</td>
</tr>
</tbody>
</table><!-- Plain HTML -->
<html lang="fr">
<head>
<meta charset="UTF-8" />
<title>Page Title — Site Name</title>
</head>// React — Next.js App Router
export const metadata = { title: 'Page Title — Site Name' };
// React — Next.js Pages Router / react-helmet
<Head><title>Page Title — Site Name</title></Head><!-- Vue / Nuxt -->
<Head><Title>Page Title — Site Name</Title></Head><!-- SvelteKit -->
<svelte:head><title>Page Title — Site Name</title></svelte:head><!-- Astro -->
<html lang="fr">
<head>
<meta charset="UTF-8" />
<title>Page Title — Site Name</title>
</head>| Criterion | Why it needs manual review |
|---|---|
| RGAA 3.1 | Color-only info requires visual inspection |
| RGAA 3.2 | Contrast ratios require rendered colors |
| RGAA 10.1 | Shape/position-only info requires visual review |
| RGAA 10.4 | Text resize to 200% requires browser interaction |
| RGAA 12.4 | Breadcrumb presence requires site-level context |
axe-corereferences/rgaa-static-criteria.md