- Add new libraries: ui-accessibility, ui-animations, ui-backgrounds, ui-code-display, ui-data-utils, ui-font-manager, hcl-studio - Add extensive layout components: gallery-grid, infinite-scroll-container, kanban-board, masonry, split-view, sticky-layout - Add comprehensive demo components for all new features - Update project configuration and dependencies - Expand component exports and routing structure - Add UI landing pages planning document 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
9.0 KiB
UI Accessibility
A comprehensive Angular accessibility library that enhances your existing components with WCAG 2.1 Level AA compliant features while using semantic tokens from your design system.
Features
- 🎯 Focus Management - Advanced focus trapping, restoration, and monitoring
- ⌨️ Keyboard Navigation - Arrow keys, roving tabindex, custom shortcuts
- 📢 Screen Reader Support - Live announcements, ARIA enhancements
- 🎨 Design System Integration - Uses semantic motion, color, and spacing tokens
- ♿ High Contrast & Reduced Motion - Automatic detection and adaptation
- 🔧 Zero Rewrites Required - Enhance existing components with directives
- 🧪 Developer Experience - Debug modes, warnings, and comprehensive logging
Installation
npm install ui-accessibility
Quick Start
1. Import the Module
import { UiAccessibilityModule } from 'ui-accessibility';
@NgModule({
imports: [
UiAccessibilityModule.forRoot({
// Optional configuration
skipLinks: { enabled: true },
keyboard: { enableArrowNavigation: true },
development: { warnings: true }
})
]
})
export class AppModule {}
2. Import SCSS Utilities
// Import accessibility utilities (uses your semantic tokens)
@use 'ui-accessibility/src/lib/utilities/a11y-utilities';
3. Add Skip Links
<!-- Add to your app.component.html -->
<ui-skip-links></ui-skip-links>
Core Features
Focus Trap Directive
Trap focus within containers like modals and drawers:
<!-- Before: Basic modal -->
<ui-modal [open]="isOpen">
<h2>Settings</h2>
<input type="text" placeholder="Name">
<button>Save</button>
</ui-modal>
<!-- After: Focus-trapped modal -->
<ui-modal [open]="isOpen" uiFocusTrap>
<h2>Settings</h2>
<input type="text" placeholder="Name">
<button>Save</button>
</ui-modal>
Features:
- Automatic focus on first element
- Tab wrapping within container
- Focus restoration on close
- Uses semantic motion tokens for transitions
Arrow Navigation Directive
Add keyboard navigation to lists, menus, and grids:
<!-- Before: Basic menu -->
<ui-menu>
<ui-menu-item>Profile</ui-menu-item>
<ui-menu-item>Settings</ui-menu-item>
<ui-menu-item>Logout</ui-menu-item>
</ui-menu>
<!-- After: Keyboard navigable menu -->
<ui-menu uiArrowNavigation="vertical">
<ui-menu-item tabindex="0">Profile</ui-menu-item>
<ui-menu-item tabindex="-1">Settings</ui-menu-item>
<ui-menu-item tabindex="-1">Logout</ui-menu-item>
</ui-menu>
Navigation Options:
vertical- Up/Down arrowshorizontal- Left/Right arrowsboth- All arrow keysgrid- 2D navigation with column support
Live Announcer Service
Announce dynamic content changes to screen readers:
import { LiveAnnouncerService } from 'ui-accessibility';
constructor(private announcer: LiveAnnouncerService) {}
// Announce with different politeness levels
onItemAdded() {
this.announcer.announce('Item added to cart', 'polite');
}
onError() {
this.announcer.announce('Error: Please fix the required fields', 'assertive');
}
// Announce a sequence of messages
onProcessComplete() {
this.announcer.announceSequence([
'Processing started',
'Validating data',
'Processing complete'
], 'polite', 1500);
}
Screen Reader Components
Hide content visually while keeping it accessible:
<!-- Screen reader only text -->
<ui-screen-reader-only>
Additional context for screen readers
</ui-screen-reader-only>
<!-- Focusable hidden text (becomes visible on focus) -->
<ui-screen-reader-only type="focusable">
Press Enter to activate
</ui-screen-reader-only>
<!-- Status messages -->
<ui-screen-reader-only type="status" statusType="error" [visible]="hasError">
Please correct the errors below
</ui-screen-reader-only>
Keyboard Manager Service
Register global and element-specific keyboard shortcuts:
import { KeyboardManagerService } from 'ui-accessibility';
constructor(private keyboard: KeyboardManagerService) {}
ngOnInit() {
// Global shortcut
this.keyboard.registerGlobalShortcut('save', {
key: 's',
ctrlKey: true,
description: 'Save document',
handler: () => this.save()
});
// Element-specific shortcut
const element = this.elementRef.nativeElement;
this.keyboard.registerElementShortcut('close', element, {
key: 'Escape',
description: 'Close dialog',
handler: () => this.close()
});
}
Design System Integration
All features use semantic tokens from your design system:
Focus Indicators
// Automatic integration with your focus tokens
.my-component:focus-visible {
outline: $semantic-border-focus-width solid $semantic-color-focus;
box-shadow: $semantic-shadow-input-focus;
transition: outline-color $semantic-motion-duration-fast;
}
Skip Links Styling
Uses your semantic spacing, colors, and typography:
.skip-link {
padding: $semantic-spacing-component-padding-y $semantic-spacing-component-padding-x;
background: $semantic-color-surface-primary;
color: $semantic-color-text-primary;
border-color: $semantic-color-border-focus;
}
Motion & Animations
Respects reduced motion preferences:
// Service automatically detects preference
const duration = this.highContrast.getMotionDuration('300ms', '0.01s');
// SCSS utilities adapt automatically
@media (prefers-reduced-motion: reduce) {
.fade-in-a11y {
animation-duration: 0.01s;
}
}
Advanced Configuration
Full Configuration Example
UiAccessibilityModule.forRoot({
announcer: {
defaultPoliteness: 'polite',
defaultDuration: 4000,
enabled: true
},
focusManagement: {
trapFocus: true,
restoreFocus: true,
focusVisibleEnabled: true
},
keyboard: {
enableShortcuts: true,
enableArrowNavigation: true,
customShortcuts: [
{ key: '/', ctrlKey: true, description: 'Search' }
]
},
skipLinks: {
enabled: true,
position: 'top',
links: [
{ href: '#main', text: 'Skip to main content' },
{ href: '#nav', text: 'Skip to navigation' },
{ href: '#search', text: 'Skip to search' }
]
},
accessibility: {
respectReducedMotion: true,
respectHighContrast: true,
injectAccessibilityStyles: true,
addBodyClasses: true
},
development: {
warnings: true,
logging: true
}
})
High Contrast & Reduced Motion
Automatic detection and CSS class application:
<!-- Body classes added automatically -->
<body class="prefers-reduced-motion prefers-high-contrast">
<!-- Your CSS can respond -->
<style>
.prefers-reduced-motion * {
animation-duration: 0.01s !important;
}
.prefers-high-contrast .card {
border: 1px solid ButtonText;
background: ButtonFace;
}
</style>
Available Directives
| Directive | Purpose | Usage |
|---|---|---|
uiFocusTrap |
Trap focus within container | <div uiFocusTrap> |
uiArrowNavigation |
Arrow key navigation | <ul uiArrowNavigation="vertical"> |
Available Services
| Service | Purpose | Key Methods |
|---|---|---|
LiveAnnouncerService |
Screen reader announcements | announce(), announceSequence() |
FocusMonitorService |
Focus origin tracking | monitor(), focusVia() |
KeyboardManagerService |
Keyboard shortcuts | registerGlobalShortcut() |
HighContrastService |
Accessibility preferences | getCurrentPreferences() |
A11yConfigService |
Configuration management | getConfig(), isEnabled() |
SCSS Utilities
// Import specific utilities
@use 'ui-accessibility/src/lib/utilities/focus-visible';
@use 'ui-accessibility/src/lib/utilities/screen-reader';
// Use utility classes
.my-element {
@extend .focus-ring; // Adds focus ring on :focus-visible
@extend .touch-target; // Ensures minimum touch target size
}
// Screen reader utilities
.sr-instructions {
@extend .sr-only; // Visually hidden, screen reader accessible
}
.status-text {
@extend .sr-only-focusable; // Hidden until focused
}
WCAG 2.1 Compliance
This library helps achieve Level AA compliance:
- ✅ 1.3.1 - Info and Relationships (ARIA attributes)
- ✅ 1.4.3 - Contrast (High contrast mode support)
- ✅ 1.4.13 - Content on Hover/Focus (Proper focus management)
- ✅ 2.1.1 - Keyboard (Full keyboard navigation)
- ✅ 2.1.2 - No Keyboard Trap (Proper focus trapping)
- ✅ 2.4.1 - Bypass Blocks (Skip links)
- ✅ 2.4.3 - Focus Order (Logical tab sequence)
- ✅ 2.4.7 - Focus Visible (Enhanced focus indicators)
- ✅ 3.2.1 - On Focus (Predictable focus behavior)
- ✅ 4.1.3 - Status Messages (Live announcements)
Browser Support
- Chrome 88+
- Firefox 85+
- Safari 14+
- Edge 88+
Demo
Visit /accessibility in your demo application to see interactive examples of all features.
Contributing
This library integrates seamlessly with your existing component architecture and design system tokens, requiring no rewrites of existing components.