frontend-accessibility

安装量: 143
排名: #5970

安装

npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill frontend-accessibility

Frontend Accessibility Overview

Build accessible web applications following WCAG guidelines with semantic HTML, ARIA attributes, keyboard navigation, and screen reader support for inclusive user experiences.

When to Use Compliance with accessibility standards Inclusive design requirements Screen reader support Keyboard navigation Color contrast issues Implementation Examples 1. Semantic HTML and ARIA

Article Title

Article content...

© 2024 Company Name

We'll never share your email
  • At least 8 characters
  • One uppercase letter
  • One number

Error: Please correct the highlighted fields
  1. Keyboard Navigation // React Component with keyboard support import React, { useEffect, useRef, useState } from 'react';

interface MenuItem { id: string; label: string; href: string; }

const KeyboardNavigationMenu: React.FC<{ items: MenuItem[] }> = ({ items }) => { const [activeIndex, setActiveIndex] = useState(0); const menuRef = useRef(null);

useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { switch (e.key) { case 'ArrowLeft': case 'ArrowUp': e.preventDefault(); setActiveIndex(prev => prev === 0 ? items.length - 1 : prev - 1 ); break;

    case 'ArrowRight':
    case 'ArrowDown':
      e.preventDefault();
      setActiveIndex(prev =>
        prev === items.length - 1 ? 0 : prev + 1
      );
      break;

    case 'Home':
      e.preventDefault();
      setActiveIndex(0);
      break;

    case 'End':
      e.preventDefault();
      setActiveIndex(items.length - 1);
      break;

    case 'Enter':
    case ' ':
      e.preventDefault();
      const link = menuRef.current?.querySelectorAll('a')[activeIndex];
      link?.click();
      break;

    case 'Escape':
      menuRef.current?.querySelector('a')?.blur();
      break;

    default:
      break;
  }
};

menuRef.current?.addEventListener('keydown', handleKeyDown);
return () => menuRef.current?.removeEventListener('keydown', handleKeyDown);

}, [items.length, activeIndex]);

return (

{items.map((item, index) => ( setActiveIndex(index)} aria-current={index === activeIndex ? 'page' : undefined} > {item.label} ))}
); };

  1. Color Contrast and Visual Accessibility / Proper color contrast (WCAG AA: 4.5:1 for text, 3:1 for large text) / :root { --color-text: #1a1a1a; / Black - high contrast / --color-background: #ffffff; --color-primary: #0066cc; / Blue with good contrast / --color-success: #008000; / Not pure green / --color-error: #d32f2f; / Not pure red / --color-warning: #ff8c00; / Not yellow / }

body { color: var(--color-text); background-color: var(--color-background); font-size: 16px; line-height: 1.5; }

a { color: var(--color-primary); text-decoration: underline; / Don't rely on color alone / }

button { min-height: 44px; / Touch target size / min-width: 44px; padding: 10px 20px; border-radius: 4px; font-size: 16px; cursor: pointer; }

/ Focus visible for keyboard navigation / button:focus-visible, a:focus-visible, input:focus-visible { outline: 3px solid var(--color-primary); outline-offset: 2px; }

/ High contrast mode support / @media (prefers-contrast: more) { body { font-weight: 500; }

button { border: 2px solid currentColor; } }

/ Reduced motion support / @media (prefers-reduced-motion: reduce) { * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } }

/ Dark mode support / @media (prefers-color-scheme: dark) { :root { --color-text: #e0e0e0; --color-background: #1a1a1a; --color-primary: #6495ed; } }

  1. Screen Reader Announcements // LiveRegion component for announcements interface LiveRegionProps { message: string; politeness?: 'polite' | 'assertive' | 'off'; role?: 'status' | 'alert'; }

const LiveRegion: React.FC = ({ message, politeness = 'polite', role = 'status' }) => { const ref = useRef(null);

useEffect(() => { if (message && ref.current) { ref.current.textContent = message; } }, [message]);

return (

); };

// Usage in component const SearchResults: React.FC = () => { const [results, setResults] = useState([]); const [message, setMessage] = useState('');

const handleSearch = async (query: string) => { const response = await fetch(/api/search?q=${query}); const data = await response.json(); setResults(data); setMessage(Found ${data.length} results); };

return ( <> handleSearch(e.target.value)} aria-label="Search results" />

    {results.map(item => (
  • {item.title}
  • ))}
</> ); };

// Skip to main content link (hidden by default) const skipLink = document.createElement('a'); skipLink.href = '#main-content'; skipLink.textContent = 'Skip to main content'; skipLink.style.position = 'absolute'; skipLink.style.top = '-40px'; skipLink.style.left = '0'; skipLink.style.background = '#000'; skipLink.style.color = '#fff'; skipLink.style.padding = '8px'; skipLink.style.zIndex = '100'; skipLink.addEventListener('focus', () => { skipLink.style.top = '0'; }); skipLink.addEventListener('blur', () => { skipLink.style.top = '-40px'; }); document.body.insertBefore(skipLink, document.body.firstChild);

  1. Accessibility Testing // jest-axe integration test import { render } from '@testing-library/react'; import { axe, toHaveNoViolations } from 'jest-axe'; import { Button } from './Button';

expect.extend(toHaveNoViolations);

describe('Button Accessibility', () => { it('should not have accessibility violations', async () => { const { container } = render( );

const results = await axe(container);
expect(results).toHaveNoViolations();

});

it('should have proper ARIA labels', async () => { const { container } = render( );

const results = await axe(container);
expect(results).toHaveNoViolations();

}); });

// Accessibility Checker Hook const useAccessibilityChecker = () => { useEffect(() => { // Run accessibility checks in development if (process.env.NODE_ENV === 'development') { import('axe-core').then(axe => { axe.run((error, results) => { if (results.violations.length > 0) { console.warn('Accessibility violations found:', results.violations); } }); }); } }, []); };

Best Practices Use semantic HTML elements Provide meaningful alt text for images Ensure 4.5:1 color contrast ratio for text Support keyboard navigation entirely Use ARIA only when necessary Test with screen readers (NVDA, JAWS) Implement skip links Support zoom up to 200% Use descriptive link text Test with actual assistive technologies Resources WCAG 2.1 Guidelines WAI-ARIA Authoring Practices MDN Accessibility Axe DevTools WAVE Browser Extension WebAIM Resources

返回排行榜