# Accessibility Patterns Advanced

> Advanced accessibility patterns — screen reader testing (NVDA/VoiceOver/TalkBack checklists), automated testing (axe-core+Playwright, jest-axe, @axe-core/react dev warnings), and accessible component implementations (modal, table, form, data visualization).

- **Type:** Skill
- **Install:** `agentstack add skill-marvinrichter-clarc-accessibility-patterns-advanced`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [marvinrichter](https://agentstack.voostack.com/s/marvinrichter)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [marvinrichter](https://github.com/marvinrichter)
- **Source:** https://github.com/marvinrichter/clarc/tree/main/skills/accessibility-patterns-advanced
- **Website:** https://marvinrichter.github.io/clarc

## Install

```sh
agentstack add skill-marvinrichter-clarc-accessibility-patterns-advanced
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## 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

```typescript
// 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)

```typescript
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)

```typescript
// 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

```tsx
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

```html

  Monthly sales by region
  
    
      Region
      Q1
      Q2
    
  
  
    
      North America
      $1.2M
      $1.5M
    
  

```

### Accessible Form

```html

  
    Email address *
    
    
      Please enter a valid email address.
    
  

```

### Accessible Data Visualization

```tsx
// 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 links
- `storybook-patterns` — addon-a11y for story-level accessibility checks
- `e2e-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](https://github.com/marvinrichter)
- **Source:** [marvinrichter/clarc](https://github.com/marvinrichter/clarc)
- **License:** MIT
- **Homepage:** https://marvinrichter.github.io/clarc

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

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-marvinrichter-clarc-accessibility-patterns-advanced
- Seller: https://agentstack.voostack.com/s/marvinrichter
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
