@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.2.9 → 0.2.11
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/CHANGELOG.md +1 -1
- package/dist/components/ui/accessibility-demo.esm.js +30 -24
- package/dist/components/ui/accessibility-demo.js +30 -24
- package/dist/components/ui/advanced-component-architecture-demo.esm.js +235 -179
- package/dist/components/ui/advanced-component-architecture-demo.js +235 -179
- package/dist/components/ui/advanced-transition-system-demo.esm.js +110 -64
- package/dist/components/ui/advanced-transition-system-demo.js +110 -64
- package/dist/components/ui/advanced-transition-system.esm.js +166 -122
- package/dist/components/ui/advanced-transition-system.js +166 -122
- package/dist/components/ui/animation/animated-container.esm.js +52 -29
- package/dist/components/ui/animation/animated-container.js +52 -29
- package/dist/components/ui/animation/staggered-container.esm.js +18 -9
- package/dist/components/ui/animation/staggered-container.js +18 -9
- package/dist/components/ui/animation-demo.esm.js +67 -35
- package/dist/components/ui/animation-demo.js +67 -35
- package/dist/components/ui/badge.esm.js +9 -6
- package/dist/components/ui/badge.js +9 -6
- package/dist/components/ui/battery-conscious-animation-demo.esm.js +122 -87
- package/dist/components/ui/battery-conscious-animation-demo.js +122 -87
- package/dist/components/ui/border-radius-shadow-demo.esm.js +23 -12
- package/dist/components/ui/border-radius-shadow-demo.js +23 -12
- package/dist/components/ui/button.esm.js +8 -2
- package/dist/components/ui/button.js +8 -2
- package/dist/components/ui/card.esm.js +33 -8
- package/dist/components/ui/card.js +33 -8
- package/dist/components/ui/checkbox.esm.js +3 -3
- package/dist/components/ui/checkbox.js +3 -3
- package/dist/components/ui/color-preview.esm.js +68 -45
- package/dist/components/ui/color-preview.js +68 -45
- package/dist/components/ui/data-display/chart.esm.js +112 -84
- package/dist/components/ui/data-display/chart.js +112 -84
- package/dist/components/ui/data-display/data-grid-simple.esm.js +1 -1
- package/dist/components/ui/data-display/data-grid-simple.js +1 -1
- package/dist/components/ui/data-display/data-grid.esm.js +80 -67
- package/dist/components/ui/data-display/data-grid.js +80 -67
- package/dist/components/ui/data-display/list.esm.js +53 -45
- package/dist/components/ui/data-display/list.js +53 -45
- package/dist/components/ui/data-display/table.esm.js +62 -54
- package/dist/components/ui/data-display/table.js +62 -54
- package/dist/components/ui/data-display/timeline.esm.js +39 -34
- package/dist/components/ui/data-display/timeline.js +39 -34
- package/dist/components/ui/data-display/tree.esm.js +116 -84
- package/dist/components/ui/data-display/tree.js +116 -84
- package/dist/components/ui/data-display/types.esm.js +389 -364
- package/dist/components/ui/data-display/types.js +389 -364
- package/dist/components/ui/enterprise-mobile-experience-demo.esm.js +120 -70
- package/dist/components/ui/enterprise-mobile-experience-demo.js +120 -70
- package/dist/components/ui/enterprise-mobile-experience.esm.js +124 -73
- package/dist/components/ui/enterprise-mobile-experience.js +124 -73
- package/dist/components/ui/feedback/alert.esm.js +22 -15
- package/dist/components/ui/feedback/alert.js +22 -15
- package/dist/components/ui/feedback/progress.esm.js +47 -24
- package/dist/components/ui/feedback/progress.js +47 -24
- package/dist/components/ui/feedback/skeleton.esm.js +39 -29
- package/dist/components/ui/feedback/skeleton.js +39 -29
- package/dist/components/ui/feedback/toast.esm.js +62 -38
- package/dist/components/ui/feedback/toast.js +62 -38
- package/dist/components/ui/feedback/types.esm.js +83 -83
- package/dist/components/ui/feedback/types.js +83 -83
- package/dist/components/ui/font-preview.esm.js +41 -39
- package/dist/components/ui/font-preview.js +41 -39
- package/dist/components/ui/form-demo.esm.js +150 -113
- package/dist/components/ui/form-demo.js +150 -113
- package/dist/components/ui/hardware-acceleration-demo.esm.js +137 -87
- package/dist/components/ui/hardware-acceleration-demo.js +137 -87
- package/dist/components/ui/input.esm.js +4 -1
- package/dist/components/ui/input.js +4 -1
- package/dist/components/ui/layout-demo.esm.js +81 -56
- package/dist/components/ui/layout-demo.js +81 -56
- package/dist/components/ui/layouts/adaptive-layout.esm.js +27 -8
- package/dist/components/ui/layouts/adaptive-layout.js +27 -8
- package/dist/components/ui/layouts/desktop-layout.esm.js +39 -19
- package/dist/components/ui/layouts/desktop-layout.js +39 -19
- package/dist/components/ui/layouts/mobile-layout.esm.js +19 -9
- package/dist/components/ui/layouts/mobile-layout.js +19 -9
- package/dist/components/ui/layouts/tablet-layout.esm.js +28 -14
- package/dist/components/ui/layouts/tablet-layout.js +28 -14
- package/dist/components/ui/mobile-form-validation.esm.js +120 -87
- package/dist/components/ui/mobile-form-validation.js +120 -87
- package/dist/components/ui/mobile-input-demo.esm.js +19 -13
- package/dist/components/ui/mobile-input-demo.js +19 -13
- package/dist/components/ui/mobile-input.esm.js +185 -120
- package/dist/components/ui/mobile-input.js +185 -120
- package/dist/components/ui/mobile-skeleton-loading-demo.esm.js +128 -111
- package/dist/components/ui/mobile-skeleton-loading-demo.js +128 -111
- package/dist/components/ui/navigation/breadcrumb.esm.js +17 -14
- package/dist/components/ui/navigation/breadcrumb.js +17 -14
- package/dist/components/ui/navigation/index.esm.js +0 -1
- package/dist/components/ui/navigation/index.js +0 -1
- package/dist/components/ui/navigation/menu.esm.js +49 -35
- package/dist/components/ui/navigation/menu.js +49 -35
- package/dist/components/ui/navigation/navigation-demo.esm.js +81 -74
- package/dist/components/ui/navigation/navigation-demo.js +81 -74
- package/dist/components/ui/navigation/pagination.esm.js +62 -50
- package/dist/components/ui/navigation/pagination.js +62 -50
- package/dist/components/ui/navigation/sidebar.esm.js +56 -42
- package/dist/components/ui/navigation/sidebar.js +56 -42
- package/dist/components/ui/navigation/stepper.esm.js +34 -23
- package/dist/components/ui/navigation/stepper.js +34 -23
- package/dist/components/ui/navigation/tabs.esm.js +32 -21
- package/dist/components/ui/navigation/tabs.js +32 -21
- package/dist/components/ui/navigation/types.esm.js +196 -195
- package/dist/components/ui/navigation/types.js +196 -195
- package/dist/components/ui/overlay/backdrop.esm.js +17 -16
- package/dist/components/ui/overlay/backdrop.js +17 -16
- package/dist/components/ui/overlay/focus-manager.esm.js +21 -19
- package/dist/components/ui/overlay/focus-manager.js +21 -19
- package/dist/components/ui/overlay/index.esm.js +0 -2
- package/dist/components/ui/overlay/index.js +0 -2
- package/dist/components/ui/overlay/modal.esm.js +38 -34
- package/dist/components/ui/overlay/modal.js +38 -34
- package/dist/components/ui/overlay/overlay-manager.esm.js +25 -20
- package/dist/components/ui/overlay/overlay-manager.js +25 -20
- package/dist/components/ui/overlay/popover.esm.js +74 -58
- package/dist/components/ui/overlay/popover.js +74 -58
- package/dist/components/ui/overlay/portal.esm.js +7 -7
- package/dist/components/ui/overlay/portal.js +7 -7
- package/dist/components/ui/overlay/tooltip.esm.js +54 -39
- package/dist/components/ui/overlay/tooltip.js +54 -39
- package/dist/components/ui/overlay/types.esm.js +132 -131
- package/dist/components/ui/overlay/types.js +132 -131
- package/dist/components/ui/performance-demo.esm.js +135 -88
- package/dist/components/ui/performance-demo.js +135 -88
- package/dist/components/ui/semantic-input-system-demo.esm.js +117 -80
- package/dist/components/ui/semantic-input-system-demo.js +117 -80
- package/dist/components/ui/theme-customizer.esm.js +84 -52
- package/dist/components/ui/theme-customizer.js +84 -52
- package/dist/components/ui/theme-preview.esm.js +95 -43
- package/dist/components/ui/theme-preview.js +95 -43
- package/dist/components/ui/theme-switcher.esm.js +70 -44
- package/dist/components/ui/theme-switcher.js +70 -44
- package/dist/components/ui/theme-toggle.esm.js +3 -3
- package/dist/components/ui/theme-toggle.js +3 -3
- package/dist/components/ui/token-demo.esm.js +33 -21
- package/dist/components/ui/token-demo.js +33 -21
- package/dist/components/ui/touch-demo.esm.js +102 -73
- package/dist/components/ui/touch-demo.js +102 -73
- package/dist/components/ui/touch-friendly-interface-demo.esm.js +102 -64
- package/dist/components/ui/touch-friendly-interface-demo.js +102 -64
- package/dist/components/ui/touch-friendly-interface.esm.js +85 -61
- package/dist/components/ui/touch-friendly-interface.js +85 -61
- package/dist/hooks/use-accessibility-support.esm.js +115 -85
- package/dist/hooks/use-accessibility-support.js +115 -85
- package/dist/hooks/use-adaptive-layout.esm.js +56 -33
- package/dist/hooks/use-adaptive-layout.js +56 -33
- package/dist/hooks/use-advanced-patterns.esm.js +57 -42
- package/dist/hooks/use-advanced-patterns.js +57 -42
- package/dist/hooks/use-advanced-transition-system.esm.js +112 -71
- package/dist/hooks/use-advanced-transition-system.js +112 -71
- package/dist/hooks/use-animation-profile.esm.js +63 -34
- package/dist/hooks/use-animation-profile.js +63 -34
- package/dist/hooks/use-battery-animations.esm.js +80 -55
- package/dist/hooks/use-battery-animations.js +80 -55
- package/dist/hooks/use-battery-conscious-loading.esm.js +166 -123
- package/dist/hooks/use-battery-conscious-loading.js +166 -123
- package/dist/hooks/use-battery-optimization.esm.js +78 -55
- package/dist/hooks/use-battery-optimization.js +78 -55
- package/dist/hooks/use-battery-status.esm.js +73 -51
- package/dist/hooks/use-battery-status.js +73 -51
- package/dist/hooks/use-component-performance.esm.js +62 -47
- package/dist/hooks/use-component-performance.js +62 -47
- package/dist/hooks/use-device-loading-states.esm.js +152 -109
- package/dist/hooks/use-device-loading-states.js +152 -109
- package/dist/hooks/use-device.esm.js +25 -14
- package/dist/hooks/use-device.js +25 -14
- package/dist/hooks/use-enterprise-mobile-experience.esm.js +137 -88
- package/dist/hooks/use-enterprise-mobile-experience.js +137 -88
- package/dist/hooks/use-form-feedback.esm.js +124 -81
- package/dist/hooks/use-form-feedback.js +124 -81
- package/dist/hooks/use-form-performance.esm.js +127 -92
- package/dist/hooks/use-form-performance.js +127 -92
- package/dist/hooks/use-frame-rate.esm.js +56 -37
- package/dist/hooks/use-frame-rate.js +56 -37
- package/dist/hooks/use-gestures.esm.js +96 -72
- package/dist/hooks/use-gestures.js +96 -72
- package/dist/hooks/use-hardware-acceleration.esm.js +65 -37
- package/dist/hooks/use-hardware-acceleration.js +65 -37
- package/dist/hooks/use-input-accessibility.esm.js +157 -119
- package/dist/hooks/use-input-accessibility.js +157 -119
- package/dist/hooks/use-input-performance.esm.js +139 -104
- package/dist/hooks/use-input-performance.js +139 -104
- package/dist/hooks/use-layout-performance.esm.js +50 -29
- package/dist/hooks/use-layout-performance.js +50 -29
- package/dist/hooks/use-loading-accessibility.esm.js +209 -169
- package/dist/hooks/use-loading-accessibility.js +209 -169
- package/dist/hooks/use-loading-performance.esm.js +117 -93
- package/dist/hooks/use-loading-performance.js +117 -93
- package/dist/hooks/use-memory-usage.esm.js +57 -38
- package/dist/hooks/use-memory-usage.js +57 -38
- package/dist/hooks/use-mobile-form-layout.esm.js +111 -74
- package/dist/hooks/use-mobile-form-layout.js +111 -74
- package/dist/hooks/use-mobile-form-validation.esm.js +211 -144
- package/dist/hooks/use-mobile-form-validation.js +211 -144
- package/dist/hooks/use-mobile-keyboard-optimization.esm.js +154 -113
- package/dist/hooks/use-mobile-keyboard-optimization.js +154 -113
- package/dist/hooks/use-mobile-layout.esm.js +73 -51
- package/dist/hooks/use-mobile-layout.js +73 -51
- package/dist/hooks/use-mobile-optimization.esm.js +72 -44
- package/dist/hooks/use-mobile-optimization.js +72 -44
- package/dist/hooks/use-mobile-skeleton.esm.js +97 -64
- package/dist/hooks/use-mobile-skeleton.js +97 -64
- package/dist/hooks/use-mobile-touch.esm.js +128 -93
- package/dist/hooks/use-mobile-touch.js +128 -93
- package/dist/hooks/use-performance-throttling.esm.js +72 -48
- package/dist/hooks/use-performance-throttling.js +72 -48
- package/dist/hooks/use-performance.esm.js +90 -52
- package/dist/hooks/use-performance.js +90 -52
- package/dist/hooks/use-reusable-architecture.esm.js +94 -65
- package/dist/hooks/use-reusable-architecture.js +94 -65
- package/dist/hooks/use-semantic-input-types.esm.js +166 -124
- package/dist/hooks/use-semantic-input-types.js +166 -124
- package/dist/hooks/use-semantic-input.esm.js +178 -126
- package/dist/hooks/use-semantic-input.js +178 -126
- package/dist/hooks/use-tablet-layout.esm.js +67 -38
- package/dist/hooks/use-tablet-layout.js +67 -38
- package/dist/hooks/use-touch-friendly-input.esm.js +193 -149
- package/dist/hooks/use-touch-friendly-input.js +193 -149
- package/dist/hooks/use-touch-friendly-interface.esm.js +99 -67
- package/dist/hooks/use-touch-friendly-interface.js +99 -67
- package/dist/hooks/use-touch-optimization.esm.js +99 -72
- package/dist/hooks/use-touch-optimization.js +99 -72
- package/dist/index.esm.js +157 -281
- package/dist/index.js +157 -281
- package/dist/lib/utils.esm.js +1 -1
- package/dist/lib/utils.js +1 -1
- package/dist/plugins/theme-css-generator.esm.js +104 -55
- package/dist/plugins/theme-css-generator.js +104 -55
- package/dist/provider.esm.js +4 -4
- package/dist/provider.js +4 -4
- package/dist/styles.css +1 -1
- package/dist/theme.esm.js +633 -468
- package/dist/theme.js +633 -468
- package/dist/themes/ThemeContext.esm.js +15 -15
- package/dist/themes/ThemeContext.js +15 -15
- package/dist/themes/ThemeProvider.esm.js +25 -22
- package/dist/themes/ThemeProvider.js +25 -22
- package/dist/themes/accessibility.esm.js +147 -108
- package/dist/themes/accessibility.js +147 -108
- package/dist/themes/aria-patterns.esm.js +198 -162
- package/dist/themes/aria-patterns.js +198 -162
- package/dist/themes/base-themes.esm.js +14 -11
- package/dist/themes/base-themes.js +14 -11
- package/dist/themes/colorManager.esm.js +101 -83
- package/dist/themes/colorManager.js +101 -83
- package/dist/themes/examples/dark-theme.esm.js +133 -103
- package/dist/themes/examples/dark-theme.js +133 -103
- package/dist/themes/examples/minimal-theme.esm.js +83 -61
- package/dist/themes/examples/minimal-theme.js +83 -61
- package/dist/themes/focus-management.esm.js +202 -143
- package/dist/themes/focus-management.js +202 -143
- package/dist/themes/fontLoader.esm.js +28 -19
- package/dist/themes/fontLoader.js +28 -19
- package/dist/themes/high-contrast.esm.js +152 -104
- package/dist/themes/high-contrast.js +152 -104
- package/dist/themes/index.esm.js +1 -1
- package/dist/themes/index.js +1 -1
- package/dist/themes/inheritance.esm.js +35 -27
- package/dist/themes/inheritance.js +35 -27
- package/dist/themes/keyboard-navigation.esm.js +152 -123
- package/dist/themes/keyboard-navigation.js +152 -123
- package/dist/themes/motion-reduction.esm.js +193 -133
- package/dist/themes/motion-reduction.js +193 -133
- package/dist/themes/navigation.esm.js +146 -146
- package/dist/themes/navigation.js +146 -146
- package/dist/themes/screen-reader.esm.js +159 -94
- package/dist/themes/screen-reader.js +159 -94
- package/dist/themes/systemThemeDetector.esm.js +42 -34
- package/dist/themes/systemThemeDetector.js +42 -34
- package/dist/themes/themeCSSUpdater.esm.js +21 -9
- package/dist/themes/themeCSSUpdater.js +21 -9
- package/dist/themes/themePersistence.esm.js +68 -47
- package/dist/themes/themePersistence.js +68 -47
- package/dist/themes/themes/stan-design.esm.js +633 -468
- package/dist/themes/themes/stan-design.js +633 -468
- package/dist/themes/types.esm.js +301 -287
- package/dist/themes/types.js +301 -287
- package/dist/themes/useSystemTheme.esm.js +4 -4
- package/dist/themes/useSystemTheme.js +4 -4
- package/dist/themes/useTheme.esm.js +4 -4
- package/dist/themes/useTheme.js +4 -4
- package/dist/themes/validation.esm.js +128 -77
- package/dist/themes/validation.js +128 -77
- package/dist/tokens/index.esm.js +1 -2
- package/dist/tokens/index.js +1 -2
- package/dist/tokens/tokenExporter.esm.js +87 -61
- package/dist/tokens/tokenExporter.js +87 -61
- package/dist/tokens/tokenGenerator.esm.js +86 -77
- package/dist/tokens/tokenGenerator.js +86 -77
- package/dist/tokens/tokenManager.esm.js +64 -51
- package/dist/tokens/tokenManager.js +64 -51
- package/dist/tokens/tokenValidator.esm.js +193 -147
- package/dist/tokens/tokenValidator.js +193 -147
- package/dist/tokens/types.esm.js +49 -35
- package/dist/tokens/types.js +49 -35
- package/dist/utils/bundle-analyzer.esm.js +83 -65
- package/dist/utils/bundle-analyzer.js +83 -65
- package/dist/utils/bundle-splitting.esm.js +142 -117
- package/dist/utils/bundle-splitting.js +142 -117
- package/dist/utils/lazy-loading.esm.js +132 -106
- package/dist/utils/lazy-loading.js +132 -106
- package/dist/utils/performance-monitor.esm.js +170 -129
- package/dist/utils/performance-monitor.js +170 -129
- package/dist/utils/tree-shaking.esm.js +69 -61
- package/dist/utils/tree-shaking.js +69 -61
- package/package.json +1 -1
- package/src/index.ts +146 -146
|
@@ -4,34 +4,40 @@ import { useTouchFriendlyInterface } from '../../hooks/use-touch-friendly-interf
|
|
|
4
4
|
|
|
5
5
|
// Touch-Friendly Button Component
|
|
6
6
|
export interface TouchFriendlyButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
7
|
-
variant
|
|
7
|
+
variant?: 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive'
|
|
8
|
+
size?: 'sm' | 'default' | 'lg' | 'xl'
|
|
9
|
+
feedback?: 'scale' | 'ripple' | 'color' | 'none'
|
|
10
|
+
children: React.ReactNode
|
|
11
|
+
}
|
|
8
12
|
|
|
9
13
|
export const TouchFriendlyButton = forwardRef<HTMLButtonElement, TouchFriendlyButtonProps>(
|
|
10
14
|
({ className, variant = 'default', size = 'default', feedback = 'scale', children, ...props }, ref) => {
|
|
11
15
|
const { isTouchTargetCompliant, getTouchTargetSize } = useTouchFriendlyInterface({
|
|
12
|
-
minSize,
|
|
16
|
+
minSize: 44,
|
|
13
17
|
feedback
|
|
14
18
|
})
|
|
15
19
|
|
|
16
20
|
const baseClasses = 'touch-target touch-friendly-button touch-interaction touch-performance'
|
|
17
21
|
const feedbackClasses = {
|
|
18
|
-
scale,
|
|
19
|
-
ripple,
|
|
20
|
-
color,
|
|
21
|
-
none
|
|
22
|
+
scale: 'touch-feedback',
|
|
23
|
+
ripple: 'touch-ripple',
|
|
24
|
+
color: 'touch-state-hover touch-state-active',
|
|
25
|
+
none: ''
|
|
26
|
+
}
|
|
22
27
|
|
|
23
28
|
const variantClasses = {
|
|
24
|
-
default,
|
|
25
|
-
secondary,
|
|
26
|
-
outline,
|
|
27
|
-
ghost,
|
|
28
|
-
destructive
|
|
29
|
+
default: 'touch-friendly-button',
|
|
30
|
+
secondary: 'touch-friendly-button-secondary',
|
|
31
|
+
outline: 'touch-target touch-spacing bg-transparent border border-cs-border text-cs-text-primary hover:bg-cs-hover-bg',
|
|
32
|
+
ghost: 'touch-target touch-spacing bg-transparent text-cs-text-primary hover:bg-cs-hover-bg',
|
|
33
|
+
destructive: 'touch-target touch-spacing bg-cs-error text-white hover:bg-cs-error-hover'
|
|
34
|
+
}
|
|
29
35
|
|
|
30
36
|
const sizeClasses = {
|
|
31
|
-
sm] min-w-[44px] px-3 py-2 text-sm',
|
|
32
|
-
default] min-w-[48px] px-4 py-3 text-base',
|
|
33
|
-
lg] min-w-[56px] px-6 py-4 text-lg',
|
|
34
|
-
xl] min-w-[64px] px-8 py-5 text-xl'
|
|
37
|
+
sm: 'min-h-[44px] min-w-[44px] px-3 py-2 text-sm',
|
|
38
|
+
default: 'min-h-[48px] min-w-[48px] px-4 py-3 text-base',
|
|
39
|
+
lg: 'min-h-[56px] min-w-[56px] px-6 py-4 text-lg',
|
|
40
|
+
xl: 'min-h-[64px] min-w-[64px] px-8 py-5 text-xl'
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
return (
|
|
@@ -45,8 +51,8 @@ export const TouchFriendlyButton = forwardRef<HTMLButtonElement, TouchFriendlyBu
|
|
|
45
51
|
className
|
|
46
52
|
)}
|
|
47
53
|
style={{
|
|
48
|
-
minHeight)}px`,
|
|
49
|
-
minWidth)}px`
|
|
54
|
+
minHeight: `${getTouchTargetSize()}px`,
|
|
55
|
+
minWidth: `${getTouchTargetSize()}px`
|
|
50
56
|
}}
|
|
51
57
|
{...props}
|
|
52
58
|
>
|
|
@@ -65,26 +71,29 @@ TouchFriendlyButton.displayName = 'TouchFriendlyButton'
|
|
|
65
71
|
|
|
66
72
|
// Touch-Friendly Input Component
|
|
67
73
|
export interface TouchFriendlyInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
68
|
-
touchSize
|
|
74
|
+
touchSize?: 'sm' | 'default' | 'lg'
|
|
75
|
+
feedback?: 'scale' | 'ripple' | 'color' | 'none'
|
|
76
|
+
}
|
|
69
77
|
|
|
70
78
|
export const TouchFriendlyInput = forwardRef<HTMLInputElement, TouchFriendlyInputProps>(
|
|
71
79
|
({ className, touchSize = 'default', feedback = 'scale', ...props }, ref) => {
|
|
72
80
|
const { getTouchTargetSize } = useTouchFriendlyInterface({
|
|
73
|
-
minSize,
|
|
81
|
+
minSize: 44,
|
|
74
82
|
feedback
|
|
75
83
|
})
|
|
76
84
|
|
|
77
85
|
const baseClasses = 'touch-target touch-friendly-input touch-interaction touch-performance'
|
|
78
86
|
const feedbackClasses = {
|
|
79
|
-
scale,
|
|
80
|
-
ripple,
|
|
81
|
-
color,
|
|
82
|
-
none
|
|
87
|
+
scale: 'touch-feedback',
|
|
88
|
+
ripple: 'touch-ripple',
|
|
89
|
+
color: 'touch-state-hover touch-state-focus',
|
|
90
|
+
none: ''
|
|
91
|
+
}
|
|
83
92
|
|
|
84
93
|
const sizeClasses = {
|
|
85
|
-
sm] min-w-[44px] px-3 py-2 text-sm',
|
|
86
|
-
default] min-w-[48px] px-4 py-3 text-base',
|
|
87
|
-
lg] min-w-[56px] px-6 py-4 text-lg'
|
|
94
|
+
sm: 'min-h-[44px] min-w-[44px] px-3 py-2 text-sm',
|
|
95
|
+
default: 'min-h-[48px] min-w-[48px] px-4 py-3 text-base',
|
|
96
|
+
lg: 'min-h-[56px] min-w-[56px] px-6 py-4 text-lg'
|
|
88
97
|
}
|
|
89
98
|
|
|
90
99
|
return (
|
|
@@ -97,8 +106,8 @@ export const TouchFriendlyInput = forwardRef<HTMLInputElement, TouchFriendlyInpu
|
|
|
97
106
|
className
|
|
98
107
|
)}
|
|
99
108
|
style={{
|
|
100
|
-
minHeight)}px`,
|
|
101
|
-
minWidth)}px`
|
|
109
|
+
minHeight: `${getTouchTargetSize()}px`,
|
|
110
|
+
minWidth: `${getTouchTargetSize()}px`
|
|
102
111
|
}}
|
|
103
112
|
{...props}
|
|
104
113
|
/>
|
|
@@ -110,29 +119,37 @@ TouchFriendlyInput.displayName = 'TouchFriendlyInput'
|
|
|
110
119
|
|
|
111
120
|
// Touch-Friendly Card Component
|
|
112
121
|
export interface TouchFriendlyCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
113
|
-
size
|
|
122
|
+
size?: 'sm' | 'default' | 'lg'
|
|
123
|
+
feedback?: 'scale' | 'ripple' | 'color' | 'none'
|
|
124
|
+
interactive?: boolean
|
|
125
|
+
}
|
|
114
126
|
|
|
115
127
|
export const TouchFriendlyCard = forwardRef<HTMLDivElement, TouchFriendlyCardProps>(
|
|
116
128
|
({ className, size = 'default', feedback = 'scale', interactive = false, children, ...props }, ref) => {
|
|
117
129
|
const { isTouchTargetCompliant, getTouchTargetSize } = useTouchFriendlyInterface({
|
|
118
|
-
minSize,
|
|
130
|
+
minSize: 44,
|
|
119
131
|
feedback
|
|
120
132
|
})
|
|
121
133
|
|
|
122
134
|
const baseClasses = 'touch-friendly-card touch-interaction touch-performance'
|
|
123
135
|
const feedbackClasses = interactive ? {
|
|
124
|
-
scale,
|
|
125
|
-
ripple,
|
|
126
|
-
color,
|
|
127
|
-
none
|
|
136
|
+
scale: 'touch-feedback',
|
|
137
|
+
ripple: 'touch-ripple',
|
|
138
|
+
color: 'touch-state-hover touch-state-active',
|
|
139
|
+
none: ''
|
|
140
|
+
} : { scale: '', ripple: '', color: '', none: '' }
|
|
128
141
|
|
|
129
142
|
const sizeClasses = {
|
|
130
|
-
sm] min-w-[44px] p-3',
|
|
131
|
-
default] min-w-[48px] p-4',
|
|
132
|
-
lg] min-w-[56px] p-6'
|
|
143
|
+
sm: 'min-h-[44px] min-w-[44px] p-3',
|
|
144
|
+
default: 'min-h-[48px] min-w-[48px] p-4',
|
|
145
|
+
lg: 'min-h-[56px] min-w-[56px] p-6'
|
|
133
146
|
}
|
|
134
147
|
|
|
135
|
-
const interactiveClasses = interactive ? 'cursor-pointer'
|
|
148
|
+
const interactiveClasses = interactive ? 'cursor-pointer' : ''
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<div
|
|
152
|
+
ref={ref}
|
|
136
153
|
className={cn(
|
|
137
154
|
baseClasses,
|
|
138
155
|
feedbackClasses[feedback],
|
|
@@ -141,8 +158,8 @@ export const TouchFriendlyCard = forwardRef<HTMLDivElement, TouchFriendlyCardPro
|
|
|
141
158
|
className
|
|
142
159
|
)}
|
|
143
160
|
style={{
|
|
144
|
-
minHeight)}px`,
|
|
145
|
-
minWidth)}px`
|
|
161
|
+
minHeight: `${getTouchTargetSize()}px`,
|
|
162
|
+
minWidth: `${getTouchTargetSize()}px`
|
|
146
163
|
}}
|
|
147
164
|
{...props}
|
|
148
165
|
>
|
|
@@ -161,20 +178,23 @@ TouchFriendlyCard.displayName = 'TouchFriendlyCard'
|
|
|
161
178
|
|
|
162
179
|
// Touch-Friendly Toggle Component
|
|
163
180
|
export interface TouchFriendlyToggleProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
164
|
-
checked
|
|
165
|
-
|
|
181
|
+
checked?: boolean
|
|
182
|
+
onCheckedChange?: (checked: boolean) => void
|
|
183
|
+
size?: 'sm' | 'default' | 'lg'
|
|
184
|
+
}
|
|
166
185
|
|
|
167
186
|
export const TouchFriendlyToggle = forwardRef<HTMLButtonElement, TouchFriendlyToggleProps>(
|
|
168
187
|
({ className, checked = false, onCheckedChange, size = 'default', ...props }, ref) => {
|
|
169
188
|
const { isTouchTargetCompliant, getTouchTargetSize } = useTouchFriendlyInterface({
|
|
170
|
-
minSize,
|
|
171
|
-
feedback
|
|
189
|
+
minSize: 44,
|
|
190
|
+
feedback: 'scale'
|
|
191
|
+
})
|
|
172
192
|
|
|
173
193
|
const baseClasses = 'touch-target touch-interaction touch-performance touch-feedback'
|
|
174
194
|
const sizeClasses = {
|
|
175
|
-
sm] min-w-[44px]',
|
|
176
|
-
default] min-w-[48px]',
|
|
177
|
-
lg] min-w-[56px]'
|
|
195
|
+
sm: 'min-h-[44px] min-w-[44px]',
|
|
196
|
+
default: 'min-h-[48px] min-w-[48px]',
|
|
197
|
+
lg: 'min-h-[56px] min-w-[56px]'
|
|
178
198
|
}
|
|
179
199
|
|
|
180
200
|
const handleClick = () => {
|
|
@@ -191,13 +211,13 @@ export const TouchFriendlyToggle = forwardRef<HTMLButtonElement, TouchFriendlyTo
|
|
|
191
211
|
baseClasses,
|
|
192
212
|
sizeClasses[size],
|
|
193
213
|
'relative inline-flex items-center justify-center rounded-full transition-colors',
|
|
194
|
-
checked ? 'bg-cs-primary' ,
|
|
195
|
-
'focus,
|
|
214
|
+
checked ? 'bg-cs-primary' : 'bg-cs-border',
|
|
215
|
+
'focus:outline-none focus:ring-2 focus:ring-cs-primary focus:ring-offset-2',
|
|
196
216
|
className
|
|
197
217
|
)}
|
|
198
218
|
style={{
|
|
199
|
-
minHeight)}px`,
|
|
200
|
-
minWidth)}px`
|
|
219
|
+
minHeight: `${getTouchTargetSize()}px`,
|
|
220
|
+
minWidth: `${getTouchTargetSize()}px`
|
|
201
221
|
}}
|
|
202
222
|
onClick={handleClick}
|
|
203
223
|
{...props}
|
|
@@ -205,8 +225,9 @@ export const TouchFriendlyToggle = forwardRef<HTMLButtonElement, TouchFriendlyTo
|
|
|
205
225
|
<span
|
|
206
226
|
className={cn(
|
|
207
227
|
'inline-block rounded-full bg-white shadow transform transition-transform',
|
|
208
|
-
size === 'sm' ? 'w-5 h-5' === 'default' ? 'w-6 h-6' ,
|
|
209
|
-
checked ? 'translate-x-full'
|
|
228
|
+
size === 'sm' ? 'w-5 h-5' : size === 'default' ? 'w-6 h-6' : 'w-7 h-7',
|
|
229
|
+
checked ? 'translate-x-full' : 'translate-x-0'
|
|
230
|
+
)}
|
|
210
231
|
/>
|
|
211
232
|
{!isTouchTargetCompliant() && (
|
|
212
233
|
<span className="text-xs text-cs-warning absolute -bottom-6 left-1/2 transform -translate-x-1/2">
|
|
@@ -222,19 +243,22 @@ TouchFriendlyToggle.displayName = 'TouchFriendlyToggle'
|
|
|
222
243
|
|
|
223
244
|
// Touch-Friendly Slider Component
|
|
224
245
|
export interface TouchFriendlySliderProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
|
|
225
|
-
touchSize
|
|
246
|
+
touchSize?: 'sm' | 'default' | 'lg'
|
|
247
|
+
showValue?: boolean
|
|
248
|
+
}
|
|
226
249
|
|
|
227
250
|
export const TouchFriendlySlider = forwardRef<HTMLInputElement, TouchFriendlySliderProps>(
|
|
228
251
|
({ className, touchSize = 'default', showValue = true, ...props }, ref) => {
|
|
229
252
|
const { isTouchTargetCompliant, getTouchTargetSize } = useTouchFriendlyInterface({
|
|
230
|
-
minSize,
|
|
231
|
-
feedback
|
|
253
|
+
minSize: 44,
|
|
254
|
+
feedback: 'scale'
|
|
255
|
+
})
|
|
232
256
|
|
|
233
257
|
const baseClasses = 'touch-target touch-interaction touch-performance touch-feedback'
|
|
234
258
|
const sizeClasses = {
|
|
235
|
-
sm] min-w-[44px]',
|
|
236
|
-
default] min-w-[48px]',
|
|
237
|
-
lg] min-w-[56px]'
|
|
259
|
+
sm: 'min-h-[44px] min-w-[44px]',
|
|
260
|
+
default: 'min-h-[48px] min-w-[48px]',
|
|
261
|
+
lg: 'min-h-[56px] min-w-[56px]'
|
|
238
262
|
}
|
|
239
263
|
|
|
240
264
|
return (
|
|
@@ -246,11 +270,11 @@ export const TouchFriendlySlider = forwardRef<HTMLInputElement, TouchFriendlySli
|
|
|
246
270
|
baseClasses,
|
|
247
271
|
sizeClasses[touchSize],
|
|
248
272
|
'w-full h-2 bg-cs-border rounded-lg appearance-none cursor-pointer',
|
|
249
|
-
'focus,
|
|
273
|
+
'focus:outline-none focus:ring-2 focus:ring-cs-primary',
|
|
250
274
|
className
|
|
251
275
|
)}
|
|
252
276
|
style={{
|
|
253
|
-
minHeight)}px`
|
|
277
|
+
minHeight: `${getTouchTargetSize()}px`
|
|
254
278
|
}}
|
|
255
279
|
{...props}
|
|
256
280
|
/>
|
|
@@ -1,54 +1,71 @@
|
|
|
1
1
|
import { useState, useCallback, useRef, useEffect, KeyboardEvent } from 'react'
|
|
2
2
|
|
|
3
3
|
export interface AccessibilitySupportConfig {
|
|
4
|
-
enableAriaSupport
|
|
4
|
+
enableAriaSupport?: boolean
|
|
5
|
+
enableKeyboardNavigation?: boolean
|
|
6
|
+
enableScreenReaderSupport?: boolean
|
|
7
|
+
enableFocusManagement?: boolean
|
|
8
|
+
enableHighContrast?: boolean
|
|
9
|
+
enableReducedMotion?: boolean
|
|
10
|
+
enableVoiceControl?: boolean
|
|
11
|
+
}
|
|
5
12
|
|
|
6
13
|
export interface AccessibilityState {
|
|
7
|
-
hasAriaLabels
|
|
14
|
+
hasAriaLabels: boolean
|
|
15
|
+
hasKeyboardNavigation: boolean
|
|
16
|
+
hasScreenReaderSupport: boolean
|
|
17
|
+
hasFocusManagement: boolean
|
|
18
|
+
isHighContrast: boolean
|
|
19
|
+
isReducedMotion: boolean
|
|
20
|
+
isVoiceControlEnabled: boolean
|
|
21
|
+
accessibilityLevel: 'basic' | 'enhanced' | 'advanced'
|
|
22
|
+
}
|
|
8
23
|
|
|
9
24
|
export interface AccessibilityFeatures {
|
|
10
|
-
ariaLabels, string>
|
|
11
|
-
keyboardShortcuts, string>
|
|
12
|
-
focusableElements
|
|
25
|
+
ariaLabels: Map<string, string>
|
|
26
|
+
keyboardShortcuts: Map<string, string>
|
|
27
|
+
focusableElements: Set<string>
|
|
28
|
+
screenReaderText: Map<string, string>
|
|
13
29
|
}
|
|
14
30
|
|
|
15
31
|
export interface AccessibilitySupportCallbacks {
|
|
16
|
-
onAriaEnhanced
|
|
17
|
-
onKeyboardNavigationEnabled
|
|
18
|
-
onScreenReaderEnhanced
|
|
19
|
-
onFocusManagementImproved
|
|
20
|
-
onAccessibilityWarning
|
|
32
|
+
onAriaEnhanced?: (feature: string) => void
|
|
33
|
+
onKeyboardNavigationEnabled?: (feature: string) => void
|
|
34
|
+
onScreenReaderEnhanced?: (feature: string) => void
|
|
35
|
+
onFocusManagementImproved?: (feature: string) => void
|
|
36
|
+
onAccessibilityWarning?: (warning: string) => void
|
|
21
37
|
}
|
|
22
38
|
|
|
23
39
|
export const useAccessibilitySupport = (
|
|
24
|
-
config= {},
|
|
25
|
-
callbacks= {}
|
|
40
|
+
config: AccessibilitySupportConfig = {},
|
|
41
|
+
callbacks: AccessibilitySupportCallbacks = {}
|
|
26
42
|
) => {
|
|
27
43
|
const {
|
|
28
44
|
enableAriaSupport = true,
|
|
29
|
-
enableKeyboardNavigation= true,
|
|
45
|
+
enableKeyboardNavigation: enableKeyboardNav = true,
|
|
30
46
|
enableScreenReaderSupport = true,
|
|
31
47
|
enableFocusManagement = true,
|
|
32
|
-
enableHighContrast= true,
|
|
33
|
-
enableReducedMotion= true,
|
|
34
|
-
enableVoiceControl= true
|
|
48
|
+
enableHighContrast: enableHighContrastMode = true,
|
|
49
|
+
enableReducedMotion: enableReducedMotionMode = true,
|
|
50
|
+
enableVoiceControl: enableVoiceControlMode = true
|
|
35
51
|
} = config
|
|
36
52
|
|
|
37
53
|
const [state, setState] = useState<AccessibilityState>({
|
|
38
|
-
hasAriaLabels,
|
|
39
|
-
hasKeyboardNavigation,
|
|
40
|
-
hasScreenReaderSupport,
|
|
41
|
-
hasFocusManagement,
|
|
42
|
-
isHighContrast,
|
|
43
|
-
isReducedMotion,
|
|
44
|
-
isVoiceControlEnabled,
|
|
45
|
-
accessibilityLevel
|
|
54
|
+
hasAriaLabels: false,
|
|
55
|
+
hasKeyboardNavigation: false,
|
|
56
|
+
hasScreenReaderSupport: false,
|
|
57
|
+
hasFocusManagement: false,
|
|
58
|
+
isHighContrast: false,
|
|
59
|
+
isReducedMotion: false,
|
|
60
|
+
isVoiceControlEnabled: false,
|
|
61
|
+
accessibilityLevel: 'basic'
|
|
62
|
+
})
|
|
46
63
|
|
|
47
64
|
const [features, setFeatures] = useState<AccessibilityFeatures>({
|
|
48
|
-
ariaLabels),
|
|
49
|
-
keyboardShortcuts),
|
|
50
|
-
focusableElements),
|
|
51
|
-
screenReaderText)
|
|
65
|
+
ariaLabels: new Map(),
|
|
66
|
+
keyboardShortcuts: new Map(),
|
|
67
|
+
focusableElements: new Set(),
|
|
68
|
+
screenReaderText: new Map()
|
|
52
69
|
})
|
|
53
70
|
|
|
54
71
|
const [isEnhancing, setIsEnhancing] = useState(false)
|
|
@@ -56,12 +73,12 @@ export const useAccessibilitySupport = (
|
|
|
56
73
|
const [accessibilityWarnings, setAccessibilityWarnings] = useState<string[]>([])
|
|
57
74
|
|
|
58
75
|
const focusableElementsRef = useRef<Set<HTMLElement>>(new Set())
|
|
59
|
-
const keyboardListenersRef = useRef<Map<string, (event) => void>>(new Map())
|
|
76
|
+
const keyboardListenersRef = useRef<Map<string, (event: KeyboardEvent) => void>>(new Map())
|
|
60
77
|
|
|
61
78
|
// ARIA support
|
|
62
79
|
const enhanceAriaSupport = useCallback((
|
|
63
|
-
elementId,
|
|
64
|
-
ariaAttributes, string>
|
|
80
|
+
elementId: string,
|
|
81
|
+
ariaAttributes: Record<string, string>
|
|
65
82
|
) => {
|
|
66
83
|
if (!enableAriaSupport) return false
|
|
67
84
|
|
|
@@ -78,13 +95,14 @@ export const useAccessibilitySupport = (
|
|
|
78
95
|
setEnhancements(prev => [...prev, ...ariaEnhancements])
|
|
79
96
|
setState(prev => ({
|
|
80
97
|
...prev,
|
|
81
|
-
hasAriaLabels,
|
|
82
|
-
accessibilityLevel=== 'basic' ? 'enhanced'
|
|
98
|
+
hasAriaLabels: true,
|
|
99
|
+
accessibilityLevel: prev.accessibilityLevel === 'basic' ? 'enhanced' : 'advanced'
|
|
100
|
+
}))
|
|
83
101
|
|
|
84
102
|
// Update features
|
|
85
103
|
setFeatures(prev => ({
|
|
86
104
|
...prev,
|
|
87
|
-
ariaLabels, JSON.stringify(ariaAttributes)))
|
|
105
|
+
ariaLabels: new Map(prev.ariaLabels.set(elementId, JSON.stringify(ariaAttributes)))
|
|
88
106
|
}))
|
|
89
107
|
|
|
90
108
|
setIsEnhancing(false)
|
|
@@ -99,8 +117,8 @@ export const useAccessibilitySupport = (
|
|
|
99
117
|
|
|
100
118
|
// Keyboard navigation
|
|
101
119
|
const enableKeyboardNavigationFeature = useCallback((
|
|
102
|
-
elementId,
|
|
103
|
-
shortcuts, string>
|
|
120
|
+
elementId: string,
|
|
121
|
+
shortcuts: Record<string, string>
|
|
104
122
|
) => {
|
|
105
123
|
if (!enableKeyboardNav) return false
|
|
106
124
|
|
|
@@ -117,13 +135,14 @@ export const useAccessibilitySupport = (
|
|
|
117
135
|
setEnhancements(prev => [...prev, ...keyboardEnhancements])
|
|
118
136
|
setState(prev => ({
|
|
119
137
|
...prev,
|
|
120
|
-
hasKeyboardNavigation,
|
|
121
|
-
accessibilityLevel=== 'basic' ? 'enhanced'
|
|
138
|
+
hasKeyboardNavigation: true,
|
|
139
|
+
accessibilityLevel: prev.accessibilityLevel === 'basic' ? 'enhanced' : 'advanced'
|
|
140
|
+
}))
|
|
122
141
|
|
|
123
142
|
// Update features
|
|
124
143
|
setFeatures(prev => ({
|
|
125
144
|
...prev,
|
|
126
|
-
keyboardShortcuts, JSON.stringify(shortcuts)))
|
|
145
|
+
keyboardShortcuts: new Map(prev.keyboardShortcuts.set(elementId, JSON.stringify(shortcuts)))
|
|
127
146
|
}))
|
|
128
147
|
|
|
129
148
|
setIsEnhancing(false)
|
|
@@ -138,8 +157,9 @@ export const useAccessibilitySupport = (
|
|
|
138
157
|
|
|
139
158
|
// Screen reader support
|
|
140
159
|
const enhanceScreenReaderSupport = useCallback((
|
|
141
|
-
elementId,
|
|
142
|
-
screenReaderText
|
|
160
|
+
elementId: string,
|
|
161
|
+
screenReaderText: string
|
|
162
|
+
) => {
|
|
143
163
|
if (!enableScreenReaderSupport) return false
|
|
144
164
|
|
|
145
165
|
setIsEnhancing(true)
|
|
@@ -155,13 +175,14 @@ export const useAccessibilitySupport = (
|
|
|
155
175
|
setEnhancements(prev => [...prev, ...screenReaderEnhancements])
|
|
156
176
|
setState(prev => ({
|
|
157
177
|
...prev,
|
|
158
|
-
hasScreenReaderSupport,
|
|
159
|
-
accessibilityLevel=== 'basic' ? 'enhanced'
|
|
178
|
+
hasScreenReaderSupport: true,
|
|
179
|
+
accessibilityLevel: prev.accessibilityLevel === 'basic' ? 'enhanced' : 'advanced'
|
|
180
|
+
}))
|
|
160
181
|
|
|
161
182
|
// Update features
|
|
162
183
|
setFeatures(prev => ({
|
|
163
184
|
...prev,
|
|
164
|
-
screenReaderText, screenReaderText))
|
|
185
|
+
screenReaderText: new Map(prev.screenReaderText.set(elementId, screenReaderText))
|
|
165
186
|
}))
|
|
166
187
|
|
|
167
188
|
setIsEnhancing(false)
|
|
@@ -176,8 +197,9 @@ export const useAccessibilitySupport = (
|
|
|
176
197
|
|
|
177
198
|
// Focus management
|
|
178
199
|
const improveFocusManagement = useCallback((
|
|
179
|
-
elementId,
|
|
180
|
-
focusStrategy
|
|
200
|
+
elementId: string,
|
|
201
|
+
focusStrategy: 'trap' | 'cycle' | 'skip' | 'highlight'
|
|
202
|
+
) => {
|
|
181
203
|
if (!enableFocusManagement) return false
|
|
182
204
|
|
|
183
205
|
setIsEnhancing(true)
|
|
@@ -193,13 +215,14 @@ export const useAccessibilitySupport = (
|
|
|
193
215
|
setEnhancements(prev => [...prev, ...focusEnhancements])
|
|
194
216
|
setState(prev => ({
|
|
195
217
|
...prev,
|
|
196
|
-
hasFocusManagement,
|
|
197
|
-
accessibilityLevel=== 'basic' ? 'enhanced'
|
|
218
|
+
hasFocusManagement: true,
|
|
219
|
+
accessibilityLevel: prev.accessibilityLevel === 'basic' ? 'enhanced' : 'advanced'
|
|
220
|
+
}))
|
|
198
221
|
|
|
199
222
|
// Update features
|
|
200
223
|
setFeatures(prev => ({
|
|
201
224
|
...prev,
|
|
202
|
-
focusableElements))
|
|
225
|
+
focusableElements: new Set(prev.focusableElements.add(elementId))
|
|
203
226
|
}))
|
|
204
227
|
|
|
205
228
|
setIsEnhancing(false)
|
|
@@ -229,8 +252,9 @@ export const useAccessibilitySupport = (
|
|
|
229
252
|
setEnhancements(prev => [...prev, ...highContrastEnhancements])
|
|
230
253
|
setState(prev => ({
|
|
231
254
|
...prev,
|
|
232
|
-
isHighContrast,
|
|
233
|
-
accessibilityLevel=== 'basic' ? 'enhanced'
|
|
255
|
+
isHighContrast: true,
|
|
256
|
+
accessibilityLevel: prev.accessibilityLevel === 'basic' ? 'enhanced' : 'advanced'
|
|
257
|
+
}))
|
|
234
258
|
|
|
235
259
|
setIsEnhancing(false)
|
|
236
260
|
|
|
@@ -259,8 +283,9 @@ export const useAccessibilitySupport = (
|
|
|
259
283
|
setEnhancements(prev => [...prev, ...reducedMotionEnhancements])
|
|
260
284
|
setState(prev => ({
|
|
261
285
|
...prev,
|
|
262
|
-
isReducedMotion,
|
|
263
|
-
accessibilityLevel=== 'basic' ? 'enhanced'
|
|
286
|
+
isReducedMotion: true,
|
|
287
|
+
accessibilityLevel: prev.accessibilityLevel === 'basic' ? 'enhanced' : 'advanced'
|
|
288
|
+
}))
|
|
264
289
|
|
|
265
290
|
setIsEnhancing(false)
|
|
266
291
|
|
|
@@ -289,8 +314,9 @@ export const useAccessibilitySupport = (
|
|
|
289
314
|
setEnhancements(prev => [...prev, ...voiceControlEnhancements])
|
|
290
315
|
setState(prev => ({
|
|
291
316
|
...prev,
|
|
292
|
-
isVoiceControlEnabled,
|
|
293
|
-
accessibilityLevel=== 'basic' ? 'enhanced'
|
|
317
|
+
isVoiceControlEnabled: true,
|
|
318
|
+
accessibilityLevel: prev.accessibilityLevel === 'basic' ? 'enhanced' : 'advanced'
|
|
319
|
+
}))
|
|
294
320
|
|
|
295
321
|
setIsEnhancing(false)
|
|
296
322
|
|
|
@@ -305,10 +331,11 @@ export const useAccessibilitySupport = (
|
|
|
305
331
|
// Accessibility validation
|
|
306
332
|
const validateAccessibility = useCallback(() => {
|
|
307
333
|
const validation = {
|
|
308
|
-
isValid,
|
|
309
|
-
warnings] as string[],
|
|
310
|
-
errors] as string[],
|
|
311
|
-
score
|
|
334
|
+
isValid: true,
|
|
335
|
+
warnings: [] as string[],
|
|
336
|
+
errors: [] as string[],
|
|
337
|
+
score: 0
|
|
338
|
+
}
|
|
312
339
|
|
|
313
340
|
// Check ARIA support
|
|
314
341
|
if (!state.hasAriaLabels) {
|
|
@@ -346,16 +373,18 @@ export const useAccessibilitySupport = (
|
|
|
346
373
|
// Accessibility analysis
|
|
347
374
|
const analyzeAccessibility = useCallback(() => {
|
|
348
375
|
const analysis = {
|
|
349
|
-
level,
|
|
350
|
-
features
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
376
|
+
level: state.accessibilityLevel,
|
|
377
|
+
features: {
|
|
378
|
+
aria: state.hasAriaLabels,
|
|
379
|
+
keyboard: state.hasKeyboardNavigation,
|
|
380
|
+
screenReader: state.hasScreenReaderSupport,
|
|
381
|
+
focus: state.hasFocusManagement,
|
|
382
|
+
highContrast: state.isHighContrast,
|
|
383
|
+
reducedMotion: state.isReducedMotion,
|
|
384
|
+
voiceControl: state.isVoiceControlEnabled
|
|
385
|
+
},
|
|
386
|
+
coverage: 0,
|
|
387
|
+
recommendations: [] as string[]
|
|
359
388
|
}
|
|
360
389
|
|
|
361
390
|
// Calculate coverage
|
|
@@ -410,11 +439,12 @@ export const useAccessibilitySupport = (
|
|
|
410
439
|
setEnhancements(prev => [...prev, ...autoEnhancements])
|
|
411
440
|
setState(prev => ({
|
|
412
441
|
...prev,
|
|
413
|
-
hasAriaLabels,
|
|
414
|
-
hasKeyboardNavigation,
|
|
415
|
-
hasScreenReaderSupport,
|
|
416
|
-
hasFocusManagement,
|
|
417
|
-
accessibilityLevel
|
|
442
|
+
hasAriaLabels: true,
|
|
443
|
+
hasKeyboardNavigation: true,
|
|
444
|
+
hasScreenReaderSupport: true,
|
|
445
|
+
hasFocusManagement: true,
|
|
446
|
+
accessibilityLevel: 'enhanced'
|
|
447
|
+
}))
|
|
418
448
|
|
|
419
449
|
setIsEnhancing(false)
|
|
420
450
|
|
|
@@ -428,7 +458,7 @@ export const useAccessibilitySupport = (
|
|
|
428
458
|
useEffect(() => {
|
|
429
459
|
// Check for high contrast preference
|
|
430
460
|
if (enableHighContrastMode) {
|
|
431
|
-
const highContrastQuery = window.matchMedia('(prefers-contrast)')
|
|
461
|
+
const highContrastQuery = window.matchMedia('(prefers-contrast: high)')
|
|
432
462
|
if (highContrastQuery.matches) {
|
|
433
463
|
enableHighContrastFeature()
|
|
434
464
|
}
|
|
@@ -436,7 +466,7 @@ export const useAccessibilitySupport = (
|
|
|
436
466
|
|
|
437
467
|
// Check for reduced motion preference
|
|
438
468
|
if (enableReducedMotionMode) {
|
|
439
|
-
const reducedMotionQuery = window.matchMedia('(prefers-reduced-motion)')
|
|
469
|
+
const reducedMotionQuery = window.matchMedia('(prefers-reduced-motion: reduce)')
|
|
440
470
|
if (reducedMotionQuery.matches) {
|
|
441
471
|
enableReducedMotionFeature()
|
|
442
472
|
}
|
|
@@ -461,12 +491,12 @@ export const useAccessibilitySupport = (
|
|
|
461
491
|
|
|
462
492
|
// Enhancement functions
|
|
463
493
|
enhanceAriaSupport,
|
|
464
|
-
enableKeyboardNavigation,
|
|
494
|
+
enableKeyboardNavigation: enableKeyboardNavigationFeature,
|
|
465
495
|
enhanceScreenReaderSupport,
|
|
466
496
|
improveFocusManagement,
|
|
467
|
-
enableHighContrast,
|
|
468
|
-
enableReducedMotion,
|
|
469
|
-
enableVoiceControl,
|
|
497
|
+
enableHighContrast: enableHighContrastFeature,
|
|
498
|
+
enableReducedMotion: enableReducedMotionFeature,
|
|
499
|
+
enableVoiceControl: enableVoiceControlFeature,
|
|
470
500
|
autoEnhanceAccessibility,
|
|
471
501
|
|
|
472
502
|
// Analysis and validation
|
|
@@ -474,14 +504,14 @@ export const useAccessibilitySupport = (
|
|
|
474
504
|
analyzeAccessibility,
|
|
475
505
|
|
|
476
506
|
// Utility functions
|
|
477
|
-
isAccessibilityEnhanced) => state.accessibilityLevel !== 'basic',
|
|
478
|
-
getAccessibilityLevel) => state.accessibilityLevel,
|
|
479
|
-
getAccessibilityScore) => {
|
|
507
|
+
isAccessibilityEnhanced: () => state.accessibilityLevel !== 'basic',
|
|
508
|
+
getAccessibilityLevel: () => state.accessibilityLevel,
|
|
509
|
+
getAccessibilityScore: () => {
|
|
480
510
|
const validation = validateAccessibility()
|
|
481
511
|
return validation.score
|
|
482
512
|
},
|
|
483
|
-
clearEnhancements) => setEnhancements([]),
|
|
484
|
-
clearWarnings) => setAccessibilityWarnings([])
|
|
513
|
+
clearEnhancements: () => setEnhancements([]),
|
|
514
|
+
clearWarnings: () => setAccessibilityWarnings([])
|
|
485
515
|
}
|
|
486
516
|
}
|
|
487
517
|
|