mtrl 0.2.5 → 0.2.6
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/package.json +1 -1
- package/src/components/badge/_styles.scss +9 -9
- package/src/components/button/_styles.scss +0 -56
- package/src/components/button/button.ts +0 -2
- package/src/components/button/constants.ts +0 -6
- package/src/components/button/index.ts +2 -2
- package/src/components/button/types.ts +1 -7
- package/src/components/card/_styles.scss +67 -25
- package/src/components/card/api.ts +54 -3
- package/src/components/card/card.ts +33 -2
- package/src/components/card/config.ts +143 -21
- package/src/components/card/constants.ts +20 -19
- package/src/components/card/content.ts +299 -2
- package/src/components/card/features.ts +155 -4
- package/src/components/card/index.ts +31 -9
- package/src/components/card/types.ts +138 -15
- package/src/components/chip/chip.ts +1 -9
- package/src/components/chip/constants.ts +0 -10
- package/src/components/chip/index.ts +1 -1
- package/src/components/chip/types.ts +1 -4
- package/src/components/progress/_styles.scss +0 -65
- package/src/components/progress/config.ts +1 -2
- package/src/components/progress/constants.ts +0 -14
- package/src/components/progress/index.ts +1 -1
- package/src/components/progress/progress.ts +1 -4
- package/src/components/progress/types.ts +1 -4
- package/src/components/radios/_styles.scss +0 -45
- package/src/components/radios/api.ts +85 -60
- package/src/components/radios/config.ts +1 -2
- package/src/components/radios/constants.ts +0 -9
- package/src/components/radios/index.ts +1 -1
- package/src/components/radios/radio.ts +34 -11
- package/src/components/radios/radios.ts +2 -1
- package/src/components/radios/types.ts +1 -7
- package/src/components/slider/_styles.scss +149 -155
- package/src/components/slider/accessibility.md +59 -0
- package/src/components/slider/config.ts +4 -6
- package/src/components/slider/features/disabled.ts +41 -16
- package/src/components/slider/features/interactions.ts +153 -18
- package/src/components/slider/features/keyboard.ts +127 -6
- package/src/components/slider/features/structure.ts +32 -5
- package/src/components/slider/features/ui.ts +18 -8
- package/src/components/tabs/_styles.scss +285 -155
- package/src/components/tabs/api.ts +178 -400
- package/src/components/tabs/config.ts +46 -52
- package/src/components/tabs/constants.ts +85 -8
- package/src/components/tabs/features.ts +401 -0
- package/src/components/tabs/index.ts +60 -3
- package/src/components/tabs/indicator.ts +225 -0
- package/src/components/tabs/responsive.ts +144 -0
- package/src/components/tabs/scroll-indicators.ts +149 -0
- package/src/components/tabs/state.ts +186 -0
- package/src/components/tabs/tab-api.ts +258 -0
- package/src/components/tabs/tab.ts +255 -0
- package/src/components/tabs/tabs.ts +50 -31
- package/src/components/tabs/types.ts +324 -128
- package/src/components/tabs/utils.ts +107 -0
- package/src/components/textfield/_styles.scss +0 -98
- package/src/components/textfield/config.ts +2 -3
- package/src/components/textfield/constants.ts +0 -14
- package/src/components/textfield/index.ts +2 -2
- package/src/components/textfield/textfield.ts +0 -2
- package/src/components/textfield/types.ts +1 -4
- package/src/core/compose/component.ts +1 -1
- package/src/core/compose/features/badge.ts +79 -0
- package/src/core/compose/features/index.ts +3 -1
- package/src/styles/abstract/_theme.scss +106 -2
- package/src/components/card/actions.ts +0 -48
- package/src/components/card/header.ts +0 -88
- package/src/components/card/media.ts +0 -52
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
@use '../../styles/abstract/mixins' as m;
|
|
6
6
|
@use '../../styles/abstract/theme' as t;
|
|
7
7
|
|
|
8
|
+
// $transform: transform 0.2s ease, width 0.2s ease, height 0.2s ease;
|
|
9
|
+
$transform: none;
|
|
10
|
+
|
|
8
11
|
$component: '#{base.$prefix}-slider';
|
|
9
12
|
|
|
10
13
|
.#{$component} {
|
|
@@ -17,6 +20,11 @@ $component: '#{base.$prefix}-slider';
|
|
|
17
20
|
user-select: none;
|
|
18
21
|
touch-action: none;
|
|
19
22
|
|
|
23
|
+
// Container should not have a focus outline
|
|
24
|
+
&:focus {
|
|
25
|
+
outline: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
20
28
|
&-track {
|
|
21
29
|
position: relative;
|
|
22
30
|
width: 100%;
|
|
@@ -33,8 +41,127 @@ $component: '#{base.$prefix}-slider';
|
|
|
33
41
|
cursor: not-allowed;
|
|
34
42
|
}
|
|
35
43
|
}
|
|
36
|
-
|
|
37
|
-
//
|
|
44
|
+
|
|
45
|
+
// Thumb - updated with T-shape and proper focus styles
|
|
46
|
+
&-thumb {
|
|
47
|
+
position: absolute;
|
|
48
|
+
top: 50%;
|
|
49
|
+
transform: translate(-50%, -50%);
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
z-index: 4;
|
|
52
|
+
padding: 4px 0;
|
|
53
|
+
transition: $transform;
|
|
54
|
+
width: 16px;
|
|
55
|
+
height: 50px;
|
|
56
|
+
border-radius: 16px;
|
|
57
|
+
background-color: rgba(red, .0);
|
|
58
|
+
|
|
59
|
+
// Focus styles for keyboard navigation
|
|
60
|
+
&:focus {
|
|
61
|
+
outline: 2px solid t.color('outline');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Class added when focused via keyboard
|
|
65
|
+
&--focused {
|
|
66
|
+
// Additional styling when focused
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Create a T-shaped thumb using pseudo-elements
|
|
70
|
+
&::before {
|
|
71
|
+
pointer-events: none;
|
|
72
|
+
content: '';
|
|
73
|
+
position: absolute;
|
|
74
|
+
width: 4px;
|
|
75
|
+
height: 40px;
|
|
76
|
+
background-color: t.color('primary');
|
|
77
|
+
border-radius: 2px;
|
|
78
|
+
left: 50%;
|
|
79
|
+
top: 50%;
|
|
80
|
+
transform: translate(-50%, -50%);
|
|
81
|
+
transition: background-color 0.15s ease, width 0.15s ease;
|
|
82
|
+
|
|
83
|
+
.#{$component}--secondary & {
|
|
84
|
+
background-color: t.color('secondary');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.#{$component}--tertiary & {
|
|
88
|
+
background-color: t.color('tertiary');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.#{$component}--error & {
|
|
92
|
+
background-color: t.color('error');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.#{$component}--disabled & {
|
|
96
|
+
background-color: t.color('on-surface');
|
|
97
|
+
opacity: 0.38;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Enable pointer events on the pseudo-element
|
|
102
|
+
&::before {
|
|
103
|
+
pointer-events: auto;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Make thumb line slimmer during dragging (feedback)
|
|
107
|
+
.#{$component}--dragging & {
|
|
108
|
+
&::before {
|
|
109
|
+
width: 3px;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Hover state
|
|
114
|
+
&:hover::before {
|
|
115
|
+
background-color: t.color('primary');
|
|
116
|
+
|
|
117
|
+
.#{$component}--secondary & {
|
|
118
|
+
background-color: t.color('secondary');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.#{$component}--tertiary & {
|
|
122
|
+
background-color: t.color('tertiary');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.#{$component}--error & {
|
|
126
|
+
background-color: t.color('error');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.#{$component}--disabled & {
|
|
130
|
+
background-color: t.color('on-surface');
|
|
131
|
+
opacity: 0.38;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Active state
|
|
136
|
+
&:active::before {
|
|
137
|
+
background-color: t.color('primary');
|
|
138
|
+
width: 3px; // Shrink width when active for visual feedback
|
|
139
|
+
|
|
140
|
+
.#{$component}--secondary & {
|
|
141
|
+
background-color: t.color('secondary');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.#{$component}--tertiary & {
|
|
145
|
+
background-color: t.color('tertiary');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.#{$component}--error & {
|
|
149
|
+
background-color: t.color('error');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Disabled state
|
|
154
|
+
.#{$component}--disabled & {
|
|
155
|
+
cursor: not-allowed;
|
|
156
|
+
|
|
157
|
+
&::before {
|
|
158
|
+
opacity: 0.38;
|
|
159
|
+
background-color: t.color('on-surface');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Start track (for range slider)
|
|
38
165
|
&-start-track {
|
|
39
166
|
position: absolute;
|
|
40
167
|
top: 0;
|
|
@@ -42,7 +169,7 @@ $component: '#{base.$prefix}-slider';
|
|
|
42
169
|
height: 100%;
|
|
43
170
|
background-color: t.color('primary');
|
|
44
171
|
transform-origin: left center;
|
|
45
|
-
|
|
172
|
+
transition: $transform;
|
|
46
173
|
border-radius: 2px;
|
|
47
174
|
opacity: 0.24;
|
|
48
175
|
z-index: 1;
|
|
@@ -71,7 +198,7 @@ $component: '#{base.$prefix}-slider';
|
|
|
71
198
|
height: 100%;
|
|
72
199
|
background-color: t.color('primary');
|
|
73
200
|
transform-origin: left center;
|
|
74
|
-
|
|
201
|
+
transition: $transform;
|
|
75
202
|
border-radius: 2px;
|
|
76
203
|
z-index: 1;
|
|
77
204
|
|
|
@@ -88,7 +215,7 @@ $component: '#{base.$prefix}-slider';
|
|
|
88
215
|
}
|
|
89
216
|
}
|
|
90
217
|
|
|
91
|
-
// Remaining track (unfilled part)
|
|
218
|
+
// Remaining track (unfilled part)
|
|
92
219
|
&-remaining-track {
|
|
93
220
|
opacity: .24;
|
|
94
221
|
position: absolute;
|
|
@@ -96,7 +223,7 @@ $component: '#{base.$prefix}-slider';
|
|
|
96
223
|
height: 100%;
|
|
97
224
|
background-color: t.color('primary');
|
|
98
225
|
transform-origin: left center;
|
|
99
|
-
|
|
226
|
+
transition: $transform;
|
|
100
227
|
border-radius: 2px;
|
|
101
228
|
width: 100%;
|
|
102
229
|
z-index: 0;
|
|
@@ -118,7 +245,7 @@ $component: '#{base.$prefix}-slider';
|
|
|
118
245
|
}
|
|
119
246
|
}
|
|
120
247
|
|
|
121
|
-
// Dot elements for track ends (
|
|
248
|
+
// Dot elements for track ends (visual anchors for accessibility)
|
|
122
249
|
&-dot {
|
|
123
250
|
pointer-events: none;
|
|
124
251
|
position: absolute;
|
|
@@ -132,7 +259,6 @@ $component: '#{base.$prefix}-slider';
|
|
|
132
259
|
// Start dot
|
|
133
260
|
&--start {
|
|
134
261
|
left: 6px;
|
|
135
|
-
// Color variants
|
|
136
262
|
background-color: t.color('on-primary');
|
|
137
263
|
|
|
138
264
|
.#{$component}--secondary & {
|
|
@@ -147,7 +273,6 @@ $component: '#{base.$prefix}-slider';
|
|
|
147
273
|
// End dot
|
|
148
274
|
&--end {
|
|
149
275
|
right: 6px;
|
|
150
|
-
// Color variants
|
|
151
276
|
background-color: t.color('primary');
|
|
152
277
|
|
|
153
278
|
.#{$component}--secondary & {
|
|
@@ -162,136 +287,10 @@ $component: '#{base.$prefix}-slider';
|
|
|
162
287
|
.#{$component}--disabled & {
|
|
163
288
|
opacity: 0.38;
|
|
164
289
|
}
|
|
165
|
-
|
|
166
290
|
}
|
|
167
291
|
|
|
168
|
-
// Thumb - updated to MD3 style with T-shape
|
|
169
|
-
&-thumb {
|
|
170
|
-
position: absolute;
|
|
171
|
-
top: 50%;
|
|
172
|
-
transform: translate(-50%, -50%);
|
|
173
|
-
cursor: pointer;
|
|
174
|
-
z-index: 4;
|
|
175
|
-
// transition: left 0.1s ease, bottom 0.1s ease;
|
|
176
|
-
width: 16px;
|
|
177
|
-
height: 100%;
|
|
178
|
-
|
|
179
|
-
// Create a T-shaped thumb using pseudo-elements
|
|
180
|
-
&::before {
|
|
181
|
-
pointer-events: none;
|
|
182
|
-
content: '';
|
|
183
|
-
position: absolute;
|
|
184
|
-
width: 4px;
|
|
185
|
-
height: 40px;
|
|
186
|
-
background-color: t.color('primary');
|
|
187
|
-
border-radius: 2px;
|
|
188
|
-
left: 50%;
|
|
189
|
-
top: 50%;
|
|
190
|
-
transform: translate(-50%, -50%);
|
|
191
|
-
transition: background-color 0.15s ease, width 0.15s ease;
|
|
192
|
-
|
|
193
|
-
.#{$component}--secondary & {
|
|
194
|
-
background-color: t.color('secondary');
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
.#{$component}--tertiary & {
|
|
198
|
-
background-color: t.color('tertiary');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
.#{$component}--error & {
|
|
202
|
-
background-color: t.color('error');
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
.#{$component}--disabled & {
|
|
206
|
-
background-color: t.color('on-surface');
|
|
207
|
-
opacity: 0.38;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Enable pointer events on the pseudo-elements
|
|
212
|
-
&::before, &::after {
|
|
213
|
-
pointer-events: auto;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Make thumb line slimmer during dragging
|
|
217
|
-
.#{$component}--dragging & {
|
|
218
|
-
&::before {
|
|
219
|
-
width: 3px;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Hover state
|
|
224
|
-
&:hover::before, &:hover::after {
|
|
225
|
-
background-color: t.color('primary');
|
|
226
|
-
|
|
227
|
-
.#{$component}--secondary & {
|
|
228
|
-
background-color: t.color('secondary');
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
.#{$component}--tertiary & {
|
|
232
|
-
background-color: t.color('tertiary');
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
.#{$component}--error & {
|
|
236
|
-
background-color: t.color('error');
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
.#{$component}--disabled & {
|
|
240
|
-
background-color: t.color('on-surface');
|
|
241
|
-
opacity: 0.38;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Focus state
|
|
246
|
-
&:focus {
|
|
247
|
-
outline: none;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
&:focus::before, &:focus::after {
|
|
251
|
-
background-color: t.color('primary');
|
|
252
|
-
|
|
253
|
-
.#{$component}--secondary & {
|
|
254
|
-
background-color: t.color('secondary');
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
.#{$component}--tertiary & {
|
|
258
|
-
background-color: t.color('tertiary');
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
.#{$component}--error & {
|
|
262
|
-
background-color: t.color('error');
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Active state
|
|
267
|
-
&:active::before, &:active::after {
|
|
268
|
-
background-color: t.color('primary');
|
|
269
|
-
|
|
270
|
-
.#{$component}--secondary & {
|
|
271
|
-
background-color: t.color('secondary');
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
.#{$component}--tertiary & {
|
|
275
|
-
background-color: t.color('tertiary');
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
.#{$component}--error & {
|
|
279
|
-
background-color: t.color('error');
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// Disabled state
|
|
284
|
-
.#{$component}--disabled & {
|
|
285
|
-
cursor: not-allowed;
|
|
286
|
-
|
|
287
|
-
&::before, &::after {
|
|
288
|
-
opacity: 0.38;
|
|
289
|
-
background-color: t.color('on-surface');
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
292
|
|
|
294
|
-
// Container for ticks
|
|
293
|
+
// Container for ticks
|
|
295
294
|
&-ticks-container {
|
|
296
295
|
position: absolute;
|
|
297
296
|
width: 100%;
|
|
@@ -320,7 +319,6 @@ $component: '#{base.$prefix}-slider';
|
|
|
320
319
|
|
|
321
320
|
// Active tick (filled)
|
|
322
321
|
&--active {
|
|
323
|
-
// background-color: white;
|
|
324
322
|
background-color: t.color('on-primary');
|
|
325
323
|
|
|
326
324
|
.#{$component}--secondary & {
|
|
@@ -351,7 +349,7 @@ $component: '#{base.$prefix}-slider';
|
|
|
351
349
|
}
|
|
352
350
|
}
|
|
353
351
|
|
|
354
|
-
// Range slider styles
|
|
352
|
+
// Range slider styles
|
|
355
353
|
&--range {
|
|
356
354
|
.#{$component}-thumb {
|
|
357
355
|
&:nth-of-type(1) {
|
|
@@ -365,24 +363,24 @@ $component: '#{base.$prefix}-slider';
|
|
|
365
363
|
}
|
|
366
364
|
}
|
|
367
365
|
|
|
368
|
-
// Value bubble
|
|
366
|
+
// Value bubble - shows current value during interaction
|
|
369
367
|
&-value {
|
|
370
368
|
position: absolute;
|
|
371
369
|
top: -40px;
|
|
372
370
|
left: 0;
|
|
373
371
|
background-color: t.color('on-surface');
|
|
374
372
|
color: t.color('surface-container-highest');
|
|
375
|
-
padding: 6px
|
|
373
|
+
padding: 6px 12px;
|
|
376
374
|
border-radius: 21px;
|
|
377
|
-
font-size:
|
|
378
|
-
font-weight:
|
|
375
|
+
font-size: 14px;
|
|
376
|
+
font-weight: 600;
|
|
379
377
|
transform: translateX(-50%);
|
|
380
378
|
visibility: hidden;
|
|
381
379
|
opacity: 0;
|
|
382
380
|
transition: opacity 0.2s ease, visibility 0s linear 0.2s;
|
|
383
381
|
pointer-events: none;
|
|
384
382
|
|
|
385
|
-
// Show value when
|
|
383
|
+
// Show value when interacting
|
|
386
384
|
&--visible {
|
|
387
385
|
visibility: visible;
|
|
388
386
|
opacity: 1;
|
|
@@ -406,11 +404,6 @@ $component: '#{base.$prefix}-slider';
|
|
|
406
404
|
&::before {
|
|
407
405
|
height: 34px;
|
|
408
406
|
}
|
|
409
|
-
|
|
410
|
-
&::after {
|
|
411
|
-
width: 14px;
|
|
412
|
-
height: 14px;
|
|
413
|
-
}
|
|
414
407
|
}
|
|
415
408
|
}
|
|
416
409
|
|
|
@@ -421,16 +414,17 @@ $component: '#{base.$prefix}-slider';
|
|
|
421
414
|
&::before {
|
|
422
415
|
height: 48px;
|
|
423
416
|
}
|
|
424
|
-
|
|
425
|
-
&::after {
|
|
426
|
-
width: 18px;
|
|
427
|
-
height: 18px;
|
|
428
|
-
}
|
|
429
417
|
}
|
|
430
418
|
}
|
|
431
419
|
|
|
432
|
-
// For dragging state
|
|
420
|
+
// For dragging state - visual feedback
|
|
433
421
|
&--dragging {
|
|
434
|
-
//
|
|
422
|
+
// No transitions during dragging for responsive feel
|
|
423
|
+
.#{$component}-start-track,
|
|
424
|
+
.#{$component}-active-track,
|
|
425
|
+
.#{$component}-remaining-track,
|
|
426
|
+
.#{$component}-thumb {
|
|
427
|
+
transition: none;
|
|
428
|
+
}
|
|
435
429
|
}
|
|
436
430
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Slider Accessibility Enhancements
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Based on the provided accessibility requirements, the slider component has been enhanced to provide better keyboard navigation, visual feedback, and overall accessibility. The changes focus on ensuring that the slider meets Material Design accessibility standards and provides appropriate feedback based on input type.
|
|
6
|
+
|
|
7
|
+
## Key Enhancements
|
|
8
|
+
|
|
9
|
+
### Focus and Keyboard Navigation
|
|
10
|
+
|
|
11
|
+
- **Direct Thumb Focus**: The initial focus now lands directly on the thumb (not the container)
|
|
12
|
+
- **Visual Feedback**: Added a clear outline on focus to provide visual cues for keyboard users
|
|
13
|
+
- **Arrow Key Navigation**:
|
|
14
|
+
- Left/Right arrows change the value by one step
|
|
15
|
+
- Up/Down arrows also change the value (for consistency with other controls)
|
|
16
|
+
- Home/End keys jump to minimum/maximum values
|
|
17
|
+
- Page Up/Down for larger step increments
|
|
18
|
+
- Shift + arrows for faster navigation (10x step size)
|
|
19
|
+
|
|
20
|
+
### Visual Feedback During Interaction
|
|
21
|
+
|
|
22
|
+
- **Thumb Shrinking**: The thumb width shrinks slightly during interaction to provide feedback
|
|
23
|
+
- **Value Display**:
|
|
24
|
+
- Value appears during interaction (touch, drag, mouse click, keyboard navigation)
|
|
25
|
+
- Value remains visible briefly after interaction ends (1.5 seconds)
|
|
26
|
+
- Value position updates to follow the thumb
|
|
27
|
+
|
|
28
|
+
### Visual Anchors for Contrast
|
|
29
|
+
|
|
30
|
+
- **Track End Indicators**: Added dot elements at both ends of the track
|
|
31
|
+
- **Color Contrast**: Ensured sufficient contrast for all elements
|
|
32
|
+
- **Disabled State**: Properly indicated visually and via ARIA attributes
|
|
33
|
+
|
|
34
|
+
## Implementation Details
|
|
35
|
+
|
|
36
|
+
1. **Keyboard Handling**:
|
|
37
|
+
- Enhanced keyboard navigation with proper step calculations
|
|
38
|
+
- Added support for modifier keys (Shift)
|
|
39
|
+
- Set appropriate ARIA attributes for screen readers
|
|
40
|
+
|
|
41
|
+
2. **Interaction Feedback**:
|
|
42
|
+
- Modified CSS to shrink thumb width during active states
|
|
43
|
+
- Enhanced value bubble display timing
|
|
44
|
+
- Improved touch and mouse event handling
|
|
45
|
+
|
|
46
|
+
3. **Focus Management**:
|
|
47
|
+
- Set clear focus styles that work cross-browser
|
|
48
|
+
- Applied focus directly to interactive thumb elements
|
|
49
|
+
- Ensured focus outline is visible against various backgrounds
|
|
50
|
+
|
|
51
|
+
## Keyboard Navigation Map
|
|
52
|
+
|
|
53
|
+
| Keys | Actions |
|
|
54
|
+
|------|---------|
|
|
55
|
+
| Tab | Moves focus to the slider handle |
|
|
56
|
+
| Arrows | Increase and decrease the value by one step |
|
|
57
|
+
| Shift + Arrows | Increase and decrease by 10x step size |
|
|
58
|
+
| Home / End | Set to minimum or maximum value |
|
|
59
|
+
| Page Up / Down | Increase/decrease by larger increments |
|
|
@@ -41,13 +41,11 @@ export const getElementConfig = (config: SliderConfig) => {
|
|
|
41
41
|
return createElementConfig(config, {
|
|
42
42
|
tag: 'div',
|
|
43
43
|
attrs: {
|
|
44
|
-
|
|
45
|
-
'tabindex':
|
|
44
|
+
// Accessibility improvement: Container is not focusable; only thumbs are
|
|
45
|
+
'tabindex': '-1',
|
|
46
46
|
'aria-disabled': config.disabled === true ? true : false,
|
|
47
|
-
|
|
48
|
-
'
|
|
49
|
-
'aria-valuenow': config.value,
|
|
50
|
-
'aria-orientation': 'horizontal'
|
|
47
|
+
// ARIA attributes will be set directly on thumbs instead
|
|
48
|
+
'role': 'none',
|
|
51
49
|
},
|
|
52
50
|
className: config.class
|
|
53
51
|
});
|
|
@@ -10,29 +10,54 @@ export const withDisabled = (config: SliderConfig) => component => {
|
|
|
10
10
|
// Initial disabled state
|
|
11
11
|
const isDisabled = config.disabled === true;
|
|
12
12
|
|
|
13
|
+
// Apply initial disabled state if needed
|
|
14
|
+
if (isDisabled && component.structure) {
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
disableComponent();
|
|
17
|
+
}, 0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function disableComponent() {
|
|
21
|
+
component.element.classList.add(`${component.getClass('slider')}--disabled`);
|
|
22
|
+
component.element.setAttribute('aria-disabled', 'true');
|
|
23
|
+
|
|
24
|
+
// Ensure thumbs cannot receive focus when disabled
|
|
25
|
+
if (component.structure.thumb) {
|
|
26
|
+
component.structure.thumb.tabIndex = -1;
|
|
27
|
+
component.structure.thumb.setAttribute('aria-disabled', 'true');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (config.range && component.structure.secondThumb) {
|
|
31
|
+
component.structure.secondThumb.tabIndex = -1;
|
|
32
|
+
component.structure.secondThumb.setAttribute('aria-disabled', 'true');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function enableComponent() {
|
|
37
|
+
component.element.classList.remove(`${component.getClass('slider')}--disabled`);
|
|
38
|
+
component.element.setAttribute('aria-disabled', 'false');
|
|
39
|
+
|
|
40
|
+
// Re-enable focus on thumbs
|
|
41
|
+
if (component.structure.thumb) {
|
|
42
|
+
component.structure.thumb.tabIndex = 0;
|
|
43
|
+
component.structure.thumb.setAttribute('aria-disabled', 'false');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (config.range && component.structure.secondThumb) {
|
|
47
|
+
component.structure.secondThumb.tabIndex = 0;
|
|
48
|
+
component.structure.secondThumb.setAttribute('aria-disabled', 'false');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
13
52
|
return {
|
|
14
53
|
...component,
|
|
15
54
|
disabled: {
|
|
16
55
|
enable() {
|
|
17
|
-
|
|
18
|
-
component.element.setAttribute('aria-disabled', 'false');
|
|
19
|
-
component.element.tabIndex = 0;
|
|
20
|
-
component.structure.thumb.tabIndex = 0;
|
|
21
|
-
|
|
22
|
-
if (config.range && component.structure.secondThumb) {
|
|
23
|
-
component.structure.secondThumb.tabIndex = 0;
|
|
24
|
-
}
|
|
56
|
+
enableComponent();
|
|
25
57
|
},
|
|
26
58
|
|
|
27
59
|
disable() {
|
|
28
|
-
|
|
29
|
-
component.element.setAttribute('aria-disabled', 'true');
|
|
30
|
-
component.element.tabIndex = -1;
|
|
31
|
-
component.structure.thumb.tabIndex = -1;
|
|
32
|
-
|
|
33
|
-
if (config.range && component.structure.secondThumb) {
|
|
34
|
-
component.structure.secondThumb.tabIndex = -1;
|
|
35
|
-
}
|
|
60
|
+
disableComponent();
|
|
36
61
|
},
|
|
37
62
|
|
|
38
63
|
isDisabled() {
|