|
1 | | -/* Focus Management System - WCAG 2.4.7 & 1.4.11 Compliant */ |
2 | | - |
3 | | -/* |
4 | | - * Focus indicators with proper contrast ratios (minimum 3:1) |
5 | | - * Uses focus-visible for better UX (keyboard navigation only) |
6 | | - */ |
7 | | - |
8 | 1 | :root { |
9 | | - /* Focus indicator colors with high contrast */ |
10 | | - --focus-outline-color-light: #0066cc; /* Blue with high contrast */ |
11 | | - --focus-outline-color-dark: #4da6ff; /* Lighter blue for dark mode */ |
12 | | - --focus-outline-width: 2px; |
13 | | - --focus-outline-offset: 2px; |
14 | | - --focus-outline-style: solid; |
15 | | - |
16 | | - /* Alternative focus colors for different contexts */ |
17 | | - --focus-outline-warning: #ff6b00; /* Orange for warnings/errors */ |
18 | | - --focus-outline-success: #00a651; /* Green for success states */ |
19 | | - |
20 | | - /* Box shadow focus for cases where outline doesn't work well */ |
21 | | - --focus-shadow-light: 0 0 0 2px #ffffff, 0 0 0 4px #0066cc; |
22 | | - --focus-shadow-dark: 0 0 0 2px #0a0a0a, 0 0 0 4px #4da6ff; |
| 2 | + --focus-outline-color-light: #0066cc; |
| 3 | + --focus-outline-color-dark: #4da6ff; |
23 | 4 | } |
24 | 5 |
|
25 | 6 | [data-theme='dark'] { |
26 | 7 | --focus-outline-color-light: var(--focus-outline-color-dark); |
27 | 8 | --focus-shadow-light: var(--focus-shadow-dark); |
28 | 9 | } |
29 | | - |
30 | | -/* Remove default focus styles only when we provide alternatives */ |
31 | | -*:focus { |
32 | | - outline: auto; |
33 | | -} |
34 | | - |
35 | | -/* Apply focus-visible for keyboard navigation */ |
36 | | -*:focus-visible { |
37 | | - outline: var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color-light); |
38 | | - outline-offset: var(--focus-outline-offset); |
39 | | -} |
40 | | - |
41 | | -/* Enhanced focus for interactive elements */ |
42 | | -a:focus-visible, |
43 | | -button:focus-visible, |
44 | | -[role='button']:focus-visible, |
45 | | -[role='link']:focus-visible, |
46 | | -[tabindex]:focus-visible { |
47 | | - outline: var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color-light); |
48 | | - outline-offset: var(--focus-outline-offset); |
49 | | -} |
50 | | - |
51 | | -/* Form controls need special handling */ |
52 | | -input:focus-visible, |
53 | | -textarea:focus-visible, |
54 | | -select:focus-visible { |
55 | | - outline: var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color-light); |
56 | | - outline-offset: 1px; /* Tighter offset for form controls */ |
57 | | -} |
58 | | - |
59 | | -/* Checkbox and radio buttons */ |
60 | | -input[type='checkbox']:focus-visible, |
61 | | -input[type='radio']:focus-visible { |
62 | | - outline: var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color-light); |
63 | | - outline-offset: 2px; |
64 | | -} |
65 | | - |
66 | | -/* For elements where outline might be cut off, use box-shadow */ |
67 | | -.focus-shadow:focus-visible { |
68 | | - outline: none; |
69 | | - box-shadow: var(--focus-shadow-light); |
70 | | -} |
71 | | - |
72 | | -/* High contrast mode support */ |
73 | | -@media (prefers-contrast: high) { |
74 | | - *:focus-visible { |
75 | | - outline-width: 3px; |
76 | | - outline-color: highlight; |
77 | | - } |
78 | | -} |
79 | | - |
80 | | -/* Focus for elements that might have complex backgrounds */ |
81 | | -.focus-high-contrast:focus-visible { |
82 | | - outline: 3px solid var(--focus-outline-color-light); |
83 | | - outline-offset: 2px; |
84 | | - background-color: rgba(255, 255, 255, 0.9); |
85 | | - |
86 | | - [data-theme='dark'] & { |
87 | | - background-color: rgba(0, 0, 0, 0.9); |
88 | | - } |
89 | | -} |
90 | | - |
91 | | -/* Skip link focus (for screen reader users) */ |
92 | | -.skip-link:focus-visible { |
93 | | - position: absolute; |
94 | | - top: 10px; |
95 | | - left: 10px; |
96 | | - z-index: 9999; |
97 | | - padding: 8px 16px; |
98 | | - background: var(--focus-outline-color-light); |
99 | | - color: white; |
100 | | - text-decoration: none; |
101 | | - border-radius: 4px; |
102 | | - outline: 2px solid white; |
103 | | - outline-offset: 2px; |
104 | | -} |
105 | | - |
106 | | -/* Ensure focus is visible even when using custom components */ |
107 | | -.custom-focus:focus-visible { |
108 | | - position: relative; |
109 | | -} |
110 | | - |
111 | | -.custom-focus:focus-visible::after { |
112 | | - content: ''; |
113 | | - position: absolute; |
114 | | - top: -2px; |
115 | | - right: -2px; |
116 | | - bottom: -2px; |
117 | | - left: -2px; |
118 | | - border: var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color-light); |
119 | | - border-radius: inherit; |
120 | | - pointer-events: none; |
121 | | -} |
122 | | - |
123 | | -/* Focus indicators that work well with rounded corners */ |
124 | | -.focus-rounded:focus-visible { |
125 | | - outline: var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color-light); |
126 | | - outline-offset: var(--focus-outline-offset); |
127 | | - border-radius: inherit; |
128 | | -} |
129 | | - |
130 | | -/* Error state focus */ |
131 | | -.focus-error:focus-visible { |
132 | | - outline-color: var(--focus-outline-warning); |
133 | | -} |
134 | | - |
135 | | -/* Success state focus */ |
136 | | -.focus-success:focus-visible { |
137 | | - outline-color: var(--focus-outline-success); |
138 | | -} |
139 | | - |
140 | | -/* Reduced motion support */ |
141 | | -@media (prefers-reduced-motion: no-preference) { |
142 | | - *:focus-visible { |
143 | | - transition: outline-color 0.15s ease-in-out; |
144 | | - } |
145 | | -} |
0 commit comments