Install
$ agentstack add skill-marvinrichter-clarc-accessibility-patterns-advanced ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo 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 No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ 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.
About
Accessibility Patterns — Advanced
This skill extends accessibility-patterns with screen reader testing, automated testing, and accessible component patterns. Load accessibility-patterns first.
When to Activate
- Running manual screen reader tests (NVDA, VoiceOver, TalkBack)
- Setting up automated a11y testing with axe-core or jest-axe
- Implementing accessible modal, table, form, or data visualization components
Screen Reader Testing
NVDA + Chrome (Windows)
Navigation shortcuts:
H / Shift+H — next/previous heading
F / Shift+F — next/previous form field
B / Shift+B — next/previous button
L / Shift+L — next/previous list
D / Shift+D — next/previous landmark
Tab — next interactive element
Enter/Space — activate button or link
Test checklist:
□ Turn on NVDA (Insert+Escape to toggle speech)
□ Navigate headings with H — is structure logical?
□ Tab through all interactive elements — are labels announced?
□ Submit a form with errors — are errors announced?
□ Open a modal — does focus move inside?
□ Close modal — does focus return to trigger?
VoiceOver + Safari (macOS/iOS)
Navigation shortcuts (VO = Control+Option):
VO+U — Rotor (shows headings, links, landmarks)
VO+Right/Left — next/previous element
VO+Space — activate element
VO+Command+H — next heading
Tab — next interactive element
Test checklist:
□ Open Rotor (VO+U) — are headings and landmarks correct?
□ Navigate to form — are labels associated?
□ Check dynamic content — does VoiceOver announce changes?
□ Test custom widgets — are roles and states announced?
Automated Testing
axe-core + Playwright
// playwright.config.ts
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test.describe('Accessibility', () => {
test('homepage has no critical violations', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa'])
.exclude('.third-party-widget') // Exclude known third-party
.analyze();
// Filter to only serious/critical
const criticalViolations = results.violations.filter(
v => v.impact === 'critical' || v.impact === 'serious'
);
expect(criticalViolations).toEqual([]);
});
test('modal dialog is accessible', async ({ page }) => {
await page.goto('/dashboard');
await page.click('[data-testid="open-modal"]');
await page.waitForSelector('[role="dialog"]');
const results = await new AxeBuilder({ page })
.include('[role="dialog"]')
.analyze();
expect(results.violations).toEqual([]);
});
});
jest-axe (Component Tests)
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
describe('Button component', () => {
it('is accessible', async () => {
const { container } = render(
{}}>Save changes
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
it('icon button has accessible label', async () => {
const { container } = render(
} />
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
});
@axe-core/react (Dev-Mode Warnings)
// index.tsx — dev-mode only
if (process.env.NODE_ENV !== 'production') {
import('@axe-core/react').then(({ default: axe }) => {
axe(React, ReactDOM, 1000); // Check every 1s, log to console
});
}
Automation finds ~30% of real issues. Always supplement with manual keyboard and screen reader testing.
Accessible Component Patterns
Accessible Modal
interface ModalProps {
isOpen: boolean;
onClose: () => void;
title: string;
children: ReactNode;
}
function Modal({ isOpen, onClose, title, children }: ModalProps) {
const containerRef = useRef(null);
useFocusTrap(isOpen, containerRef);
if (!isOpen) return null;
return (
{title}
{children}
✕
);
}
Accessible Table
Monthly sales by region
Region
Q1
Q2
North America
$1.2M
$1.5M
Accessible Form
Email address *
Please enter a valid email address.
Accessible Data Visualization
// Every chart needs a text alternative
function SalesChart({ data }: { data: SalesData[] }) {
return (
Monthly sales 2026 — peaks in Q2 and Q4
{/* Visual chart for sighted users */}
{/* Text table for screen reader users */}
Monthly sales data 2026
MonthSales
{data.map(d => (
{d.month}
{formatCurrency(d.sales)}
))}
);
}
Reference
accessibility-patterns— WCAG criteria, ARIA patterns, keyboard navigation, focus trap, skip linksstorybook-patterns— addon-a11y for story-level accessibility checkse2e-testing— Playwright E2E tests (add axe checks to critical flows)
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: marvinrichter
- Source: marvinrichter/clarc
- License: MIT
- Homepage: https://marvinrichter.github.io/clarc
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.