Skip to content

riceharvest/react-a11y-utils

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

@opensourceframework/react-a11y-utils

npm version License: MIT

React accessibility utility functions and hooks for building accessible user interfaces. Provides a comprehensive set of ARIA prop factories and CSS utilities to help you build WCAG-compliant React applications.

Features

  • 🎯 ARIA Prop Factories - Functions to generate correct ARIA props for common patterns
  • 👁️ Screen Reader Utilities - CSS styles for visually hidden but accessible content
  • 🔧 TypeScript Support - Full type definitions for all ARIA attributes
  • 🪶 Zero Dependencies - No external dependencies
  • WCAG Compliant - Built following accessibility best practices

Installation

npm install @opensourceframework/react-a11y-utils
# or
yarn add @opensourceframework/react-a11y-utils
# or
pnpm add @opensourceframework/react-a11y-utils

Quick Start

import {
  srOnly,
  createDisclosureProps,
  createLiveRegion,
  statusMessageProps,
} from '@opensourceframework/react-a11y-utils';

function Accordion({ title, children, isOpen, onToggle }) {
  return (
    <div>
      <button
        {...createDisclosureProps(isOpen, 'panel-1')}
        onClick={onToggle}
      >
        {title}
      </button>
      <div id="panel-1" hidden={!isOpen}>
        {children}
      </div>
    </div>
  );
}

function StatusMessage({ message }) {
  return (
    <div {...statusMessageProps}>
      {message}
    </div>
  );
}

// Screen reader only text
function SkipLink() {
  return (
    <a href="#main-content" style={srOnly} tabIndex={0}>
      Skip to main content
    </a>
  );
}

API Reference

Screen Reader Utilities

srOnly

CSS styles for screen-reader-only content. Elements are visually hidden but accessible to screen readers.

<span style={srOnly}>This text is only visible to screen readers</span>

srOnlyFocusable

CSS styles for elements that should become visible when focused (e.g., skip links).

<a href="#main" style={srOnlyFocusable}>Skip to main content</a>

Pre-built Props

decorative

Props for decorative elements that should be hidden from screen readers.

<img src="decoration.png" alt="" {...decorative} />

disabledProps

Props for disabled interactive elements.

<button {...disabledProps}>Disabled Button</button>

statusMessageProps

Props for status messages (polite announcements).

<div {...statusMessageProps}>Changes saved successfully</div>

alertMessageProps

Props for alert messages (assertive announcements).

<div {...alertMessageProps}>Error: Please correct the form</div>

Factory Functions

createLiveRegion(options)

Creates props for live regions that announce changes to screen readers.

<div {...createLiveRegion({ atomic: true, live: 'polite' })}>
  {message}
</div>

Options:

Option Type Default Description
atomic boolean false Announce entire region or just changes
relevant 'additions' | 'removals' | 'text' | 'all' 'additions' What changes to announce
busy boolean false Whether region is being updated
live 'polite' | 'assertive' 'polite' How assertive the announcement

createSkipLinkProps(targetId)

Creates props for skip links.

<a {...createSkipLinkProps('main-content')}>Skip to main content</a>
<main id="main-content">...</main>

createDisclosureProps(expanded, controlsId)

Creates props for elements that expand/collapse content.

<button {...createDisclosureProps(isOpen, 'panel-id')} onClick={toggle}>
  Toggle
</button>

createPressedProps(pressed)

Creates props for toggle buttons with pressed state.

<button {...createPressedProps(isActive)} onClick={toggle}>
  Toggle Feature
</button>

createSelectedProps(selected)

Creates props for elements with selected state.

<li {...createSelectedProps(isSelected)} role="option">
  Option 1
</li>

createCheckedProps(checked)

Creates props for elements with checked state.

<div {...createCheckedProps(checked)} role="checkbox" tabIndex={0}>
  {checked ? '✓' : ''}
</div>

createDialogTriggerProps(dialogId, isOpen)

Creates props for dialog/modal triggers.

<button {...createDialogTriggerProps('my-dialog', isOpen)}>
  Open Dialog
</button>

createFormFieldProps(required, invalid?)

Creates props for form fields.

<input {...createFormFieldProps(true, hasError)} />

createDescribedByProps(describedById)

Creates props for elements described by another element.

<input {...createDescribedByProps('error-message')} />
<span id="error-message">This field is required</span>

createLabelledByProps(labelledById)

Creates props for elements labeled by another element.

<div {...createLabelledByProps('panel-title')} role="region">
  <h2 id="panel-title">Panel Title</h2>
  Content
</div>

mergeA11yProps(...props)

Combines multiple accessibility props objects.

<div {...mergeA11yProps(statusMessageProps, { 'aria-label': 'Status' })}>
  {message}
</div>

Usage Examples

Accordion Component

import { createDisclosureProps } from '@opensourceframework/react-a11y-utils';

function AccordionItem({ id, title, children, isExpanded, onToggle }) {
  const panelId = `panel-${id}`;
  
  return (
    <div className="accordion-item">
      <h3>
        <button
          {...createDisclosureProps(isExpanded, panelId)}
          onClick={onToggle}
        >
          {title}
        </button>
      </h3>
      <div
        id={panelId}
        role="region"
        hidden={!isExpanded}
      >
        {children}
      </div>
    </div>
  );
}

Checkbox Component

import { createCheckedProps } from '@opensourceframework/react-a11y-utils';

function Checkbox({ checked, onChange, children }) {
  return (
    <div
      {...createCheckedProps(checked)}
      role="checkbox"
      tabIndex={0}
      onClick={() => onChange(!checked)}
      onKeyDown={(e) => {
        if (e.key === ' ' || e.key === 'Enter') {
          onChange(!checked);
        }
      }}
    >
      {checked ? '✓' : ''}
      {children}
    </div>
  );
}

Toast Notifications

import { createLiveRegion, alertMessageProps } from '@opensourceframework/react-a11y-utils';

function Toast({ message, type = 'info' }) {
  const props = type === 'error' 
    ? alertMessageProps 
    : createLiveRegion({ live: 'polite' });

  return (
    <div {...props} className={`toast toast-${type}`}>
      {message}
    </div>
  );
}

Contributing

See Contributing Guide for details.

License

MIT © OpenSource Framework Contributors


Maintained by @opensourceframework in the monorepo.