Contents

Chapter 1

Accessibility Guide

This guide explains the accessibility patterns used across every component in the library. Follow these patterns when customizing components to maintain WCAG 2.1 AA compliance.

Core Principles

1. Semantic HTML First

Every component uses the correct HTML element for its purpose. This provides baseline accessibility that works even without JavaScript:

PurposeElementWhy
NavigationScreen readers announce "navigation" landmark
Main content
Allows "skip to content" functionality
Footer
Identified as "contentinfo" landmark
Clickable actionKeyboard-focusable, announces as "button"
Navigation linkAnnounces destination, right-click works
Form field labelClicking the label focuses the input
Modal
Announces as "dialog" to screen readers
Tab interfacerole="tablist" / role="tab"Proper tab semantics

Anti-pattern to avoid: Using

instead of
// We use focus-visible instead of focus so the ring only appears
// during keyboard navigation, not mouse clicks
className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500"

Focus Trapping in Modals:

When a modal opens, Tab should only cycle through elements inside the modal, not escape to the page behind it:

tsx
// The Modal component traps focus by intercepting Tab and Shift+Tab
// and wrapping around to the first/last focusable element
const handleKeyDown = (e: React.KeyboardEvent) => {
  if (e.key !== "Tab") return;
  const focusable = modalRef.current.querySelectorAll<HTMLElement>(
    'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
  );
  // ... wrap focus between first and last
};

Focus Restoration:

When a modal or slide-over closes, focus should return to the element that opened it:

tsx
const previousFocusRef = useRef<HTMLElement | null>(null);

useEffect(() => {
  if (isOpen) {
    previousFocusRef.current = document.activeElement as HTMLElement;
  } else {
    previousFocusRef.current?.focus();
  }
}, [isOpen]);

4. ARIA Attributes Reference

AttributeWhere UsedPurpose
aria-labelIcon-only buttonsProvides accessible name
aria-labelledbyModals, sectionsLinks element to its heading
aria-describedbyForm inputsLinks to error/helper text
aria-requiredRequired inputsAnnounces "required"
aria-invalidInputs with errorsAnnounces "invalid entry"
aria-expandedDropdowns, accordionsAnnounces open/closed state
aria-controlsTabs, accordionsLinks trigger to content
aria-selectedTabs, list itemsAnnounces selected state
aria-current="page"Navigation linksAnnounces current page
aria-sortTable headersAnnounces sort direction
aria-live="polite"Toast/alertsAnnounces dynamic content
aria-modal="true"ModalsMarks as modal dialog
role="alert"Error messagesImmediate announcement
role="status"Success messagesPolite announcement
role="switch"Toggle switchesAnnounces as switch

5. Color and Contrast

Minimum Contrast Ratios (WCAG AA):

Text TypeRequired RatioOur Default
Normal text (< 18px)4.5:15.1:1+
Large text (>= 18px)3:14.2:1+
UI components (borders, icons)3:13.5:1+

Never rely on color alone to convey information:

tsx
// Bad: Color is the only indicator
<span className="text-red-500">Error</span>

// Good: Icon + color + text
<span className="text-danger-600">
  <ErrorIcon /> Error: Field is required
</span>

6. Motion and Animation

All animations respect the user's motion preference:

css
/* In your global CSS */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Or per-component with Tailwind:

tsx
className="motion-safe:animate-fade-in motion-reduce:animate-none"

Testing Accessibility

Automated Testing

Run these on every build:

1. axe-core — Catches ~30% of accessibility issues

bash
   npm install -D @axe-core/react

2. eslint-plugin-jsx-a11y — Catches issues at lint time

bash
   npm install -D eslint-plugin-jsx-a11y

Manual Testing Checklist

1. Tab through the page — Can you reach every interactive element? Is the tab order logical?

2. Use a screen reader — VoiceOver (Mac), NVDA (Windows), or JAWS. Does it announce elements correctly?

3. Zoom to 200% — Does the layout still work? Is text readable?

4. Turn off CSS — Does the content still make sense?

5. Use keyboard only — Can you complete every task without a mouse?

6. Check color contrast — Use the browser's DevTools accessibility inspector

Screen Reader Testing Tips

PlatformScreen ReaderToggle
macOSVoiceOverCmd + F5
WindowsNVDAFree download from nvaccess.org
WindowsNarratorWin + Ctrl + Enter
ChromeChromeVoxExtension

Part of Frontend Developer Pro

Chapter 2
🔒 Available in full product

Customization Guide

Chapter 3
🔒 Available in full product

Accessibility Guide

Chapter 4
🔒 Available in full product

Customization Guide

You’ve reached the end of the free preview

Get the full Tailwind Component Library and unlock everything.

All Chapters

Get the complete guide with every chapter unlocked, including code samples, diagrams, and best practices.

Full Tool Suite

Access all interactive tools with complete data, all workload profiles, and the full scenario library.

Source Files

Downloadable source code, configuration files, and working examples from every chapter.

Lifetime Updates

Free updates for life. Every new chapter, tool, and improvement included.

Buy Now — $39 →
📦 Free sample included — download another copy or visit the store for the full product.
Tailwind Component Library v1.0.0 — Free Preview