Usage Guide
Accessibility
TypeScript UI components are built with accessibility in mind, following WCAG 2.1 guidelines and implementing proper ARIA attributes for assistive technologies.
Focus Management
Visible Focus States
All interactive elements include visible focus indicators:
// Button focus styles
className="focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-500"
These styles use focus-visible to show focus rings only for keyboard navigation, not mouse clicks.
Skip Links
When building page layouts, include skip links for keyboard users:
<a
href="#main-content"
className="sr-only focus:not-sr-only focus:absolute focus:z-50 focus:p-4"
>
Skip to main content
</a>
ARIA Attributes
Toggle Components
The PricingTiered billing toggle uses proper ARIA roles:
<button
role="switch"
aria-checked={isYearly}
onClick={() => setIsYearly(!isYearly)}
>
{/* Toggle UI */}
</button>
Dismissible Elements
The CTABanner component includes accessible dismiss buttons:
<button
type="button"
onClick={handleDismiss}
className="..."
>
<span className="sr-only">Dismiss</span>
<XIcon aria-hidden="true" />
</button>
Screen Reader Text
Components use sr-only for screen-reader-only content:
// Hidden text for context
<span className="sr-only">Feature</span>
// Visible to screen readers only
<th className="sr-only">Feature name</th>
Semantic HTML
Proper Heading Hierarchy
Feature and pricing sections use semantic headings:
// Section title
<h2>Feature Centered Title</h2>
// Card titles
<h3>Individual Feature</h3>
Lists for Features
Feature lists use proper <ul> and <li> elements:
<ul className="space-y-3">
{features.map((feature) => (
<li key={feature.text}>
{/* Feature content */}
</li>
))}
</ul>
Tables for Comparisons
PricingComparison uses proper table structure:
<table>
<thead>
<tr>
<th scope="col">Feature</th>
<th scope="col">Free</th>
<th scope="col">Pro</th>
</tr>
</thead>
<tbody>
{/* Table rows */}
</tbody>
</table>
Keyboard Navigation
Interactive Elements
All buttons and links are keyboard accessible:
Tabto navigate between elementsEnterorSpaceto activate buttonsEscapeto dismiss modals/banners (where applicable)
Form Controls
The newsletter signup form uses proper form structure:
<form onSubmit={handleSubmit}>
<input
type="email"
required
aria-label="Email address"
placeholder="Enter your email"
/>
<button type="submit">Subscribe</button>
</form>
Color Contrast
Text Contrast
Components maintain WCAG AA contrast ratios:
| Text Type | Light Mode | Dark Mode |
|---|---|---|
| Headings | text-slate-900 | text-white |
| Body | text-slate-600 | text-slate-400 |
| Muted | text-slate-500 | text-slate-500 |
Interactive States
Buttons and links have sufficient contrast in all states:
// Primary button
"bg-sky-500 text-white hover:bg-sky-600"
// Light mode contrast: 4.5:1+
// Dark mode contrast: 4.5:1+
Images and Icons
Alt Text
Image components require alt attributes:
<FeatureWithImage
imageSrc="/feature.jpg"
imageAlt="Developer working on code" // Required
// ...
/>
Decorative Icons
Icons that are purely decorative use aria-hidden:
<svg aria-hidden="true" className="h-5 w-5">
{/* Icon path */}
</svg>
Meaningful Icons
Icons that convey meaning include accessible text:
<button>
<span className="sr-only">Close</span>
<XIcon aria-hidden="true" />
</button>
Testing Accessibility
Recommended Tools
- axe DevTools - Browser extension for automated testing
- WAVE - Web accessibility evaluation tool
- Lighthouse - Built into Chrome DevTools
Manual Testing
- Navigate using only keyboard (Tab, Enter, Escape)
- Test with screen reader (VoiceOver, NVDA, JAWS)
- Verify color contrast with disabled colors
- Test at 200% zoom level
Best Practices
Required Alt Text
Always provide meaningful alt text for images. Empty alt (alt="") is only appropriate for purely decorative images.
Motion Preferences
Respect prefers-reduced-motion for animations:
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Don't Remove Outlines
Never use outline: none without providing an alternative focus indicator. This breaks keyboard navigation.