Skip to content

About

The Accessibility Plugin is a JavaScript library that helps improve the accessibility of your web applications. It provides a set of utility functions and components that can be easily integrated into your project.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

accessibility-plugin-react

Composable React controls for display preferences and reading assistance. Choose the controls in JSX, keep the widget outside your application layout, and let the provider own state, persistence, effects, focus behavior, and cleanup.

The 2.3.0 minor release introduces modular accessible control primitives (FeatureCard, ToggleControl, ChoiceControl, StepperControl), state UI (SearchCount, EmptyState, ErrorState), profile previews (ProfilePreviewCard), locale and oversized control modes (largeControls), and automated releases across npm, GitHub Releases, and GitHub Packages. It supports React 18.3.1 and React 19.x, ships ESM, CommonJS, TypeScript declarations, and scoped plain CSS, and has no runtime dependency other than React and React DOM.

This library improves the presentation of your content. It cannot repair inaccessible application markup or certify WCAG conformance. Human screen-reader, physical-device, actual-zoom, forced-colors, and host integration checks remain part of your application's accessibility process.

Clean light accessibility panel with remembered placement and fixed quick actions

Installation

From npm (recommended)

npm install accessibility-plugin-react

From GitHub Packages

npm install @prabothcharith/accessibility-plugin-react --registry=https://npm.pkg.github.com

React and React DOM are peer dependencies and must use the same major/minor line. The package requires Node.js 22.13 or newer for development and builds. The widget itself does not require an API key, backend, environment variable, Tailwind, Motion, or an icon library.

Quick start

Import the package and mount one provider per document, preferably above route changes or in the persistent application layout. The package automatically injects its scoped CSS in browser environments:

import {
  AccessibilityPlugin,
  AccessibilityButton,
  AccessibilityList,
  FontSizeController,
  ContrastController,
  GrayscaleController,
  ResetController,
} from "accessibility-plugin-react";

export function AccessibilitySettings() {
  return (
    <AccessibilityPlugin position="right">
      <AccessibilityButton description="Adjust display preferences" />
      <AccessibilityList>
        <FontSizeController />
        <ContrastController />
        <GrayscaleController />
        <ResetController />
      </AccessibilityList>
    </AccessibilityPlugin>
  );
}

The button and panel are non-modal body portals. The application remains interactive while the panel is open. Opening moves focus to the named region; Escape and Close return focus to the trigger. Focus is not trapped.

AccessibilityPlugin can be rendered next to application content:

export function App() {
  return (
    <>
      <main>{/* application routes and content */}</main>
      <AccessibilitySettings />
    </>
  );
}

Built-in controllers

Every controller is opt-in. Add only the controls that make sense for your site, and choose their order in JSX.

Controller Effect
TextScaleController Stepwise reflow-safe text enlargement (1.0x, 1.125x, 1.25x, 1.5x, 2.0x) protecting forms, code, and icons.
FontSizeController Scales eligible HTML text from 50% to 200%; supports continuous 10% steps or stepScale mode.
LineHeightController Scales computed line height from 50% to 200%.
LetterSpacingController Applies 0–10px letter spacing.
ContrastController Turns contrast off, reduces it, increases it, or selects a named palette.
SaturationController Reduces or increases saturation.
InvertColorsController Inverts eligible page content.
GrayscaleController Removes color while preserving the selected saturation value for later.
LinkHighlightController Highlights links or selects a link palette.
TextAlignController Restores the host alignment or forces left, center, right, or justified text.
HideImagesController Hides images and CSS background images while retaining layout.
HideVideosController Hides video elements and recognized YouTube/Vimeo embeds visually.
BigCursorController Applies a larger high-contrast cursor where supported.
ReadingMaskController Dims the page around a transparent reading window.
ReadingGuideController Follows pointer/focus with a reading guide line.
ResetController Resets display features and custom registered features without moving the widget.

Effects compose where appropriate. For example, contrast, saturation, invert, and grayscale are applied in a deterministic order. Defaults leave host styles unchanged, and the provider restores host inline values and priorities when an effect is disabled or the provider is removed.

Control primitives and profiles

Build custom accessible panels or custom features with modular primitives that include ARIA semantics, keyboard navigation, and Clean light styling:

  • FeatureCard: Accessible container with header, icon, description, status badge, and alert states (idle, active, error, unavailable, permission-required).
  • ToggleControl: Native switch button with role="switch", aria-checked, and >=44px touch targets.
  • ChoiceControl: Segmented or grouped choices with role="radiogroup", Arrow key navigation (Left/Right/Up/Down/Home/End), and visual check indicators.
  • StepperControl: Bounded decrement/increment buttons, <output aria-live="polite">, and optional range slider.
  • SearchCount & EmptyState: Polite live announcements for feature filtering and search zero-results states.
  • ProfilePreviewCard: Previews affected accessibility profile settings (e.g. low-vision, dyslexia, cognitive) and provides one-click reversal back to custom settings.

Custom features

Use the two-argument hook for simple state, or provide validation and a provider-owned effect for a feature that changes the page:

import { useAccessibility } from "accessibility-plugin-react";

export function OutlineFeature() {
  const { value, setValue } = useAccessibility("site:outline", false, {
    apply(enabled) {
      if (!enabled) return;

      const previous = document.body.style.outline;
      document.body.style.outline = "3px solid #1e40af";
      return () => {
        document.body.style.outline = previous;
      };
    },
  });

  return (
    <button type="button" aria-pressed={value} onClick={() => setValue(!value)}>
      Outline page
    </button>
  );
}

Place the feature inside AccessibilityList:

<AccessibilityList>
  <FontSizeController />
  <OutlineFeature />
  <ResetController />
</AccessibilityList>

The provider owns the effect lifetime, so it continues when the panel closes or the control temporarily unmounts. Cleanup runs before reapplication and when the provider unmounts. Custom state is JSON-compatible; supply validate for arrays and objects. Feature keys must be stable and cannot use reserved prototype names or built-in keys. See custom feature details.

Persistence and movement

Preferences are stored in a versioned local-storage record under react-accessibility-plugin:state by default. Writes are debounced and flushed when the page is hidden or the provider is removed. Invalid saved values fall back to defaults; storage failures do not make the widget unusable.

<AccessibilityPlugin
  persistenceKey="my-site:accessibility"
  persist={true}
  position="left"
>
  {/* button, list, and selected controllers */}
</AccessibilityPlugin>

Persistence options are fixed for the provider lifetime. Remount with a React key when changing the storage identity. Use one provider per document.

The trigger is draggable by default. Movement also works with Alt+Arrow keys and the panel's explicit corner and arrow controls. Drag activation has an 8px threshold, cancelled drags do not open the panel, and placement is clamped on resize. ResetController preserves placement; the panel's separate position reset removes it. Set draggable={false} when only the non-drag controls should be available.

Styling and framework integration

The stylesheet is scoped to .arap-root and does not add a global reset, Tailwind preflight, or host theme variables. Load it once, then put consumer overrides after it:

.arap-root {
  --arap-accent: #1e40af;
  --arap-accent-hover: #1e3a8a;
  --arap-selected: #eff6ff;
}

.arap-root .my-trigger {
  border-radius: 999px;
}

Use className, style, title, description, and closeLabel to adapt the widget to your product language and layout. Preserve visible focus, pressed states, contrast, and the library's 44px minimum interactive targets when overriding styles.

For Next.js App Router, put the provider and custom controls in a Client Component, import the CSS from the root layout, and render the provider in the persistent layout rather than once per route:

// app/accessibility-settings.tsx
"use client";

import {
  AccessibilityPlugin,
  AccessibilityButton,
  AccessibilityList,
  FontSizeController,
  ResetController,
} from "accessibility-plugin-react";

export function AccessibilitySettings() {
  return (
    <AccessibilityPlugin>
      <AccessibilityButton />
      <AccessibilityList>
        <FontSizeController />
        <ResetController />
      </AccessibilityList>
    </AccessibilityPlugin>
  );
}

See installation and Next.js for App Router and Pages Router examples, runnable code in examples/next-app/, and strict CSP guidance.

API and limitations

  • Public components, props, exported types, placement, persistence, custom features, and CSS variables are documented in API.md.
  • Detailed per-feature defaults, bounds, and host behavior are in FEATURES.md.
  • Filters can create stacking contexts and containing blocks for fixed host descendants. Test sticky headers, overlays, and third-party widgets in the real application.
  • Text measurement covers the current document's eligible HTML elements. Shadow DOM, iframe interiors, SVG/canvas text, pseudo-elements, and raw text nodes directly under body are outside scope.
  • Image/video hiding is visual; video playback is not paused or muted.
  • Reading aids are pointer-transparent overlays and do not replace semantic reading structure.
  • There is no live cross-tab synchronization or server-side preference sync.
  • persist={false} disables both display and placement persistence.

See troubleshooting before filing an issue.

Documentation and examples

Runnable package-consumer examples are in examples/:

npm ci
npm run build
npm run example

License

This package is available under the ISC license. The original vanilla JavaScript project is maintained separately at prabothcharith/accessibility-plugin.

About

The Accessibility Plugin is a JavaScript library that helps improve the accessibility of your web applications. It provides a set of utility functions and components that can be easily integrated into your project.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages