@gtcx/accessibility 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +163 -0
- package/dist/index.d.mts +183 -0
- package/dist/index.d.ts +183 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +329 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +294 -0
- package/dist/tech-literacy.d.ts +99 -0
- package/dist/tech-literacy.d.ts.map +1 -0
- package/dist/tech-literacy.js +177 -0
- package/dist/tech-literacy.js.map +1 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# @gtcx/accessibility
|
|
2
|
+
|
|
3
|
+
Inclusive design system for GTCX Protocol — tech literacy adaptation, WCAG compliance, and universal access.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Tech Literacy Levels** — Beginner, intermediate, advanced UX adaptation
|
|
8
|
+
- **WCAG 2.1 AA Compliance** — Full accessibility standards
|
|
9
|
+
- **Offline Accessibility** — Screen readers, voice control without connectivity
|
|
10
|
+
- **Multi-Modal Input** — Voice, touch, gesture, keyboard
|
|
11
|
+
- **Cognitive Accessibility** — Clear language, consistent design, error prevention
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add @gtcx/accessibility
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { AccessibilityService, TechLiteracyLevel, detectTechLiteracy } from '@gtcx/accessibility';
|
|
23
|
+
|
|
24
|
+
// Initialize accessibility service
|
|
25
|
+
const a11y = new AccessibilityService({
|
|
26
|
+
wcagLevel: 'AA',
|
|
27
|
+
techLiteracy: 'beginner',
|
|
28
|
+
offlineEnabled: true,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Detect user's tech literacy from interaction patterns
|
|
32
|
+
const literacy = await detectTechLiteracy(userInteractions);
|
|
33
|
+
// Returns: 'beginner' | 'intermediate' | 'advanced'
|
|
34
|
+
|
|
35
|
+
// Adapt UI complexity based on literacy level
|
|
36
|
+
const uiConfig = a11y.getUIConfig(literacy);
|
|
37
|
+
/*
|
|
38
|
+
beginner: Large buttons, simple nav, audio guidance, step-by-step
|
|
39
|
+
intermediate: Standard UI, contextual help, keyboard shortcuts
|
|
40
|
+
advanced: Power user features, API access, customization
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
// Voice guidance for low-literacy users
|
|
44
|
+
await a11y.speak('Please tap the green button to continue', {
|
|
45
|
+
language: 'sw', // Swahili
|
|
46
|
+
speed: 'slow',
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Tech Literacy Adaptation
|
|
51
|
+
|
|
52
|
+
The system adapts based on user capability:
|
|
53
|
+
|
|
54
|
+
### Beginner Level
|
|
55
|
+
|
|
56
|
+
- **Visual**: Large buttons (min 48px), clear icons, simple navigation
|
|
57
|
+
- **Guidance**: Step-by-step wizards, progress indicators, audio instructions
|
|
58
|
+
- **Input**: Touch-friendly, voice input, minimal typing
|
|
59
|
+
- **Feedback**: Immediate visual + audio confirmation
|
|
60
|
+
|
|
61
|
+
### Intermediate Level
|
|
62
|
+
|
|
63
|
+
- **Visual**: Standard controls, contextual help tooltips
|
|
64
|
+
- **Guidance**: Guided setup with skip options
|
|
65
|
+
- **Input**: Keyboard shortcuts available, form auto-complete
|
|
66
|
+
- **Feedback**: Visual confirmation, optional audio
|
|
67
|
+
|
|
68
|
+
### Advanced Level
|
|
69
|
+
|
|
70
|
+
- **Visual**: Compact UI, power-user features visible
|
|
71
|
+
- **Guidance**: Help available on demand
|
|
72
|
+
- **Input**: Full keyboard control, CLI available, API access
|
|
73
|
+
- **Feedback**: Minimal, non-intrusive
|
|
74
|
+
|
|
75
|
+
## WCAG Compliance
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
// Check element accessibility
|
|
79
|
+
const issues = a11y.audit(element);
|
|
80
|
+
/*
|
|
81
|
+
[
|
|
82
|
+
{ rule: 'color-contrast', severity: 'error', element: '#btn1' },
|
|
83
|
+
{ rule: 'alt-text', severity: 'warning', element: 'img.logo' }
|
|
84
|
+
]
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
// Get compliant color palette
|
|
88
|
+
const colors = a11y.getAccessibleColors({
|
|
89
|
+
primary: '#1a5f2a',
|
|
90
|
+
background: '#ffffff',
|
|
91
|
+
minContrast: 4.5, // WCAG AA
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Generate accessible form
|
|
95
|
+
const form = a11y.createAccessibleForm({
|
|
96
|
+
fields: ['name', 'email', 'phone'],
|
|
97
|
+
labelPosition: 'above', // Better for screen readers
|
|
98
|
+
errorAnnouncement: 'polite',
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Offline Capabilities
|
|
103
|
+
|
|
104
|
+
All accessibility features work offline:
|
|
105
|
+
|
|
106
|
+
- **Screen Reader Support** — Pre-cached ARIA labels
|
|
107
|
+
- **Voice Guidance** — Offline TTS with local voices
|
|
108
|
+
- **Keyboard Navigation** — No network required
|
|
109
|
+
- **High Contrast** — Local CSS, no CDN
|
|
110
|
+
|
|
111
|
+
## Multi-Modal Input
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// Enable voice control
|
|
115
|
+
a11y.enableVoiceControl({
|
|
116
|
+
language: 'en-GH', // Ghanaian English
|
|
117
|
+
commands: {
|
|
118
|
+
next: () => nextStep(),
|
|
119
|
+
back: () => prevStep(),
|
|
120
|
+
help: () => showHelp(),
|
|
121
|
+
submit: () => submitForm(),
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Enable gesture control
|
|
126
|
+
a11y.enableGestures({
|
|
127
|
+
swipeLeft: () => prevStep(),
|
|
128
|
+
swipeRight: () => nextStep(),
|
|
129
|
+
doubleTap: () => select(),
|
|
130
|
+
longPress: () => showOptions(),
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Architecture
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
packages/accessibility/
|
|
138
|
+
├── src/
|
|
139
|
+
│ ├── index.ts # Main exports
|
|
140
|
+
│ ├── service.ts # AccessibilityService
|
|
141
|
+
│ ├── tech-literacy.ts # Literacy detection & adaptation
|
|
142
|
+
│ ├── wcag/ # WCAG compliance utilities
|
|
143
|
+
│ │ ├── audit.ts
|
|
144
|
+
│ │ ├── colors.ts
|
|
145
|
+
│ │ └── forms.ts
|
|
146
|
+
│ ├── input/ # Multi-modal input
|
|
147
|
+
│ │ ├── voice.ts
|
|
148
|
+
│ │ ├── gesture.ts
|
|
149
|
+
│ │ └── keyboard.ts
|
|
150
|
+
│ ├── output/ # Accessible output
|
|
151
|
+
│ │ ├── screen-reader.ts
|
|
152
|
+
│ │ ├── tts.ts
|
|
153
|
+
│ │ └── haptic.ts
|
|
154
|
+
│ └── types.ts
|
|
155
|
+
└── configs/
|
|
156
|
+
└── literacy-levels.yaml # UI configs per level
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Related Packages
|
|
160
|
+
|
|
161
|
+
- `@gtcx/i18n` — Multi-language support with cultural adaptation
|
|
162
|
+
- `@gtcx/offline-sync` — Offline-first data synchronization
|
|
163
|
+
- `@gtcx/ui` — Base component library
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { RefObject } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Tech Literacy Detection and Adaptation
|
|
6
|
+
*
|
|
7
|
+
* Automatically detects user's technical proficiency and adapts UI accordingly
|
|
8
|
+
*/
|
|
9
|
+
type TechLiteracyLevel = 'beginner' | 'intermediate' | 'advanced';
|
|
10
|
+
interface InteractionPattern {
|
|
11
|
+
/** Time to complete action in ms */
|
|
12
|
+
actionTime: number;
|
|
13
|
+
/** Number of errors/corrections */
|
|
14
|
+
errorCount: number;
|
|
15
|
+
/** Used keyboard shortcuts */
|
|
16
|
+
usedShortcuts: boolean;
|
|
17
|
+
/** Scrolled to find features */
|
|
18
|
+
searchedFeatures: boolean;
|
|
19
|
+
/** Requested help */
|
|
20
|
+
requestedHelp: boolean;
|
|
21
|
+
/** Used voice input */
|
|
22
|
+
usedVoice: boolean;
|
|
23
|
+
/** Interaction timestamp */
|
|
24
|
+
timestamp: number;
|
|
25
|
+
}
|
|
26
|
+
interface LiteracyScore {
|
|
27
|
+
level: TechLiteracyLevel;
|
|
28
|
+
confidence: number;
|
|
29
|
+
signals: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Detect tech literacy level from interaction patterns
|
|
33
|
+
*/
|
|
34
|
+
declare function detectTechLiteracy(interactions: InteractionPattern[]): Promise<LiteracyScore>;
|
|
35
|
+
/**
|
|
36
|
+
* Tech literacy detector with continuous learning
|
|
37
|
+
*/
|
|
38
|
+
declare class TechLiteracyDetector {
|
|
39
|
+
private interactions;
|
|
40
|
+
private currentLevel;
|
|
41
|
+
private onLevelChange?;
|
|
42
|
+
constructor(options?: {
|
|
43
|
+
initialLevel?: TechLiteracyLevel;
|
|
44
|
+
onLevelChange?: (level: TechLiteracyLevel) => void;
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Record an interaction for analysis
|
|
48
|
+
*/
|
|
49
|
+
recordInteraction(pattern: Omit<InteractionPattern, 'timestamp'>): void;
|
|
50
|
+
/**
|
|
51
|
+
* Evaluate current literacy level
|
|
52
|
+
*/
|
|
53
|
+
evaluate(): Promise<LiteracyScore>;
|
|
54
|
+
/**
|
|
55
|
+
* Get current assessed level
|
|
56
|
+
*/
|
|
57
|
+
getLevel(): TechLiteracyLevel;
|
|
58
|
+
/**
|
|
59
|
+
* Manually set level (user preference)
|
|
60
|
+
*/
|
|
61
|
+
setLevel(level: TechLiteracyLevel): void;
|
|
62
|
+
}
|
|
63
|
+
declare const LITERACY_UI_CONFIGS: {
|
|
64
|
+
readonly beginner: {
|
|
65
|
+
readonly buttonSize: "large";
|
|
66
|
+
readonly fontSize: "large";
|
|
67
|
+
readonly navigation: "simple";
|
|
68
|
+
readonly icons: "labeled";
|
|
69
|
+
readonly animations: "minimal";
|
|
70
|
+
readonly guidance: "proactive";
|
|
71
|
+
readonly inputMode: "touch";
|
|
72
|
+
readonly errorHandling: "guided";
|
|
73
|
+
readonly confirmations: "explicit";
|
|
74
|
+
readonly shortcuts: "hidden";
|
|
75
|
+
};
|
|
76
|
+
readonly intermediate: {
|
|
77
|
+
readonly buttonSize: "medium";
|
|
78
|
+
readonly fontSize: "medium";
|
|
79
|
+
readonly navigation: "standard";
|
|
80
|
+
readonly icons: "tooltips";
|
|
81
|
+
readonly animations: "standard";
|
|
82
|
+
readonly guidance: "contextual";
|
|
83
|
+
readonly inputMode: "mixed";
|
|
84
|
+
readonly errorHandling: "inline";
|
|
85
|
+
readonly confirmations: "smart";
|
|
86
|
+
readonly shortcuts: "discoverable";
|
|
87
|
+
};
|
|
88
|
+
readonly advanced: {
|
|
89
|
+
readonly buttonSize: "compact";
|
|
90
|
+
readonly fontSize: "small";
|
|
91
|
+
readonly navigation: "full";
|
|
92
|
+
readonly icons: "minimal";
|
|
93
|
+
readonly animations: "full";
|
|
94
|
+
readonly guidance: "on-demand";
|
|
95
|
+
readonly inputMode: "keyboard";
|
|
96
|
+
readonly errorHandling: "technical";
|
|
97
|
+
readonly confirmations: "minimal";
|
|
98
|
+
readonly shortcuts: "prominent";
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* WCAG color contrast utilities.
|
|
104
|
+
*
|
|
105
|
+
* Implements the WCAG 2.1 relative luminance and contrast ratio algorithm
|
|
106
|
+
* for checking foreground/background color accessibility.
|
|
107
|
+
*/
|
|
108
|
+
/** Calculate relative luminance per WCAG 2.1. */
|
|
109
|
+
declare function relativeLuminance(hex: string): number;
|
|
110
|
+
/** Calculate the contrast ratio between two hex colors. */
|
|
111
|
+
declare function contrastRatio(fg: string, bg: string): number;
|
|
112
|
+
/**
|
|
113
|
+
* Check if a foreground/background pair meets WCAG contrast requirements.
|
|
114
|
+
*
|
|
115
|
+
* @param fg Foreground hex color (e.g. `'#333333'`)
|
|
116
|
+
* @param bg Background hex color (e.g. `'#ffffff'`)
|
|
117
|
+
* @param level `'AA'` (4.5:1 normal, 3:1 large) or `'AAA'` (7:1 normal, 4.5:1 large)
|
|
118
|
+
* @param large Whether the text is "large" (>= 18pt or >= 14pt bold)
|
|
119
|
+
*/
|
|
120
|
+
declare function meetsWCAG(fg: string, bg: string, level?: 'AA' | 'AAA', large?: boolean): boolean;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* React hook for detecting `prefers-reduced-motion` media query.
|
|
124
|
+
*
|
|
125
|
+
* Returns `true` when the user has enabled reduced motion in their
|
|
126
|
+
* OS accessibility settings. Components should disable non-essential
|
|
127
|
+
* animations when this is `true`.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```tsx
|
|
131
|
+
* const reduced = useReducedMotion();
|
|
132
|
+
* return <div style={{ transition: reduced ? 'none' : 'all 0.3s' }} />;
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
declare function useReducedMotion(): boolean;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* React hook for trapping focus within a container element.
|
|
139
|
+
*
|
|
140
|
+
* Used for modals, dialogs, and drawers to ensure keyboard users
|
|
141
|
+
* cannot Tab outside the container while it is active.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```tsx
|
|
145
|
+
* function Modal({ open, children }) {
|
|
146
|
+
* const ref = useFocusTrap<HTMLDivElement>(open);
|
|
147
|
+
* return open ? <div ref={ref} role="dialog">{children}</div> : null;
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
declare function useFocusTrap<T extends HTMLElement>(active: boolean): RefObject<T | null>;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* React hook for screen reader announcements via `aria-live` regions.
|
|
156
|
+
*
|
|
157
|
+
* Creates an invisible live region and provides an `announce()` function
|
|
158
|
+
* that dynamically updates its content, causing screen readers to
|
|
159
|
+
* read the message aloud.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```tsx
|
|
163
|
+
* const { announce, liveRegionProps } = useAnnounce();
|
|
164
|
+
* // Place the live region once in your layout:
|
|
165
|
+
* <div {...liveRegionProps} />
|
|
166
|
+
* // Then announce messages:
|
|
167
|
+
* announce('3 items selected');
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
interface LiveRegionProps {
|
|
171
|
+
role: 'status';
|
|
172
|
+
'aria-live': 'polite' | 'assertive';
|
|
173
|
+
'aria-atomic': boolean;
|
|
174
|
+
style: Record<string, string | number>;
|
|
175
|
+
}
|
|
176
|
+
declare function useAnnounce(politeness?: 'polite' | 'assertive'): {
|
|
177
|
+
announce: (message: string) => void;
|
|
178
|
+
liveRegionProps: LiveRegionProps & {
|
|
179
|
+
ref: react.MutableRefObject<HTMLElement | null>;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export { LITERACY_UI_CONFIGS, type LiveRegionProps, TechLiteracyDetector, type TechLiteracyLevel, contrastRatio, detectTechLiteracy, meetsWCAG, relativeLuminance, useAnnounce, useFocusTrap, useReducedMotion };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { RefObject } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Tech Literacy Detection and Adaptation
|
|
6
|
+
*
|
|
7
|
+
* Automatically detects user's technical proficiency and adapts UI accordingly
|
|
8
|
+
*/
|
|
9
|
+
type TechLiteracyLevel = 'beginner' | 'intermediate' | 'advanced';
|
|
10
|
+
interface InteractionPattern {
|
|
11
|
+
/** Time to complete action in ms */
|
|
12
|
+
actionTime: number;
|
|
13
|
+
/** Number of errors/corrections */
|
|
14
|
+
errorCount: number;
|
|
15
|
+
/** Used keyboard shortcuts */
|
|
16
|
+
usedShortcuts: boolean;
|
|
17
|
+
/** Scrolled to find features */
|
|
18
|
+
searchedFeatures: boolean;
|
|
19
|
+
/** Requested help */
|
|
20
|
+
requestedHelp: boolean;
|
|
21
|
+
/** Used voice input */
|
|
22
|
+
usedVoice: boolean;
|
|
23
|
+
/** Interaction timestamp */
|
|
24
|
+
timestamp: number;
|
|
25
|
+
}
|
|
26
|
+
interface LiteracyScore {
|
|
27
|
+
level: TechLiteracyLevel;
|
|
28
|
+
confidence: number;
|
|
29
|
+
signals: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Detect tech literacy level from interaction patterns
|
|
33
|
+
*/
|
|
34
|
+
declare function detectTechLiteracy(interactions: InteractionPattern[]): Promise<LiteracyScore>;
|
|
35
|
+
/**
|
|
36
|
+
* Tech literacy detector with continuous learning
|
|
37
|
+
*/
|
|
38
|
+
declare class TechLiteracyDetector {
|
|
39
|
+
private interactions;
|
|
40
|
+
private currentLevel;
|
|
41
|
+
private onLevelChange?;
|
|
42
|
+
constructor(options?: {
|
|
43
|
+
initialLevel?: TechLiteracyLevel;
|
|
44
|
+
onLevelChange?: (level: TechLiteracyLevel) => void;
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Record an interaction for analysis
|
|
48
|
+
*/
|
|
49
|
+
recordInteraction(pattern: Omit<InteractionPattern, 'timestamp'>): void;
|
|
50
|
+
/**
|
|
51
|
+
* Evaluate current literacy level
|
|
52
|
+
*/
|
|
53
|
+
evaluate(): Promise<LiteracyScore>;
|
|
54
|
+
/**
|
|
55
|
+
* Get current assessed level
|
|
56
|
+
*/
|
|
57
|
+
getLevel(): TechLiteracyLevel;
|
|
58
|
+
/**
|
|
59
|
+
* Manually set level (user preference)
|
|
60
|
+
*/
|
|
61
|
+
setLevel(level: TechLiteracyLevel): void;
|
|
62
|
+
}
|
|
63
|
+
declare const LITERACY_UI_CONFIGS: {
|
|
64
|
+
readonly beginner: {
|
|
65
|
+
readonly buttonSize: "large";
|
|
66
|
+
readonly fontSize: "large";
|
|
67
|
+
readonly navigation: "simple";
|
|
68
|
+
readonly icons: "labeled";
|
|
69
|
+
readonly animations: "minimal";
|
|
70
|
+
readonly guidance: "proactive";
|
|
71
|
+
readonly inputMode: "touch";
|
|
72
|
+
readonly errorHandling: "guided";
|
|
73
|
+
readonly confirmations: "explicit";
|
|
74
|
+
readonly shortcuts: "hidden";
|
|
75
|
+
};
|
|
76
|
+
readonly intermediate: {
|
|
77
|
+
readonly buttonSize: "medium";
|
|
78
|
+
readonly fontSize: "medium";
|
|
79
|
+
readonly navigation: "standard";
|
|
80
|
+
readonly icons: "tooltips";
|
|
81
|
+
readonly animations: "standard";
|
|
82
|
+
readonly guidance: "contextual";
|
|
83
|
+
readonly inputMode: "mixed";
|
|
84
|
+
readonly errorHandling: "inline";
|
|
85
|
+
readonly confirmations: "smart";
|
|
86
|
+
readonly shortcuts: "discoverable";
|
|
87
|
+
};
|
|
88
|
+
readonly advanced: {
|
|
89
|
+
readonly buttonSize: "compact";
|
|
90
|
+
readonly fontSize: "small";
|
|
91
|
+
readonly navigation: "full";
|
|
92
|
+
readonly icons: "minimal";
|
|
93
|
+
readonly animations: "full";
|
|
94
|
+
readonly guidance: "on-demand";
|
|
95
|
+
readonly inputMode: "keyboard";
|
|
96
|
+
readonly errorHandling: "technical";
|
|
97
|
+
readonly confirmations: "minimal";
|
|
98
|
+
readonly shortcuts: "prominent";
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* WCAG color contrast utilities.
|
|
104
|
+
*
|
|
105
|
+
* Implements the WCAG 2.1 relative luminance and contrast ratio algorithm
|
|
106
|
+
* for checking foreground/background color accessibility.
|
|
107
|
+
*/
|
|
108
|
+
/** Calculate relative luminance per WCAG 2.1. */
|
|
109
|
+
declare function relativeLuminance(hex: string): number;
|
|
110
|
+
/** Calculate the contrast ratio between two hex colors. */
|
|
111
|
+
declare function contrastRatio(fg: string, bg: string): number;
|
|
112
|
+
/**
|
|
113
|
+
* Check if a foreground/background pair meets WCAG contrast requirements.
|
|
114
|
+
*
|
|
115
|
+
* @param fg Foreground hex color (e.g. `'#333333'`)
|
|
116
|
+
* @param bg Background hex color (e.g. `'#ffffff'`)
|
|
117
|
+
* @param level `'AA'` (4.5:1 normal, 3:1 large) or `'AAA'` (7:1 normal, 4.5:1 large)
|
|
118
|
+
* @param large Whether the text is "large" (>= 18pt or >= 14pt bold)
|
|
119
|
+
*/
|
|
120
|
+
declare function meetsWCAG(fg: string, bg: string, level?: 'AA' | 'AAA', large?: boolean): boolean;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* React hook for detecting `prefers-reduced-motion` media query.
|
|
124
|
+
*
|
|
125
|
+
* Returns `true` when the user has enabled reduced motion in their
|
|
126
|
+
* OS accessibility settings. Components should disable non-essential
|
|
127
|
+
* animations when this is `true`.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```tsx
|
|
131
|
+
* const reduced = useReducedMotion();
|
|
132
|
+
* return <div style={{ transition: reduced ? 'none' : 'all 0.3s' }} />;
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
declare function useReducedMotion(): boolean;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* React hook for trapping focus within a container element.
|
|
139
|
+
*
|
|
140
|
+
* Used for modals, dialogs, and drawers to ensure keyboard users
|
|
141
|
+
* cannot Tab outside the container while it is active.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```tsx
|
|
145
|
+
* function Modal({ open, children }) {
|
|
146
|
+
* const ref = useFocusTrap<HTMLDivElement>(open);
|
|
147
|
+
* return open ? <div ref={ref} role="dialog">{children}</div> : null;
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
declare function useFocusTrap<T extends HTMLElement>(active: boolean): RefObject<T | null>;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* React hook for screen reader announcements via `aria-live` regions.
|
|
156
|
+
*
|
|
157
|
+
* Creates an invisible live region and provides an `announce()` function
|
|
158
|
+
* that dynamically updates its content, causing screen readers to
|
|
159
|
+
* read the message aloud.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```tsx
|
|
163
|
+
* const { announce, liveRegionProps } = useAnnounce();
|
|
164
|
+
* // Place the live region once in your layout:
|
|
165
|
+
* <div {...liveRegionProps} />
|
|
166
|
+
* // Then announce messages:
|
|
167
|
+
* announce('3 items selected');
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
interface LiveRegionProps {
|
|
171
|
+
role: 'status';
|
|
172
|
+
'aria-live': 'polite' | 'assertive';
|
|
173
|
+
'aria-atomic': boolean;
|
|
174
|
+
style: Record<string, string | number>;
|
|
175
|
+
}
|
|
176
|
+
declare function useAnnounce(politeness?: 'polite' | 'assertive'): {
|
|
177
|
+
announce: (message: string) => void;
|
|
178
|
+
liveRegionProps: LiveRegionProps & {
|
|
179
|
+
ref: react.MutableRefObject<HTMLElement | null>;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export { LITERACY_UI_CONFIGS, type LiveRegionProps, TechLiteracyDetector, type TechLiteracyLevel, contrastRatio, detectTechLiteracy, meetsWCAG, relativeLuminance, useAnnounce, useFocusTrap, useReducedMotion };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,iBAAiB,EAClB,MAAM,iBAAiB,CAAC"}
|