|
23 | 23 |
|
24 | 24 | let inputText = $state(selectedLocation?.name ?? ""); |
25 | 25 | let inputElement: HTMLInputElement; |
26 | | - let isExpanded = $state(false); |
27 | | - let focused = $state(-1); |
| 26 | + let isFocused = $state(false); |
| 27 | + let focusedId = $state(-1); |
28 | 28 | let isInputBlurredBySelection = $state(true); |
29 | 29 | let isSuggestionsHidden = $state(false); |
30 | 30 |
|
|
51 | 51 | * selects the first suggested location if the user leaves the input without a selection |
52 | 52 | */ |
53 | 53 | function handleInputBlur(): void { |
54 | | - isExpanded = false; |
| 54 | + isFocused = false; |
55 | 55 | isSuggestionsHidden = false; |
56 | 56 | isInputBlurredBySelection = false; // this is reset to `true` in `handleSuggestionClick()`, otherwise it remains `false` |
57 | 57 | setTimeout(() => { |
|
68 | 68 | void suggestions.then((suggestions) => { |
69 | 69 | selectedLocation = suggestions[0]; |
70 | 70 | inputText = suggestions[0]?.name ?? ""; |
71 | | - focused = -1; |
| 71 | + focusedId = -1; |
72 | 72 | }); |
73 | 73 | } |
74 | 74 | }, 500); |
|
98 | 98 | inputElement.blur(); |
99 | 99 | selectedLocation = suggestion; |
100 | 100 | inputText = suggestion.name; |
101 | | - focused = -1; |
| 101 | + focusedId = -1; |
102 | 102 | isInputBlurredBySelection = true; |
103 | 103 | isSuggestionsHidden = true; |
104 | 104 | } |
|
107 | 107 | void suggestions.then((suggestions) => { |
108 | 108 | switch (ev.key) { |
109 | 109 | case "ArrowDown": |
110 | | - focused = (focused + 1) % suggestions.length; |
| 110 | + focusedId = (focusedId + 1) % suggestions.length; |
111 | 111 | ev.preventDefault(); |
112 | 112 | break; |
113 | 113 | case "ArrowUp": |
114 | | - focused = focused <= 0 ? suggestions.length - 1 : focused - 1; |
| 114 | + focusedId = focusedId <= 0 ? suggestions.length - 1 : focusedId - 1; |
115 | 115 | ev.preventDefault(); |
116 | 116 | break; |
117 | 117 | case "Enter": |
118 | | - if (focused >= 0) { |
| 118 | + if (focusedId >= 0) { |
119 | 119 | isSuggestionsHidden = true; |
120 | 120 | } |
121 | 121 | ev.preventDefault(); |
122 | 122 | // fallthrough |
123 | 123 | case "Tab": |
124 | | - if (focused >= 0) { |
| 124 | + if (focusedId >= 0) { |
125 | 125 | // something is focused |
126 | | - selectedLocation = suggestions[focused]; // do not use `handleSuggestionClick`, since the input does not need to be blurred |
127 | | - inputText = suggestions[focused].name; |
| 126 | + selectedLocation = suggestions[focusedId]; // do not use `handleSuggestionClick`, since the input does not need to be blurred |
| 127 | + inputText = suggestions[focusedId].name; |
128 | 128 | } |
129 | | - focused = -1; |
| 129 | + focusedId = -1; |
130 | 130 | break; |
131 | 131 | case "ArrowRight": |
132 | 132 | case "ArrowLeft": |
133 | 133 | break; |
134 | 134 | default: |
135 | 135 | isSuggestionsHidden = false; |
136 | | - focused = -1; |
| 136 | + focusedId = -1; |
137 | 137 | } |
138 | 138 | }); |
139 | 139 | } |
|
163 | 163 | onblur={handleInputBlur} |
164 | 164 | onfocus={(): void => { |
165 | 165 | isInputBlurredBySelection = false; |
166 | | - isExpanded = true; |
| 166 | + isFocused = true; |
167 | 167 | isSuggestionsHidden = false; |
168 | 168 | }} |
169 | 169 | role="combobox" |
170 | 170 | aria-label="Station {stationInputId + 1}" |
171 | 171 | aria-autocomplete="list" |
172 | | - aria-activedescendant="search-input__{stationInputId}--suggestions__{focused}" |
173 | | - aria-expanded={isExpanded && !isSuggestionsHidden} |
| 172 | + aria-activedescendant={focusedId !== -1 |
| 173 | + ? `search-input__${stationInputId}--suggestions__${focusedId}` |
| 174 | + : ""} |
| 175 | + aria-expanded={isFocused && !isSuggestionsHidden} |
174 | 176 | aria-controls="search-input__{stationInputId}--suggestions" |
175 | 177 | /> |
176 | 178 | {#if selectedLocation !== undefined && selectedLocation.name !== "Standort"} |
|
223 | 225 | <button |
224 | 226 | type="button" |
225 | 227 | class="flex-row padded-top-bottom suggestion__button" |
226 | | - class:focused={focused === i} |
| 228 | + class:focused={focusedId === i} |
227 | 229 | tabindex="-1" |
228 | 230 | onclick={() => void handleSuggestionClick(suggestion)} |
229 | 231 | > |
|
0 commit comments