Accessibility

Last updated on 2026-04-05

The Sales Dashboard Kit is built with WCAG AA accessibility as a baseline. Every component and page meets or exceeds these standards, using semantic HTML, ARIA attributes, and accessible interaction patterns throughout all 9 screens.

Every page includes a skip-to-content link as the first focusable element:

import { SkipLink } from "@/components/a11y/skip-link"

<SkipLink />

The skip link is visually hidden until focused. It jumps the user directly to the #main-content landmark, bypassing the sales sidebar and header navigation.

Color Contrast

All text meets WCAG AA contrast ratios:

  • Normal text (< 18px): minimum 4.5:1 contrast ratio
  • Large text (>= 18px bold or >= 24px): minimum 3:1 contrast ratio
  • UI components and states: minimum 3:1 against adjacent colors

The oklch color token system ensures contrast is maintained in both light and dark mode. The sales theme was specifically tuned so that primary-on-background and foreground-on-muted combinations pass AA thresholds. Chart colors are also tested for sufficient contrast against chart backgrounds.

Keyboard Navigation

All interactive elements are keyboard accessible:

  • Tab -- navigate between focusable elements in logical order
  • Shift+Tab -- navigate backwards
  • Enter/Space -- activate buttons, links, and toggles
  • Arrow keys -- navigate within menus, radio groups, tabs, and pipeline columns
  • Escape -- close dialogs, sheets, popovers, and dropdown menus

Pipeline Keyboard Support

The pipeline board supports full keyboard interaction for managing deals across stages:

  • Tab -- move focus between pipeline columns and deal cards
  • Space -- lift and drop a deal card
  • Arrow Left/Right -- move a lifted card between pipeline columns
  • Arrow Up/Down -- reorder a lifted card within the current column
  • Escape -- cancel a drag operation and return the card to its original position

Each pipeline column includes an aria-label describing the stage name and deal count. Screen readers announce when a card is picked up, moved to a new stage, or dropped into position.

Table Keyboard Support

The deals table and leaderboard support keyboard navigation:

  • Tab -- move between interactive elements within table rows (links, buttons, checkboxes)
  • Arrow Up/Down -- navigate between table rows when a row is focused
  • Enter -- activate the primary action on the focused row (view deal detail, view rep profile)
  • Space -- toggle row selection checkbox

Chart Keyboard Support

Charts built with Recharts include keyboard accessibility:

  • Tab -- move focus to chart container
  • Arrow keys -- navigate between data points within a chart
  • Enter -- activate a data point to show its tooltip with detailed values
  • Charts include role="img" and descriptive aria-label attributes summarizing the data trend

Focus Indicators

Visible focus rings appear on all interactive elements using the --ring design token:

:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

Focus Traps

Focus is trapped inside overlay components to prevent keyboard users from tabbing behind them:

  • Dialog -- deal delete confirmation, filter dialogs
  • Sheet -- mobile sidebar navigation
  • Dropdown menus -- card action menus, metric selectors

When these components close, focus returns to the trigger element that opened them.

Screen Reader Support

Semantic HTML

All pages use proper HTML5 landmarks:

  • <header> for the app header
  • <nav> with aria-label for sidebar navigation and mobile navigation
  • <main> for primary content area
  • <aside> for the sidebar
  • <section> with aria-label for dashboard widgets, report sections, and pipeline columns
  • <time> with datetime attribute for deal close dates and activity timestamps
  • <table> with proper <thead>, <tbody>, <th scope> for deal and leaderboard tables

ARIA Labels

Icon-only buttons include descriptive labels:

<Button aria-label="Search deals">
  <Search className="size-4" />
</Button>

<Button aria-label="Switch to dark mode">
  <Moon className="size-5" />
</Button>

<Button aria-label="Add deal to Proposal stage">
  <Plus className="size-4" />
</Button>

Live Regions

The LiveRegion component announces dynamic content changes to screen readers:

import { LiveRegion } from "@/components/a11y/live-region"

<LiveRegion message="Deal moved to Negotiation stage" politeness="polite" />

Live regions are used for deal stage changes (pipeline drag-and-drop), quota milestone announcements, leaderboard rank changes, and filter result count updates.

Heading Hierarchy

Every page follows a strict heading hierarchy:

  • One <h1> per page (the page title)
  • <h2> for major sections
  • <h3> for subsections within those sections
  • No skipped heading levels

For example, the dashboard uses <h1> for "Dashboard", <h2> for "Revenue Overview", "Conversion Funnel", "Quota Attainment", and "Recent Activity" sections.

Touch Targets

All interactive elements meet the 44x44px minimum touch target size. The kit includes a .touch-target utility class:

.touch-target {
  min-width: 44px;
  min-height: 44px;
}

This class is applied to icon buttons in the app header, sidebar navigation items, pipeline card actions, metric toggles, and filter controls on mobile.

Reduced Motion

The kit respects the prefers-reduced-motion media query. When enabled:

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

This disables all animations including pipeline drag-and-drop transitions, chart entrance animations, sidebar collapse/expand transitions, progress bar fill animations, sparkline drawing animations, and hover transforms on deal cards and stat cards.

Status Indicators

Status information is never conveyed by color alone. The kit uses color plus icon plus text:

{/* Deal stage uses icon + text + color */}
<CheckCircle className="size-3 text-chart-4" />
<span className="text-chart-4">Closed Won</span>

{/* Quota at risk uses icon + text + color */}
<AlertTriangle className="size-3 text-destructive" />
<span className="text-destructive">At Risk (62%)</span>

{/* Rank change uses icon + text + color */}
<TrendingUp className="size-3 text-chart-4" />
<span className="text-chart-4">+2 positions</span>

The StageBadge, PriorityBadge, and QuotaProgress components combine color-coded indicators with readable text labels so no information depends solely on color.

Testing Recommendations

Tool Purpose
axe DevTools Automated accessibility scanning
VoiceOver (macOS) Screen reader testing
NVDA (Windows) Screen reader testing
Keyboard-only navigation Tab through every page
Lighthouse Accessibility audit score

Need a professional accessibility review? We run audits for Next.js and React apps starting at $499.