🎉 75% of content is free forever — Unlock Premium from $10/mo →
CW
đŸ’ŧ Servicesâ„šī¸ Aboutâœ‰ī¸ ContactView Pricing Plansfrom $10

Accessibility (a11y)

React Best PracticesđŸŸĸ Free Lesson

Advertisement

Accessibility (a11y)

ARIA attributes, keyboard navigation, screen reader support, and testing.

Overview

Accessibility ensures React apps are usable by everyone, including people with disabilities.

Key Concepts

  • Semantic HTML — Use proper HTML elements for meaning
  • ARIA Attributes — Enhance accessibility when HTML isn't enough
  • Keyboard Navigation — Support tab, enter, escape, arrow keys
  • Screen Readers — Announce dynamic content changes
  • Focus Management — Maintain logical focus order

Code Examples

function AccessibleModal({ isOpen, onClose, title, children }) {
  const closeRef = useRef(null);

  useEffect(() => {
    if (isOpen) closeRef.current?.focus();
  }, [isOpen]);

  useEffect(() => {
    const handleEscape = (e) => {
      if (e.key === 'Escape') onClose();
    };
    if (isOpen) {
      document.addEventListener('keydown', handleEscape);
      return () => document.removeEventListener('keydown', handleEscape);
    }
  }, [isOpen, onClose]);

  if (!isOpen) return null;

  return (
    <div 
      className="modal-overlay" 
      onClick={onClose}
      role="dialog"
      aria-modal="true"
      aria-labelledby="modal-title"
    >
      <div className="modal-content" onClick={e => e.stopPropagation()}>
        <h2 id="modal-title">{title}</h2>
        {children}
        <button ref={closeRef} onClick={onClose} aria-label="Close modal">
          ×
        </button>
      </div>
    </div>
  );
}

function AccessibleTabs({ tabs, panels }) {
  const [activeIndex, setActiveIndex] = useState(0);

  const handleKeyDown = (e) => {
    if (e.key === 'ArrowRight') setActiveIndex(i => (i + 1) % tabs.length);
    if (e.key === 'ArrowLeft') setActiveIndex(i => (i - 1 + tabs.length) % tabs.length);
  };

  return (
    <div>
      <div role="tablist" onKeyDown={handleKeyDown}>
        {tabs.map((tab, index) => (
          <button
            key={tab.id}
            role="tab"
            aria-selected={index === activeIndex}
            aria-controls={`panel-${tab.id}`}
            tabIndex={index === activeIndex ? 0 : -1}
            onClick={() => setActiveIndex(index)}
          >
            {tab.label}
          </button>
        ))}
      </div>
      {panels.map((panel, index) => (
        <div
          key={panel.id}
          role="tabpanel"
          id={`panel-${panel.id}`}
          hidden={index !== activeIndex}
        >
          {panel.content}
        </div>
      ))}
    </div>
  );
}

Practice

Audit and fix accessibility issues in a React component library.

Need Expert React Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement