Agent skill
accessibility
Use this skill when building or reviewing frontend components for accessibility compliance. Covers WCAG 2.2 AA standards including semantic HTML, keyboard navigation, ARIA patterns, focus management, screen reader support, and form accessibility. Apply when creating new UI components, fixing accessibility bugs, adding skip links or focus traps, or ensuring inclusive markup — even if the user doesn't explicitly mention "a11y" or "WCAG."
Install this agent skill to your Project
npx add-skill https://github.com/exceptionless/Exceptionless/tree/main/.agents/skills/accessibility
SKILL.md
Accessibility (WCAG 2.2 AA)
Core Principles
- Semantic HTML elements and ARIA landmarks
- Keyboard-first navigation with visible focus states
- Skip links for main content in layouts
- Inclusive, people-first language
Semantic HTML
<!-- Use semantic elements -->
<header>
<nav aria-label="Main navigation">
<a href="/dashboard">Dashboard</a>
<a href="/projects">Projects</a>
</nav>
</header>
<main id="main-content">
<h1>Page Title</h1>
<section aria-labelledby="section-heading">
<h2 id="section-heading">Section Title</h2>
<article>...</article>
</section>
</main>
<footer>...</footer>
Skip Links
<!-- At top of layout -->
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute ...">
Skip to main content
</a>
Form Accessibility
Label Every Control
<!-- Visible label -->
<label for="email">Email address</label>
<input id="email" type="email" />
<!-- Or using aria-label for icon-only inputs -->
<input type="search" aria-label="Search events" />
Required Fields
<label for="name">Name <span aria-hidden="true">*</span></label>
<input id="name" required aria-required="true" />
Error Messages
<input
id="email"
aria-invalid={hasError}
aria-describedby={hasError ? 'email-error' : undefined}
/>
{#if hasError}
<p id="email-error" class="text-destructive">
Please enter a valid email address
</p>
{/if}
Validation Behavior
- On validation failure: focus first invalid input
- Never disable submit just to block validation
- Show inline errors linked via
aria-describedby
Keyboard Navigation
Focus Order
<!-- Natural tab order follows DOM order -->
<button>First</button>
<button>Second</button>
<button>Third</button>
<!-- Remove from tab order when hidden -->
<div hidden>
<button tabindex="-1">Hidden button</button>
</div>
Focus Management in Dialogs
// When dialog opens, focus first interactive element
$effect(() => {
if (open) {
dialogRef?.querySelector("input, button")?.focus();
}
});
// When dialog closes, return focus to trigger
const triggerRef = document.activeElement;
// ... on close
triggerRef?.focus();
Keyboard Shortcuts
<button
onkeydown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleClick();
}
}}
>
Action
</button>
Images and Icons
Informative Images
<img src={user.avatar} alt={`Profile photo of ${user.name}`} />
Decorative Images
<img src="/decorative-pattern.svg" alt="" aria-hidden="true" />
Icon Buttons
<button aria-label="Delete event">
<TrashIcon aria-hidden="true" />
</button>
Icons with Text
<button>
<PlusIcon aria-hidden="true" />
Add Event
</button>
ARIA Patterns
Live Regions
<!-- For dynamic updates (notifications, loading states) -->
<div aria-live="polite" aria-atomic="true">
{#if loading}
Loading events...
{/if}
</div>
<!-- For urgent messages -->
<div role="alert">
Error: Failed to save changes
</div>
Expandable Content
<button
aria-expanded={isExpanded}
aria-controls="panel-content"
>
{isExpanded ? 'Collapse' : 'Expand'}
</button>
<div id="panel-content" hidden={!isExpanded}>
Panel content
</div>
Tabs
<div role="tablist" aria-label="Event tabs">
<button role="tab" aria-selected={activeTab === 'details'}>
Details
</button>
<button role="tab" aria-selected={activeTab === 'stack'}>
Stack Trace
</button>
</div>
<div role="tabpanel" aria-labelledby="details-tab">
Tab content
</div>
Color and Contrast
- Minimum contrast ratio: 4.5:1 for normal text
- 3:1 for large text and UI components
- Don't rely on color alone to convey information
<!-- ✅ Good: Icon + color + text -->
<span class="text-destructive">
<AlertIcon aria-hidden="true" />
Error: Invalid input
</span>
<!-- ❌ Bad: Color only -->
<span class="text-destructive">Invalid input</span>
Testing Accessibility
# Run axe-playwright audits in E2E tests
npm run test:e2e
// In Playwright tests
import AxeBuilder from "@axe-core/playwright";
test("page is accessible", async ({ page }) => {
await page.goto("/dashboard");
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
foundatio-repositories
releasenotes
Generate formatted changelogs from git history since the last release tag. Use when preparing release notes that categorize changes into breaking changes, features, fixes, and other sections.
e2e-testing
Use this skill when writing or running end-to-end browser tests with Playwright. Covers Page Object Model patterns, selector strategies (data-testid, getByRole, getByLabel), fixtures, and accessibility audits with axe-playwright. Apply when adding E2E test coverage, debugging flaky tests, or testing user flows through the browser.
tanstack-query
Use this skill when fetching data, managing server state, or handling API mutations in the Svelte frontend. Covers createQuery, createMutation, query keys, cache invalidation, optimistic updates, and WebSocket-driven refetching. Apply when adding API calls, managing loading/error states, or coordinating cache updates after mutations.
dogfood
Systematically explore and test a web application to find bugs, UX issues, and other problems. Use when asked to "dogfood", "QA", "exploratory test", "find issues", "bug hunt", "test this app/site/platform", or review the quality of a web application. Produces a structured report with full reproduction evidence -- step-by-step screenshots, repro videos, and detailed repro steps for every issue -- so findings can be handed directly to the responsible teams.
storybook
Use this skill when creating or updating Storybook stories for Svelte components. Covers Svelte CSF story format, defineMeta, argTypes, snippet-based customization, and autodocs. Apply when adding visual documentation for components, setting up story files, or running Storybook for development.
Didn't find tool you were looking for?