From 106d2005ae207687d42e5c54c8389798e30f17f4 Mon Sep 17 00:00:00 2001 From: praboth charith Date: Thu, 22 Oct 2026 14:52:44 +0530 Subject: [PATCH] docs: update README, API, and FEATURES for v2.3.0 and control primitives (#94) --- README.md | 22 ++++++++++++++++++++-- docs/API.md | 26 +++++++++++++++++++------- docs/FEATURES.md | 14 ++++++++++++++ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e316c2c..81b7be7 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ 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.0.2` patch release adds automatic widget stylesheet injection on package -import while retaining the standalone stylesheet export for explicit pipelines. +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. @@ -18,10 +17,18 @@ and scoped plain CSS, and has no runtime dependency other than React and React D ## Installation +### From npm (recommended) + ```sh npm install accessibility-plugin-react ``` +### From GitHub Packages + +```sh +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, @@ -104,6 +111,17 @@ 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, ``, 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 diff --git a/docs/API.md b/docs/API.md index d6e50a1..93d7c18 100644 --- a/docs/API.md +++ b/docs/API.md @@ -4,12 +4,18 @@ All exports are named from `accessibility-plugin-react`. JavaScript consumers re ## Components -| Component | Props | -| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| AccessibilityPlugin | `children: ReactNode` required; `position?: 'left' \| 'right' \| 'top' \| 'bottom'` default right; `persistenceKey?: string` default `react-accessibility-plugin:state`; `persist?: boolean` default true | -| AccessibilityButton | `draggable?: boolean` default true (pointer/Alt+arrow movement); `icon?: ReactNode` default inline accessibility SVG; `title?: string` accessible name, default Accessibility; `description?: string` supplementary accessible description; `className?: string`; `style?: CSSProperties` | -| AccessibilityList | `footer?: ReactNode` extra fixed actions; `children: ReactNode` required; `title?: string` visible heading and region name, default Accessibility settings; `description?: string` default Adjust your reading experience (empty string omits it); `closeLabel?: string` default Close accessibility settings; `className?: string`; `style?: CSSProperties` | -| All fifteen controllers listed in FEATURES.md | No props. Pick/omit in JSX. For custom labels or behavior, compose a control with useAccessibility. | +| Component | Props | +| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| AccessibilityPlugin | `children: ReactNode` required; `position?: 'left' \| 'right' \| 'top' \| 'bottom'` default right; `persistenceKey?: string` default `react-accessibility-plugin:state`; `persist?: boolean` default true; `storage?: 'local' \| 'session' \| 'none'` default local; `locale?: string`; `statementUrl?: string`; `largeControls?: boolean` default false | +| AccessibilityButton | `draggable?: boolean` default true (pointer/Alt+arrow movement); `icon?: ReactNode` default inline accessibility SVG; `title?: string` accessible name, default Accessibility; `description?: string` supplementary accessible description; `className?: string`; `style?: CSSProperties`; `largeControls?: boolean` | +| AccessibilityList | `footer?: ReactNode` extra fixed actions; `children: ReactNode` required; `title?: string` visible heading and region name, default Accessibility settings; `description?: string` default Adjust your reading experience; `closeLabel?: string` default Close; `statementUrl?: string`; `largeControls?: boolean`; `locale?: string`; `className?: string`; `style?: CSSProperties` | +| FeatureCard | `title: ReactNode` required; `children: ReactNode` required; `featureKey?: string`; `icon?: ReactNode`; `description?: ReactNode`; `statusBadge?: string`; `status?: 'idle' \| 'active' \| 'error' \| 'unavailable' \| 'permission-required'`; `errorMessage?: string`; `unavailableMessage?: string`; `permissionMessage?: string`; `onRequestPermission?: () => void`; `largeControls?: boolean` | +| ToggleControl | `label: ReactNode` required; `checked: boolean` required; `onChange: (checked: boolean) => void` required; `disabled?: boolean`; `unavailable?: boolean`; `unavailableReason?: string`; `largeControls?: boolean` | +| ChoiceControl | `label: string` required; `value: T` required; `options?: ChoiceOption[]`; `groups?: ChoiceGroup[]`; `onChange: (value: T) => void` required; `disabled?: boolean`; `largeControls?: boolean` | +| StepperControl | `label: string` required; `value: number` required; `min: number`; `max: number`; `step: number`; `unit?: string` default '%'; `showSlider?: boolean`; `formatValue?: (val: number) => string`; `onChange: (value: number) => void` required; `disabled?: boolean`; `largeControls?: boolean` | +| ProfilePreviewCard | `profile: ProfileDefinition` required; `isActive: boolean` required; `onApply: (profile: ProfileDefinition) => void` required; `onRevert: () => void` required; `largeControls?: boolean` | +| SearchCount / EmptyState / ErrorState | Standalone accessible status and announcement primitives for search counts, zero-results fallbacks, and error recovery banners. | +| All fifteen controllers listed in FEATURES.md | No props. Pick/omit in JSX. For custom labels or behavior, compose a control with useAccessibility or the modular control primitives. | Use one button/list pair per provider and one provider per document. UI IDs use React `useId`; do not target the old fixed `arap-panel` ID. Plugin children can include ordinary app content, but mounting the widget as a sibling makes intent clearer. Persistence configuration is fixed at mount; use `` when switching storage identity. @@ -37,7 +43,13 @@ Definitions/defaults are immutable for the provider lifetime; the first register `FeatureRegistration` is `FeatureOptions` plus `defaultValue: unknown`. Use the generic hook instead of manually casting callbacks. Legacy `registerReset(key, fn)` / `unregisterReset(key)` remain available; callbacks run before global state is cleared. They are not the primary effect lifecycle API. Callback owners must unregister their callback on teardown. -Exported types: `AccessibilityPluginProps`, `AccessibilityButtonProps`, `AccessibilityListProps`, `AccessibilityState`, `AccessibilityContextValue`, `PluginPosition`, `WidgetPlacement`, `FeatureOptions`, `FeatureRegistration`. +Exported types: `AccessibilityPluginProps`, `AccessibilityButtonProps`, `AccessibilityListProps`, `AccessibilityState`, `AccessibilityContextValue`, `PluginPosition`, `WidgetPlacement`, `FeatureOptions`, `FeatureRegistration`, `ToggleControlProps`, `ChoiceControlProps`, `ChoiceOption`, `ChoiceGroup`, `StepperControlProps`, `FeatureCardProps`, `FeatureStatus`, `SearchCountProps`, `EmptyStateProps`, `ErrorStateProps`, `ProfilePreviewCardProps`, `AccessibilityPreferences`, `ContrastMode`, `CursorSizePreference`, `FontFamilyPreference`, `ProfileDefinition`, `ProfilePresetId`, `ReaderMode`, `SaturationPreference`, `StorageMode`, `TextAlignPreference`, `LocaleStrings`. + +Exported control components: `ToggleControl`, `ChoiceControl`, `StepperControl`, `FeatureCard`, `SearchCount`, `EmptyState`, `ErrorState`, `ProfilePreviewCard`. + +Exported preference and profile utilities: `DEFAULT_PREFERENCES`, `PROFILE_DEFINITIONS`, `normalizePreferences`, `normalizePreferenceValue`, `resolveEffectivePreferences`, `preferencesReducer`, `createInitialPreferencesState`. + +Exported localization utilities: `enLocale`, `registerLocale`, `resolveLocaleStrings`, `isRtlLocale`. ## Styling and labels diff --git a/docs/FEATURES.md b/docs/FEATURES.md index ec9db9c..10886a6 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -20,6 +20,20 @@ All features are opt-in via controllers, use native buttons, support Enter/Space | ReadingGuideController / readingGuide | false; boolean | 4px blue line with white border follows pointer or host focus. Can coexist with mask. | | ResetController | No feature state | Clears display settings including custom/unmounted controls, preserves widget placement; runs legacy reset callbacks; keeps panel open. | +## Accessible control primitives and UI states + +The library exports modular UI primitives conforming to WCAG 2.2 criteria: + +| Primitive | Accessible Role & State | Key Capabilities | +| --------------------------- | --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | +| `ToggleControl` | `role="switch"`, `aria-checked` | Keyboard Space/Enter toggle, disabled/unavailable states, >=44px touch targets (>=48px in largeControls mode). | +| `ChoiceControl` | `role="radiogroup"`, `role="radio"`, `aria-checked` | Arrow key (Left/Right/Up/Down/Home/End) cycling, check indicators, multi-level/category grouping. | +| `StepperControl` | `role="group"` with `` | Accessible increment/decrement buttons, boundary clamping, optional `role="slider"` range input. | +| `FeatureCard` | `role="group"`, `aria-label` | Card container with title, icon, description, status badge, and alert states (`idle`, `active`, `error`, `unavailable`, `permission-required`). | +| `SearchCount` | `role="status"`, `aria-live="polite"` | Live status announcement of matched and total features for search filtering. | +| `EmptyState` / `ErrorState` | `role="status"` / `role="alert"` | Clear messaging with action button for empty results and error recovery. | +| `ProfilePreviewCard` | `role="group"` | Previews affected settings for accessibility profiles (low-vision, dyslexia, etc.) and provides one-click reversal back to custom settings. | + ## Original JavaScript and branch comparison Reference: vanilla `47f44c5` (`accessibility-menu.js`, package 1.2.2); older React `7aef17c`; newer baseline `6dfbd44`. “Present” is source evidence, not proof of correctness. See baseline for defects.