@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 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
@@ -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,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"}