@@ -3,9 +3,27 @@ import debounce from './debounce'
3
3
import { fragment } from './send'
4
4
import Combobox from '@github/combobox-nav'
5
5
6
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
7
- // @ts -ignore
8
- const SCREEN_READER_DELAY = window . testScreenReaderDelay || 100
6
+ // @jscholes :
7
+ /* clear button */
8
+ // ensure "suggestions hidden" only fires if the suggestions were visible
9
+
10
+ /* other */
11
+ // this autopopulation with the value instead of the label of the option ??
12
+ // disabled options shouldn't happen
13
+ // "As soon as you move focus from the control, the list should hide"
14
+
15
+ /*
16
+ This autocomplete behavior may not be relevant everywhere.
17
+
18
+ Label dropdown case
19
+ - add tabindex=0 to listbox
20
+ - remove aria-expanded
21
+ - remove combobox role
22
+ ** doesn't get the value in the input itself
23
+
24
+ */
25
+
26
+ const SCREEN_READER_DELAY = 300
9
27
10
28
export default class Autocomplete {
11
29
container : AutocompleteElement
@@ -38,32 +56,24 @@ export default class Autocomplete {
38
56
39
57
// make sure feedback has all required aria attributes
40
58
if ( this . feedback ) {
41
- this . feedback . setAttribute ( 'aria-live' , 'assertive' )
59
+ // this.feedback.setAttribute('aria-live', 'assertive')
60
+ this . feedback . setAttribute ( 'aria-live' , 'polite' )
42
61
this . feedback . setAttribute ( 'aria-atomic' , 'true' )
43
62
}
44
63
45
- // if clearButton is not a button, show error
46
- if ( this . clearButton && ! ( this . clearButton instanceof HTMLButtonElement ) ) {
47
- const buttonErrorMessage = `Accessibility violation: ${ this . clearButton . tagName } provided for clear button. Please use a "button" element.`
48
- const buttonErrorText = '\u26a0 Error: See console'
49
- const buttonError = document . createElement ( 'span' )
50
- buttonError . setAttribute ( 'style' , 'color:#92140C' )
51
- buttonError . id = `${ this . input . id || this . input . name } -error`
52
- buttonError . textContent = buttonErrorText
53
- this . clearButton . parentNode ?. replaceChild ( buttonError , this . clearButton )
54
- this . clearButton = buttonError
55
- // eslint-disable-next-line no-console
56
- console . error ( buttonErrorMessage )
57
- }
58
-
59
64
// if clearButton doesn't have an accessible label, give it one
60
65
if ( this . clearButton && ! this . clearButton . getAttribute ( 'aria-label' ) ) {
61
66
const labelElem = document . querySelector ( `label[for="${ this . input . name } "]` )
62
- const label = labelElem ?. innerHTML || this . input . getAttribute ( 'aria-label' ) || ''
63
- this . clearButton . setAttribute ( 'aria-label ' , `clear ${ label } ` )
67
+ this . clearButton . setAttribute ( 'aria-label' , `clear:` )
68
+ this . clearButton . setAttribute ( 'aria-labelledby ' , `${ this . clearButton . id } ${ labelElem ?. id || '' } ` )
64
69
}
65
70
71
+ if ( ! this . input . getAttribute ( 'aria-expanded' ) ) {
72
+ this . input . setAttribute ( 'aria-expanded' , 'false' )
73
+ }
74
+
66
75
this . results . hidden = true
76
+ this . results . setAttribute ( 'aria-label' , 'results' )
67
77
this . input . setAttribute ( 'autocomplete' , 'off' )
68
78
this . input . setAttribute ( 'spellcheck' , 'false' )
69
79
@@ -101,7 +111,12 @@ export default class Autocomplete {
101
111
this . input . value = ''
102
112
this . container . value = ''
103
113
this . input . focus ( )
104
- this . updateFeedbackForScreenReaders ( 'Suggestions hidden.' )
114
+
115
+ if ( this . input . getAttribute ( 'aria-expanded' ) === 'true' ) {
116
+ this . container . open = false
117
+ this . input . setAttribute ( 'aria-expanded' , 'false' )
118
+ this . updateFeedbackForScreenReaders ( 'Results hidden.' )
119
+ }
105
120
}
106
121
107
122
onKeydown ( event : KeyboardEvent ) : void {
@@ -154,7 +169,7 @@ export default class Autocomplete {
154
169
this . container . value = value
155
170
156
171
if ( ! value ) {
157
- this . updateFeedbackForScreenReaders ( `Suggestions hidden.` )
172
+ this . updateFeedbackForScreenReaders ( `Results hidden.` )
158
173
}
159
174
}
160
175
@@ -209,15 +224,15 @@ export default class Autocomplete {
209
224
const hasResults = ! ! allNewOptions . length
210
225
const numOptions = allNewOptions . length
211
226
212
- // inform SR users of which element is "on-deck" so that it's clear what Enter will do
213
227
const [ firstOption ] = allNewOptions
214
228
const firstOptionValue = firstOption ?. textContent
215
229
if ( this . autoselectEnabled && firstOptionValue ) {
230
+ // inform SR users of which element is "on-deck" so that it's clear what Enter will do
216
231
this . updateFeedbackForScreenReaders (
217
- `${ numOptions } suggested options. Press Enter to select ${ firstOptionValue } .`
232
+ `${ numOptions } results. ${ firstOptionValue } is the top result: Press Enter to activate .`
218
233
)
219
234
} else {
220
- this . updateFeedbackForScreenReaders ( `${ numOptions } suggested options .` )
235
+ this . updateFeedbackForScreenReaders ( `${ numOptions || 0 } results .` )
221
236
}
222
237
223
238
this . container . open = hasResults
0 commit comments