@instructure/ui-select 10.19.2-snapshot-9 → 10.19.2-snapshot-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 +2 -1
- package/package.json +23 -23
- package/src/Select/README.md +199 -112
package/CHANGELOG.md
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [10.19.2-snapshot-
|
|
6
|
+
## [10.19.2-snapshot-11](https://github.com/instructure/instructure-ui/compare/v10.19.1...v10.19.2-snapshot-11) (2025-06-13)
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
### Bug Fixes
|
|
10
10
|
|
|
11
11
|
* **many:** update dependencies, browsersdb and moment timezone database ([3813636](https://github.com/instructure/instructure-ui/commit/3813636458c901ad4bc74a4d5ae015cb55defcb2))
|
|
12
|
+
* **ui-time-select,ui-simple-select,ui-select:** add missing keyboard interactions and fix duplicate SR announcements ([0f7ffa5](https://github.com/instructure/instructure-ui/commit/0f7ffa5b263b0b287ca1c2387e0b902189706cb2))
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/ui-select",
|
|
3
|
-
"version": "10.19.2-snapshot-
|
|
3
|
+
"version": "10.19.2-snapshot-11",
|
|
4
4
|
"description": "A component for select and autocomplete behavior.",
|
|
5
5
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
6
6
|
"module": "./es/index.js",
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@instructure/ui-axe-check": "10.19.2-snapshot-
|
|
27
|
-
"@instructure/ui-babel-preset": "10.19.2-snapshot-
|
|
28
|
-
"@instructure/ui-color-utils": "10.19.2-snapshot-
|
|
29
|
-
"@instructure/ui-scripts": "10.19.2-snapshot-
|
|
30
|
-
"@instructure/ui-test-utils": "10.19.2-snapshot-
|
|
31
|
-
"@instructure/ui-themes": "10.19.2-snapshot-
|
|
26
|
+
"@instructure/ui-axe-check": "10.19.2-snapshot-11",
|
|
27
|
+
"@instructure/ui-babel-preset": "10.19.2-snapshot-11",
|
|
28
|
+
"@instructure/ui-color-utils": "10.19.2-snapshot-11",
|
|
29
|
+
"@instructure/ui-scripts": "10.19.2-snapshot-11",
|
|
30
|
+
"@instructure/ui-test-utils": "10.19.2-snapshot-11",
|
|
31
|
+
"@instructure/ui-themes": "10.19.2-snapshot-11",
|
|
32
32
|
"@testing-library/jest-dom": "^6.6.3",
|
|
33
33
|
"@testing-library/react": "^16.0.1",
|
|
34
34
|
"@testing-library/user-event": "^14.6.1",
|
|
@@ -36,22 +36,22 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@babel/runtime": "^7.27.6",
|
|
39
|
-
"@instructure/emotion": "10.19.2-snapshot-
|
|
40
|
-
"@instructure/shared-types": "10.19.2-snapshot-
|
|
41
|
-
"@instructure/ui-dom-utils": "10.19.2-snapshot-
|
|
42
|
-
"@instructure/ui-form-field": "10.19.2-snapshot-
|
|
43
|
-
"@instructure/ui-icons": "10.19.2-snapshot-
|
|
44
|
-
"@instructure/ui-options": "10.19.2-snapshot-
|
|
45
|
-
"@instructure/ui-popover": "10.19.2-snapshot-
|
|
46
|
-
"@instructure/ui-position": "10.19.2-snapshot-
|
|
47
|
-
"@instructure/ui-prop-types": "10.19.2-snapshot-
|
|
48
|
-
"@instructure/ui-react-utils": "10.19.2-snapshot-
|
|
49
|
-
"@instructure/ui-selectable": "10.19.2-snapshot-
|
|
50
|
-
"@instructure/ui-testable": "10.19.2-snapshot-
|
|
51
|
-
"@instructure/ui-text-input": "10.19.2-snapshot-
|
|
52
|
-
"@instructure/ui-utils": "10.19.2-snapshot-
|
|
53
|
-
"@instructure/ui-view": "10.19.2-snapshot-
|
|
54
|
-
"@instructure/uid": "10.19.2-snapshot-
|
|
39
|
+
"@instructure/emotion": "10.19.2-snapshot-11",
|
|
40
|
+
"@instructure/shared-types": "10.19.2-snapshot-11",
|
|
41
|
+
"@instructure/ui-dom-utils": "10.19.2-snapshot-11",
|
|
42
|
+
"@instructure/ui-form-field": "10.19.2-snapshot-11",
|
|
43
|
+
"@instructure/ui-icons": "10.19.2-snapshot-11",
|
|
44
|
+
"@instructure/ui-options": "10.19.2-snapshot-11",
|
|
45
|
+
"@instructure/ui-popover": "10.19.2-snapshot-11",
|
|
46
|
+
"@instructure/ui-position": "10.19.2-snapshot-11",
|
|
47
|
+
"@instructure/ui-prop-types": "10.19.2-snapshot-11",
|
|
48
|
+
"@instructure/ui-react-utils": "10.19.2-snapshot-11",
|
|
49
|
+
"@instructure/ui-selectable": "10.19.2-snapshot-11",
|
|
50
|
+
"@instructure/ui-testable": "10.19.2-snapshot-11",
|
|
51
|
+
"@instructure/ui-text-input": "10.19.2-snapshot-11",
|
|
52
|
+
"@instructure/ui-utils": "10.19.2-snapshot-11",
|
|
53
|
+
"@instructure/ui-view": "10.19.2-snapshot-11",
|
|
54
|
+
"@instructure/uid": "10.19.2-snapshot-11",
|
|
55
55
|
"prop-types": "^15.8.1"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
package/src/Select/README.md
CHANGED
|
@@ -40,14 +40,27 @@ describes: Select
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
handleShowOptions = (event) => {
|
|
43
|
+
const { options } = this.props
|
|
44
|
+
const { inputValue, selectedOptionId } = this.state
|
|
45
|
+
|
|
43
46
|
this.setState({
|
|
44
47
|
isShowingOptions: true
|
|
45
48
|
})
|
|
49
|
+
if (inputValue || selectedOptionId || options.length === 0) return
|
|
50
|
+
|
|
51
|
+
switch (event.key) {
|
|
52
|
+
case 'ArrowDown':
|
|
53
|
+
return this.handleHighlightOption(event, { id: options[0].id })
|
|
54
|
+
case 'ArrowUp':
|
|
55
|
+
return this.handleHighlightOption(event, {
|
|
56
|
+
id: options[options.length - 1].id
|
|
57
|
+
})
|
|
58
|
+
}
|
|
46
59
|
}
|
|
47
60
|
|
|
48
61
|
handleHideOptions = (event) => {
|
|
49
62
|
const { selectedOptionId } = this.state
|
|
50
|
-
const option = this.getOptionById(selectedOptionId)
|
|
63
|
+
const option = this.getOptionById(selectedOptionId)?.label
|
|
51
64
|
this.setState({
|
|
52
65
|
isShowingOptions: false,
|
|
53
66
|
highlightedOptionId: null,
|
|
@@ -68,17 +81,17 @@ describes: Select
|
|
|
68
81
|
const nowOpen = !this.state.isShowingOptions
|
|
69
82
|
? `List expanded. ${optionsAvailable}`
|
|
70
83
|
: ''
|
|
71
|
-
const option = this.getOptionById(id)
|
|
84
|
+
const option = this.getOptionById(id)?.label
|
|
72
85
|
this.setState((state) => ({
|
|
73
86
|
highlightedOptionId: id,
|
|
74
|
-
inputValue:
|
|
87
|
+
inputValue: state.inputValue,
|
|
75
88
|
announcement: `${option} ${nowOpen}`
|
|
76
89
|
}))
|
|
77
90
|
}
|
|
78
91
|
|
|
79
92
|
handleSelectOption = (event, { id }) => {
|
|
80
93
|
this.focusInput()
|
|
81
|
-
const option = this.getOptionById(id)
|
|
94
|
+
const option = this.getOptionById(id)?.label
|
|
82
95
|
this.setState({
|
|
83
96
|
selectedOptionId: id,
|
|
84
97
|
inputValue: option,
|
|
@@ -125,13 +138,6 @@ describes: Select
|
|
|
125
138
|
)
|
|
126
139
|
})}
|
|
127
140
|
</Select>
|
|
128
|
-
<Alert
|
|
129
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
130
|
-
liveRegionPoliteness="assertive"
|
|
131
|
-
screenReaderOnly
|
|
132
|
-
>
|
|
133
|
-
{announcement}
|
|
134
|
-
</Alert>
|
|
135
141
|
</div>
|
|
136
142
|
)
|
|
137
143
|
}
|
|
@@ -185,10 +191,20 @@ describes: Select
|
|
|
185
191
|
|
|
186
192
|
const handleShowOptions = (event) => {
|
|
187
193
|
setIsShowingOptions(true)
|
|
194
|
+
if (inputValue || selectedOptionId || options.length === 0) return
|
|
195
|
+
|
|
196
|
+
switch (event.key) {
|
|
197
|
+
case 'ArrowDown':
|
|
198
|
+
return handleHighlightOption(event, { id: options[0].id })
|
|
199
|
+
case 'ArrowUp':
|
|
200
|
+
return handleHighlightOption(event, {
|
|
201
|
+
id: options[options.length - 1].id
|
|
202
|
+
})
|
|
203
|
+
}
|
|
188
204
|
}
|
|
189
205
|
|
|
190
206
|
const handleHideOptions = (event) => {
|
|
191
|
-
const option = getOptionById(selectedOptionId)
|
|
207
|
+
const option = getOptionById(selectedOptionId)?.label
|
|
192
208
|
setIsShowingOptions(false)
|
|
193
209
|
setHighlightedOptionId(null)
|
|
194
210
|
setSelectedOptionId(selectedOptionId ? option : '')
|
|
@@ -205,15 +221,15 @@ describes: Select
|
|
|
205
221
|
const nowOpen = !isShowingOptions
|
|
206
222
|
? `List expanded. ${optionsAvailable}`
|
|
207
223
|
: ''
|
|
208
|
-
const option = getOptionById(id)
|
|
224
|
+
const option = getOptionById(id)?.label
|
|
209
225
|
setHighlightedOptionId(id)
|
|
210
|
-
setInputValue(
|
|
226
|
+
setInputValue(inputValue)
|
|
211
227
|
setAnnouncement(`${option} ${nowOpen}`)
|
|
212
228
|
}
|
|
213
229
|
|
|
214
230
|
const handleSelectOption = (event, { id }) => {
|
|
215
|
-
const option = getOptionById(id).label
|
|
216
231
|
focusInput()
|
|
232
|
+
const option = getOptionById(id)?.label
|
|
217
233
|
setSelectedOptionId(id)
|
|
218
234
|
setInputValue(option)
|
|
219
235
|
setIsShowingOptions(false)
|
|
@@ -249,13 +265,6 @@ describes: Select
|
|
|
249
265
|
)
|
|
250
266
|
})}
|
|
251
267
|
</Select>
|
|
252
|
-
<Alert
|
|
253
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
254
|
-
liveRegionPoliteness="assertive"
|
|
255
|
-
screenReaderOnly
|
|
256
|
-
>
|
|
257
|
-
{announcement}
|
|
258
|
-
</Alert>
|
|
259
268
|
</div>
|
|
260
269
|
)
|
|
261
270
|
}
|
|
@@ -378,10 +387,24 @@ It's best practice to always provide autocomplete functionality to help users ma
|
|
|
378
387
|
}
|
|
379
388
|
|
|
380
389
|
handleShowOptions = (event) => {
|
|
390
|
+
const { options } = this.props
|
|
391
|
+
const { inputValue, selectedOptionId } = this.state
|
|
392
|
+
|
|
381
393
|
this.setState(({ filteredOptions }) => ({
|
|
382
394
|
isShowingOptions: true,
|
|
383
395
|
announcement: `List expanded. ${filteredOptions.length} options available.`
|
|
384
396
|
}))
|
|
397
|
+
|
|
398
|
+
if (inputValue || selectedOptionId || options.length === 0) return
|
|
399
|
+
|
|
400
|
+
switch (event.key) {
|
|
401
|
+
case 'ArrowDown':
|
|
402
|
+
return this.handleHighlightOption(event, { id: options[0].id })
|
|
403
|
+
case 'ArrowUp':
|
|
404
|
+
return this.handleHighlightOption(event, {
|
|
405
|
+
id: options[options.length - 1].id
|
|
406
|
+
})
|
|
407
|
+
}
|
|
385
408
|
}
|
|
386
409
|
|
|
387
410
|
handleHideOptions = (event) => {
|
|
@@ -404,7 +427,7 @@ It's best practice to always provide autocomplete functionality to help users ma
|
|
|
404
427
|
if (!option) return // prevent highlighting of empty option
|
|
405
428
|
this.setState((state) => ({
|
|
406
429
|
highlightedOptionId: id,
|
|
407
|
-
inputValue:
|
|
430
|
+
inputValue: state.inputValue,
|
|
408
431
|
announcement: option.label
|
|
409
432
|
}))
|
|
410
433
|
}
|
|
@@ -490,13 +513,6 @@ It's best practice to always provide autocomplete functionality to help users ma
|
|
|
490
513
|
</Select.Option>
|
|
491
514
|
)}
|
|
492
515
|
</Select>
|
|
493
|
-
<Alert
|
|
494
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
495
|
-
liveRegionPoliteness="assertive"
|
|
496
|
-
screenReaderOnly
|
|
497
|
-
>
|
|
498
|
-
{announcement}
|
|
499
|
-
</Alert>
|
|
500
516
|
</div>
|
|
501
517
|
)
|
|
502
518
|
}
|
|
@@ -605,6 +621,16 @@ It's best practice to always provide autocomplete functionality to help users ma
|
|
|
605
621
|
setAnnouncement(
|
|
606
622
|
`List expanded. ${filteredOptions.length} options available.`
|
|
607
623
|
)
|
|
624
|
+
if (inputValue || selectedOptionId || options.length === 0) return
|
|
625
|
+
|
|
626
|
+
switch (event.key) {
|
|
627
|
+
case 'ArrowDown':
|
|
628
|
+
return handleHighlightOption(event, { id: options[0].id })
|
|
629
|
+
case 'ArrowUp':
|
|
630
|
+
return handleHighlightOption(event, {
|
|
631
|
+
id: options[options.length - 1].id
|
|
632
|
+
})
|
|
633
|
+
}
|
|
608
634
|
}
|
|
609
635
|
|
|
610
636
|
const handleHideOptions = (event) => {
|
|
@@ -623,7 +649,7 @@ It's best practice to always provide autocomplete functionality to help users ma
|
|
|
623
649
|
const option = getOptionById(id)
|
|
624
650
|
if (!option) return // prevent highlighting of empty option
|
|
625
651
|
setHighlightedOptionId(id)
|
|
626
|
-
setInputValue(
|
|
652
|
+
setInputValue(inputValue)
|
|
627
653
|
setAnnouncement(option.label)
|
|
628
654
|
}
|
|
629
655
|
|
|
@@ -694,13 +720,6 @@ It's best practice to always provide autocomplete functionality to help users ma
|
|
|
694
720
|
</Select.Option>
|
|
695
721
|
)}
|
|
696
722
|
</Select>
|
|
697
|
-
<Alert
|
|
698
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
699
|
-
liveRegionPoliteness="assertive"
|
|
700
|
-
screenReaderOnly
|
|
701
|
-
>
|
|
702
|
-
{announcement}
|
|
703
|
-
</Alert>
|
|
704
723
|
</div>
|
|
705
724
|
)
|
|
706
725
|
}
|
|
@@ -813,7 +832,29 @@ To mark an option as "highlighted", use the option's `isHighlighted` prop. Note
|
|
|
813
832
|
}
|
|
814
833
|
|
|
815
834
|
handleShowOptions = (event) => {
|
|
835
|
+
const { options } = this.props
|
|
836
|
+
const { inputValue, selectedOptionId } = this.state
|
|
837
|
+
|
|
816
838
|
this.setState({ isShowingOptions: true })
|
|
839
|
+
|
|
840
|
+
if (inputValue || options.length === 0) return
|
|
841
|
+
|
|
842
|
+
switch (event.key) {
|
|
843
|
+
case 'ArrowDown':
|
|
844
|
+
return this.handleHighlightOption(event, {
|
|
845
|
+
id: options.find((option) => !selectedOptionId.includes(option.id))
|
|
846
|
+
.id
|
|
847
|
+
})
|
|
848
|
+
case 'ArrowUp':
|
|
849
|
+
// Highlight last non-selected option
|
|
850
|
+
return this.handleHighlightOption(event, {
|
|
851
|
+
id: options[
|
|
852
|
+
options.findLastIndex(
|
|
853
|
+
(option) => !selectedOptionId.includes(option.id)
|
|
854
|
+
)
|
|
855
|
+
].id
|
|
856
|
+
})
|
|
857
|
+
}
|
|
817
858
|
}
|
|
818
859
|
|
|
819
860
|
handleHideOptions = (event) => {
|
|
@@ -835,7 +876,7 @@ To mark an option as "highlighted", use the option's `isHighlighted` prop. Note
|
|
|
835
876
|
if (!option) return // prevent highlighting empty option
|
|
836
877
|
this.setState((state) => ({
|
|
837
878
|
highlightedOptionId: id,
|
|
838
|
-
inputValue:
|
|
879
|
+
inputValue: state.inputValue,
|
|
839
880
|
announcement: option.label
|
|
840
881
|
}))
|
|
841
882
|
}
|
|
@@ -908,7 +949,7 @@ To mark an option as "highlighted", use the option's `isHighlighted` prop. Note
|
|
|
908
949
|
key={id}
|
|
909
950
|
text={
|
|
910
951
|
<AccessibleContent alt={`Remove ${this.getOptionById(id).label}`}>
|
|
911
|
-
{this.getOptionById(id)
|
|
952
|
+
{this.getOptionById(id)?.label}
|
|
912
953
|
</AccessibleContent>
|
|
913
954
|
}
|
|
914
955
|
margin={
|
|
@@ -968,13 +1009,6 @@ To mark an option as "highlighted", use the option's `isHighlighted` prop. Note
|
|
|
968
1009
|
</Select.Option>
|
|
969
1010
|
)}
|
|
970
1011
|
</Select>
|
|
971
|
-
<Alert
|
|
972
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
973
|
-
liveRegionPoliteness="assertive"
|
|
974
|
-
screenReaderOnly
|
|
975
|
-
>
|
|
976
|
-
{announcement}
|
|
977
|
-
</Alert>
|
|
978
1012
|
</div>
|
|
979
1013
|
)
|
|
980
1014
|
}
|
|
@@ -1072,6 +1106,25 @@ To mark an option as "highlighted", use the option's `isHighlighted` prop. Note
|
|
|
1072
1106
|
|
|
1073
1107
|
const handleShowOptions = (event) => {
|
|
1074
1108
|
setIsShowingOptions(true)
|
|
1109
|
+
|
|
1110
|
+
if (inputValue || options.length === 0) return
|
|
1111
|
+
|
|
1112
|
+
switch (event.key) {
|
|
1113
|
+
case 'ArrowDown':
|
|
1114
|
+
return handleHighlightOption(event, {
|
|
1115
|
+
id: options.find((option) => !selectedOptionId.includes(option.id))
|
|
1116
|
+
.id
|
|
1117
|
+
})
|
|
1118
|
+
case 'ArrowUp':
|
|
1119
|
+
// Highlight last non-selected option
|
|
1120
|
+
return handleHighlightOption(event, {
|
|
1121
|
+
id: options[
|
|
1122
|
+
options.findLastIndex(
|
|
1123
|
+
(option) => !selectedOptionId.includes(option.id)
|
|
1124
|
+
)
|
|
1125
|
+
].id
|
|
1126
|
+
})
|
|
1127
|
+
}
|
|
1075
1128
|
}
|
|
1076
1129
|
|
|
1077
1130
|
const handleHideOptions = (event) => {
|
|
@@ -1088,7 +1141,7 @@ To mark an option as "highlighted", use the option's `isHighlighted` prop. Note
|
|
|
1088
1141
|
const option = getOptionById(id)
|
|
1089
1142
|
if (!option) return // prevent highlighting empty option
|
|
1090
1143
|
setHighlightedOptionId(id)
|
|
1091
|
-
setInputValue(
|
|
1144
|
+
setInputValue(inputValue)
|
|
1092
1145
|
setAnnouncement(option.label)
|
|
1093
1146
|
}
|
|
1094
1147
|
|
|
@@ -1197,13 +1250,6 @@ To mark an option as "highlighted", use the option's `isHighlighted` prop. Note
|
|
|
1197
1250
|
</Select.Option>
|
|
1198
1251
|
)}
|
|
1199
1252
|
</Select>
|
|
1200
|
-
<Alert
|
|
1201
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
1202
|
-
liveRegionPoliteness="assertive"
|
|
1203
|
-
screenReaderOnly
|
|
1204
|
-
>
|
|
1205
|
-
{announcement}
|
|
1206
|
-
</Alert>
|
|
1207
1253
|
</div>
|
|
1208
1254
|
)
|
|
1209
1255
|
}
|
|
@@ -1284,10 +1330,26 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1284
1330
|
}
|
|
1285
1331
|
|
|
1286
1332
|
handleShowOptions = (event) => {
|
|
1333
|
+
const { options } = this.props
|
|
1334
|
+
const { inputValue, selectedOptionId } = this.state
|
|
1335
|
+
|
|
1287
1336
|
this.setState({
|
|
1288
1337
|
isShowingOptions: true,
|
|
1289
1338
|
highlightedOptionId: null
|
|
1290
1339
|
})
|
|
1340
|
+
|
|
1341
|
+
if (inputValue || selectedOptionId || options.length === 0) return
|
|
1342
|
+
|
|
1343
|
+
switch (event.key) {
|
|
1344
|
+
case 'ArrowDown':
|
|
1345
|
+
return this.handleHighlightOption(event, {
|
|
1346
|
+
id: options[Object.keys(options)[0]][0].id
|
|
1347
|
+
})
|
|
1348
|
+
case 'ArrowUp':
|
|
1349
|
+
return this.handleHighlightOption(event, {
|
|
1350
|
+
id: Object.values(options).at(-1)?.at(-1)?.id
|
|
1351
|
+
})
|
|
1352
|
+
}
|
|
1291
1353
|
}
|
|
1292
1354
|
|
|
1293
1355
|
handleHideOptions = (event) => {
|
|
@@ -1295,7 +1357,7 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1295
1357
|
this.setState({
|
|
1296
1358
|
isShowingOptions: false,
|
|
1297
1359
|
highlightedOptionId: null,
|
|
1298
|
-
inputValue: this.getOptionById(selectedOptionId)
|
|
1360
|
+
inputValue: this.getOptionById(selectedOptionId)?.label
|
|
1299
1361
|
})
|
|
1300
1362
|
}
|
|
1301
1363
|
|
|
@@ -1310,8 +1372,7 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1310
1372
|
const newOption = this.getOptionById(id)
|
|
1311
1373
|
this.setState((state) => ({
|
|
1312
1374
|
highlightedOptionId: id,
|
|
1313
|
-
inputValue:
|
|
1314
|
-
event.type === 'keydown' ? newOption.label : state.inputValue,
|
|
1375
|
+
inputValue: state.inputValue,
|
|
1315
1376
|
announcement: this.getGroupChangedMessage(newOption)
|
|
1316
1377
|
}))
|
|
1317
1378
|
}
|
|
@@ -1392,7 +1453,7 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1392
1453
|
<Badge
|
|
1393
1454
|
type="notification"
|
|
1394
1455
|
variant={
|
|
1395
|
-
this.getOptionById(selectedOptionId)
|
|
1456
|
+
this.getOptionById(selectedOptionId)?.group === 'Eastern'
|
|
1396
1457
|
? 'success'
|
|
1397
1458
|
: 'primary'
|
|
1398
1459
|
}
|
|
@@ -1406,13 +1467,6 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1406
1467
|
>
|
|
1407
1468
|
{this.renderGroup()}
|
|
1408
1469
|
</Select>
|
|
1409
|
-
<Alert
|
|
1410
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
1411
|
-
liveRegionPoliteness="assertive"
|
|
1412
|
-
screenReaderOnly
|
|
1413
|
-
>
|
|
1414
|
-
{announcement}
|
|
1415
|
-
</Alert>
|
|
1416
1470
|
</div>
|
|
1417
1471
|
)
|
|
1418
1472
|
}
|
|
@@ -1432,7 +1486,7 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1432
1486
|
{ id: 'opt1', label: 'Alabama' },
|
|
1433
1487
|
{ id: 'opt2', label: 'Connecticut' },
|
|
1434
1488
|
{ id: 'opt3', label: 'Delaware' },
|
|
1435
|
-
{ id: '
|
|
1489
|
+
{ id: 'opt4', label: 'Illinois' }
|
|
1436
1490
|
]
|
|
1437
1491
|
}}
|
|
1438
1492
|
/>
|
|
@@ -1486,12 +1540,24 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1486
1540
|
const handleShowOptions = (event) => {
|
|
1487
1541
|
setIsShowingOptions(true)
|
|
1488
1542
|
setHighlightedOptionId(null)
|
|
1543
|
+
if (inputValue || selectedOptionId || options.length === 0) return
|
|
1544
|
+
|
|
1545
|
+
switch (event.key) {
|
|
1546
|
+
case 'ArrowDown':
|
|
1547
|
+
return handleHighlightOption(event, {
|
|
1548
|
+
id: options[Object.keys(options)[0]][0].id
|
|
1549
|
+
})
|
|
1550
|
+
case 'ArrowUp':
|
|
1551
|
+
return handleHighlightOption(event, {
|
|
1552
|
+
id: Object.values(options).at(-1)?.at(-1)?.id
|
|
1553
|
+
})
|
|
1554
|
+
}
|
|
1489
1555
|
}
|
|
1490
1556
|
|
|
1491
1557
|
const handleHideOptions = (event) => {
|
|
1492
1558
|
setIsShowingOptions(false)
|
|
1493
1559
|
setHighlightedOptionId(null)
|
|
1494
|
-
setInputValue(getOptionById(selectedOptionId)
|
|
1560
|
+
setInputValue(getOptionById(selectedOptionId)?.label)
|
|
1495
1561
|
}
|
|
1496
1562
|
|
|
1497
1563
|
const handleBlur = (event) => {
|
|
@@ -1502,7 +1568,7 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1502
1568
|
event.persist()
|
|
1503
1569
|
const newOption = getOptionById(id)
|
|
1504
1570
|
setHighlightedOptionId(id)
|
|
1505
|
-
setInputValue(
|
|
1571
|
+
setInputValue(inputValue)
|
|
1506
1572
|
setAnnouncement(getGroupChangedMessage(newOption))
|
|
1507
1573
|
}
|
|
1508
1574
|
|
|
@@ -1567,7 +1633,7 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1567
1633
|
<Badge
|
|
1568
1634
|
type="notification"
|
|
1569
1635
|
variant={
|
|
1570
|
-
getOptionById(selectedOptionId)
|
|
1636
|
+
getOptionById(selectedOptionId)?.group === 'Eastern'
|
|
1571
1637
|
? 'success'
|
|
1572
1638
|
: 'primary'
|
|
1573
1639
|
}
|
|
@@ -1581,13 +1647,6 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1581
1647
|
>
|
|
1582
1648
|
{renderGroup()}
|
|
1583
1649
|
</Select>
|
|
1584
|
-
<Alert
|
|
1585
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
1586
|
-
liveRegionPoliteness="assertive"
|
|
1587
|
-
screenReaderOnly
|
|
1588
|
-
>
|
|
1589
|
-
{announcement}
|
|
1590
|
-
</Alert>
|
|
1591
1650
|
</div>
|
|
1592
1651
|
)
|
|
1593
1652
|
}
|
|
@@ -1606,7 +1665,7 @@ In addition to `<Select.Option />` Select also accepts `<Select.Group />` as chi
|
|
|
1606
1665
|
{ id: 'opt1', label: 'Alabama' },
|
|
1607
1666
|
{ id: 'opt2', label: 'Connecticut' },
|
|
1608
1667
|
{ id: 'opt3', label: 'Delaware' },
|
|
1609
|
-
{ id: '
|
|
1668
|
+
{ id: 'opt4', label: 'Illinois' }
|
|
1610
1669
|
]
|
|
1611
1670
|
}}
|
|
1612
1671
|
/>
|
|
@@ -1659,10 +1718,26 @@ Due to a WebKit bug if you are using `Select.Group` with autocomplete, the scree
|
|
|
1659
1718
|
}
|
|
1660
1719
|
|
|
1661
1720
|
handleShowOptions = (event) => {
|
|
1721
|
+
const { options } = this.props
|
|
1722
|
+
const { inputValue, selectedOptionId } = this.state
|
|
1723
|
+
|
|
1662
1724
|
this.setState({
|
|
1663
1725
|
isShowingOptions: true,
|
|
1664
1726
|
highlightedOptionId: null
|
|
1665
1727
|
})
|
|
1728
|
+
|
|
1729
|
+
if (inputValue || selectedOptionId || options.length === 0) return
|
|
1730
|
+
|
|
1731
|
+
switch (event.key) {
|
|
1732
|
+
case 'ArrowDown':
|
|
1733
|
+
return this.handleHighlightOption(event, {
|
|
1734
|
+
id: options[Object.keys(options)[0]][0].id
|
|
1735
|
+
})
|
|
1736
|
+
case 'ArrowUp':
|
|
1737
|
+
return this.handleHighlightOption(event, {
|
|
1738
|
+
id: Object.values(options).at(-1)?.at(-1)?.id
|
|
1739
|
+
})
|
|
1740
|
+
}
|
|
1666
1741
|
}
|
|
1667
1742
|
|
|
1668
1743
|
handleHideOptions = (event) => {
|
|
@@ -1848,6 +1923,19 @@ Due to a WebKit bug if you are using `Select.Group` with autocomplete, the scree
|
|
|
1848
1923
|
const handleShowOptions = (event) => {
|
|
1849
1924
|
setIsShowingOptions(true)
|
|
1850
1925
|
setHighlightedOptionId(null)
|
|
1926
|
+
|
|
1927
|
+
if (inputValue || selectedOptionId || options.length === 0) return
|
|
1928
|
+
|
|
1929
|
+
switch (event.key) {
|
|
1930
|
+
case 'ArrowDown':
|
|
1931
|
+
return handleHighlightOption(event, {
|
|
1932
|
+
id: options[Object.keys(options)[0]][0].id
|
|
1933
|
+
})
|
|
1934
|
+
case 'ArrowUp':
|
|
1935
|
+
return handleHighlightOption(event, {
|
|
1936
|
+
id: Object.values(options).at(-1)?.at(-1)?.id
|
|
1937
|
+
})
|
|
1938
|
+
}
|
|
1851
1939
|
}
|
|
1852
1940
|
|
|
1853
1941
|
const handleHideOptions = (event) => {
|
|
@@ -2060,7 +2148,7 @@ If no results match the user's search, it's recommended to leave `isShowingOptio
|
|
|
2060
2148
|
if (!option) return // prevent highlighting of empty option
|
|
2061
2149
|
this.setState((state) => ({
|
|
2062
2150
|
highlightedOptionId: id,
|
|
2063
|
-
inputValue:
|
|
2151
|
+
inputValue: state.inputValue,
|
|
2064
2152
|
announcement: option.label
|
|
2065
2153
|
}))
|
|
2066
2154
|
}
|
|
@@ -2170,13 +2258,6 @@ If no results match the user's search, it's recommended to leave `isShowingOptio
|
|
|
2170
2258
|
</Select.Option>
|
|
2171
2259
|
)}
|
|
2172
2260
|
</Select>
|
|
2173
|
-
<Alert
|
|
2174
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
2175
|
-
liveRegionPoliteness="assertive"
|
|
2176
|
-
screenReaderOnly
|
|
2177
|
-
>
|
|
2178
|
-
{announcement}
|
|
2179
|
-
</Alert>
|
|
2180
2261
|
</div>
|
|
2181
2262
|
)
|
|
2182
2263
|
}
|
|
@@ -2283,7 +2364,7 @@ If no results match the user's search, it's recommended to leave `isShowingOptio
|
|
|
2283
2364
|
if (!option) return // prevent highlighting of empty option
|
|
2284
2365
|
|
|
2285
2366
|
setHighlightedOptionId(id)
|
|
2286
|
-
setInputValue(
|
|
2367
|
+
setInputValue(inputValue)
|
|
2287
2368
|
setAnnouncement(option.label)
|
|
2288
2369
|
}
|
|
2289
2370
|
|
|
@@ -2373,13 +2454,6 @@ If no results match the user's search, it's recommended to leave `isShowingOptio
|
|
|
2373
2454
|
</Select.Option>
|
|
2374
2455
|
)}
|
|
2375
2456
|
</Select>
|
|
2376
|
-
<Alert
|
|
2377
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
2378
|
-
liveRegionPoliteness="assertive"
|
|
2379
|
-
screenReaderOnly
|
|
2380
|
-
>
|
|
2381
|
-
{announcement}
|
|
2382
|
-
</Alert>
|
|
2383
2457
|
</div>
|
|
2384
2458
|
)
|
|
2385
2459
|
}
|
|
@@ -2436,14 +2510,28 @@ To display icons (or other elements) before or after an option, pass it via the
|
|
|
2436
2510
|
}
|
|
2437
2511
|
|
|
2438
2512
|
handleShowOptions = (event) => {
|
|
2513
|
+
const { options } = this.props
|
|
2514
|
+
const { inputValue, selectedOptionId } = this.state
|
|
2515
|
+
|
|
2439
2516
|
this.setState({
|
|
2440
2517
|
isShowingOptions: true
|
|
2441
2518
|
})
|
|
2519
|
+
|
|
2520
|
+
if (inputValue || selectedOptionId || options.length === 0) return
|
|
2521
|
+
|
|
2522
|
+
switch (event.key) {
|
|
2523
|
+
case 'ArrowDown':
|
|
2524
|
+
return this.handleHighlightOption(event, { id: options[0].id })
|
|
2525
|
+
case 'ArrowUp':
|
|
2526
|
+
return this.handleHighlightOption(event, {
|
|
2527
|
+
id: options[options.length - 1].id
|
|
2528
|
+
})
|
|
2529
|
+
}
|
|
2442
2530
|
}
|
|
2443
2531
|
|
|
2444
2532
|
handleHideOptions = (event) => {
|
|
2445
2533
|
const { selectedOptionId } = this.state
|
|
2446
|
-
const option = this.getOptionById(selectedOptionId)
|
|
2534
|
+
const option = this.getOptionById(selectedOptionId)?.label
|
|
2447
2535
|
this.setState({
|
|
2448
2536
|
isShowingOptions: false,
|
|
2449
2537
|
highlightedOptionId: null,
|
|
@@ -2467,7 +2555,7 @@ To display icons (or other elements) before or after an option, pass it via the
|
|
|
2467
2555
|
const option = this.getOptionById(id).label
|
|
2468
2556
|
this.setState((state) => ({
|
|
2469
2557
|
highlightedOptionId: id,
|
|
2470
|
-
inputValue:
|
|
2558
|
+
inputValue: state.inputValue,
|
|
2471
2559
|
announcement: `${option} ${nowOpen}`
|
|
2472
2560
|
}))
|
|
2473
2561
|
}
|
|
@@ -2522,13 +2610,6 @@ To display icons (or other elements) before or after an option, pass it via the
|
|
|
2522
2610
|
)
|
|
2523
2611
|
})}
|
|
2524
2612
|
</Select>
|
|
2525
|
-
<Alert
|
|
2526
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
2527
|
-
liveRegionPoliteness="assertive"
|
|
2528
|
-
screenReaderOnly
|
|
2529
|
-
>
|
|
2530
|
-
{announcement}
|
|
2531
|
-
</Alert>
|
|
2532
2613
|
</div>
|
|
2533
2614
|
)
|
|
2534
2615
|
}
|
|
@@ -2587,10 +2668,21 @@ To display icons (or other elements) before or after an option, pass it via the
|
|
|
2587
2668
|
|
|
2588
2669
|
const handleShowOptions = (event) => {
|
|
2589
2670
|
setIsShowingOptions(true)
|
|
2671
|
+
|
|
2672
|
+
if (inputValue || selectedOptionId || options.length === 0) return
|
|
2673
|
+
|
|
2674
|
+
switch (event.key) {
|
|
2675
|
+
case 'ArrowDown':
|
|
2676
|
+
return handleHighlightOption(event, { id: options[0].id })
|
|
2677
|
+
case 'ArrowUp':
|
|
2678
|
+
return handleHighlightOption(event, {
|
|
2679
|
+
id: options[options.length - 1].id
|
|
2680
|
+
})
|
|
2681
|
+
}
|
|
2590
2682
|
}
|
|
2591
2683
|
|
|
2592
2684
|
const handleHideOptions = (event) => {
|
|
2593
|
-
const option = getOptionById(selectedOptionId)
|
|
2685
|
+
const option = getOptionById(selectedOptionId)?.label
|
|
2594
2686
|
setIsShowingOptions(false)
|
|
2595
2687
|
setHighlightedOptionId(null)
|
|
2596
2688
|
setInputValue(selectedOptionId ? option : '')
|
|
@@ -2609,7 +2701,7 @@ To display icons (or other elements) before or after an option, pass it via the
|
|
|
2609
2701
|
: ''
|
|
2610
2702
|
const option = getOptionById(id).label
|
|
2611
2703
|
setHighlightedOptionId(id)
|
|
2612
|
-
setInputValue(
|
|
2704
|
+
setInputValue(inputValue)
|
|
2613
2705
|
setAnnouncement(`${option} ${nowOpen}`)
|
|
2614
2706
|
}
|
|
2615
2707
|
|
|
@@ -2652,13 +2744,6 @@ To display icons (or other elements) before or after an option, pass it via the
|
|
|
2652
2744
|
)
|
|
2653
2745
|
})}
|
|
2654
2746
|
</Select>
|
|
2655
|
-
<Alert
|
|
2656
|
-
liveRegion={() => document.getElementById('flash-messages')}
|
|
2657
|
-
liveRegionPoliteness="assertive"
|
|
2658
|
-
screenReaderOnly
|
|
2659
|
-
>
|
|
2660
|
-
{announcement}
|
|
2661
|
-
</Alert>
|
|
2662
2747
|
</div>
|
|
2663
2748
|
)
|
|
2664
2749
|
}
|
|
@@ -2708,6 +2793,8 @@ type: embed
|
|
|
2708
2793
|
<Figure recommendation="a11y" title="Accessibility">
|
|
2709
2794
|
<Figure.Item>To ensure Select is accessible for iOS VoiceOver users, the input field’s focus must be blurred and then reapplied after selecting an option and closing the listbox. The examples above demonstrate this behavior.
|
|
2710
2795
|
</Figure.Item>
|
|
2796
|
+
<Figure.Item>If no option is selected initially, pressing the down arrow should open the listbox and move focus to the first option, while pressing up should move focus to the last item. You can see this behavior in the examples above.
|
|
2797
|
+
</Figure.Item>
|
|
2711
2798
|
</Figure>
|
|
2712
2799
|
</Guidelines>
|
|
2713
2800
|
```
|