Files
ui-essentials/projects/ui-accessibility/README.md
skyai_dev 5346d6d0c9 Add comprehensive library expansion with new components and demos
- 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>
2025-09-05 05:37:37 +10:00

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';
<!-- 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 arrows
  • horizontal - Left/Right arrows
  • both - All arrow keys
  • grid - 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;
}

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.