accessibility | Skill Performance & Reviews | TopRankSkills

TopRank Skills

Home / Skills / tools / accessibility

accessibility

maintained by exceptionless

star 2.4k account_tree 513 verified_user MIT License
bolt View GitHub

name: Accessibility description: | WCAG 2.2 AA accessibility standards for the Exceptionless frontend. Semantic HTML, keyboard navigation, ARIA patterns, focus management, and form accessibility. Keywords: WCAG, accessibility, a11y, ARIA, semantic HTML, keyboard navigation, focus management, screen reader, alt text, aria-label, aria-describedby, skip links, focus trap

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="https://github.com/exceptionless/Exceptionless/blob/main/#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="https://raw.githubusercontent.com/exceptionless/Exceptionless/main//decorative-pattern.svg" alt="accessibility /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([]);
});

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!

Skill Details

GitHub Stars 2.4k
GitHub Forks 513
Created Jan 2026
Last Updated 5个月前
tools tools sales marketing

Related Skills

ui-ux-pro-max
chevron_right
content-prd
chevron_right
ui-ux-pro-max
chevron_right
design-engineer
chevron_right
brand-strategy
chevron_right

Build your own?

Join 12,000+ developers contributing to the Claude ecosystem.