@thecb/components 6.0.0-beta.3 → 6.0.0-beta.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thecb/components",
3
- "version": "6.0.0-beta.3",
3
+ "version": "6.0.0-beta.6",
4
4
  "description": "Common lib for CityBase react components",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -74,10 +74,10 @@ const DropdownItemWrapper = styled.div`
74
74
 
75
75
  const SearchInput = styled.input`
76
76
  border: none;
77
- background-color: ${({ themeValues }) =>
78
- themeValues.hoverColor && themeValues.hoverColor};
77
+ background-color: transparent;
79
78
  font-size: 16px;
80
79
  height: 24px;
80
+ min-width: 80%;
81
81
  `;
82
82
 
83
83
  const Dropdown = ({
@@ -94,7 +94,9 @@ const Dropdown = ({
94
94
  widthFitOptions = false,
95
95
  disabled,
96
96
  hasTitles = false,
97
- autoEraseTypeAhead = true // legacy behavior as of 05/22
97
+ autoEraseTypeAhead = true, // legacy behavior as of 05/22
98
+ ariaLabelledby,
99
+ autocompleteValue = "" // autofill item for browsers, like country-name or address-level1 for state
98
100
  }) => {
99
101
  const [inputValue, setInputValue] = useState("");
100
102
  const [optionsState, setOptionsState] = useState([]);
@@ -161,10 +163,18 @@ const Dropdown = ({
161
163
  break;
162
164
  case "Backspace" || "Delete":
163
165
  e.preventDefault();
164
- console.log("input value is", inputValue);
165
- console.log("new input value will be", inputValue.slice(0, -1));
166
166
  setInputValue(inputValue.slice(0, -1));
167
167
  break;
168
+ case "Home":
169
+ e.preventDefault();
170
+ optionRefs.current[0].current.focus();
171
+ break;
172
+ case "End":
173
+ e.preventDefault();
174
+ optionRefs.current[
175
+ optionRefs?.current?.length ?? 0 - 1
176
+ ].current.focus();
177
+ break;
168
178
  }
169
179
  if ((keyCode > 64 && keyCode < 91) || keyCode == 32 || keyCode == 189) {
170
180
  e.preventDefault();
@@ -179,7 +189,11 @@ const Dropdown = ({
179
189
  );
180
190
  console.log("selected refs in isopen useffect", selectedRef);
181
191
  console.log("value in isopen useffect", value);
182
- if (isOpen && optionRefs.current[0].current) {
192
+ if (isOpen && selectedRef !== undefined) {
193
+ // WAI-ARIA requires the selected option to receive focus
194
+ selectedRef.current.focus();
195
+ } else if (isOpen && optionRefs.current[0].current) {
196
+ // If no selected option, first option receives focus
183
197
  optionRefs.current[0].current.focus();
184
198
  }
185
199
  clearTimeout(timer);
@@ -207,6 +221,8 @@ const Dropdown = ({
207
221
  !disabledValues.includes(filteredOptions[0].value) &&
208
222
  filteredOptions[0].text != placeholder
209
223
  ) {
224
+ console.log("filtered options are", filteredOptions);
225
+ console.log("option refs are", optionRefs);
210
226
  onSelect(filteredOptions[0].value);
211
227
  }
212
228
  if (optionRefs.current[0].current) {
@@ -224,6 +240,10 @@ const Dropdown = ({
224
240
  width="100%"
225
241
  hoverStyles={`background-color: ${themeValues.hoverColor};`}
226
242
  aria-expanded={isOpen}
243
+ role="combobox"
244
+ aria-owns={`${ariaLabelledby}_listbox`}
245
+ aria-haspopup="listbox"
246
+ aria-labelledby={ariaLabelledby}
227
247
  extraStyles={
228
248
  disabled &&
229
249
  `color: #6e727e;
@@ -256,27 +276,28 @@ const Dropdown = ({
256
276
  pointer-events: none;`}
257
277
  `}
258
278
  >
259
- <Stack direction="row" bottomItem={2}>
260
- {isOpen ? (
261
- <SearchInput
262
- aria-label={inputValue || "Dropdown awaiting search value"}
263
- value={inputValue}
264
- onChange={noop}
265
- themeValues={themeValues}
266
- />
267
- ) : (
268
- <Text
269
- variant="p"
270
- extraStyles={
271
- disabled &&
272
- `color: #6e727e;
273
- background-color: #f7f7f7;
274
- pointer-events: none;`
275
- }
276
- >
277
- {getSelection()}
278
- </Text>
279
- )}
279
+ <Stack
280
+ direction="row"
281
+ bottomItem={2}
282
+ extraStyles={`position: relative;`}
283
+ >
284
+ <SearchInput
285
+ aria-label={getSelection()}
286
+ placeholder={getSelection()}
287
+ value={inputValue}
288
+ onChange={noop}
289
+ themeValues={themeValues}
290
+ role="searchbox"
291
+ type="text"
292
+ aria-multiline="false"
293
+ aria-autocomplete="list"
294
+ aria-controls={`${ariaLabelledby}_listbox`}
295
+ aria-activedescendant="selected_option"
296
+ isOpen={isOpen}
297
+ tabIndex={-1}
298
+ name={autocompleteValue}
299
+ autocomplete={autocompleteValue}
300
+ />
280
301
  <IconWrapper open={isOpen}>
281
302
  <DropdownIcon />
282
303
  </IconWrapper>
@@ -289,14 +310,20 @@ const Dropdown = ({
289
310
  ref={dropdownRef}
290
311
  widthFitOptions={widthFitOptions}
291
312
  tabIndex={0}
313
+ role="listbox"
314
+ id={`${ariaLabelledby}_listbox`}
292
315
  >
293
316
  <Stack childGap="0">
294
317
  {filteredOptions.map((choice, i) => {
295
- if (selectedRef === undefined && choice.value === value) {
318
+ if (
319
+ choice.value === value &&
320
+ selectedRef !== optionRefs.current[i]
321
+ ) {
296
322
  setSelectedRef(optionRefs.current[i]);
297
323
  }
298
324
  return (
299
325
  <DropdownItemWrapper
326
+ id={choice.value === value ? "selected_option" : choice.value}
300
327
  key={choice.value}
301
328
  ref={optionRefs.current[i]}
302
329
  as="button"
@@ -304,13 +331,18 @@ const Dropdown = ({
304
331
  onClick={
305
332
  disabledValues.includes(choice.value)
306
333
  ? evt => evt.preventDefault()
307
- : () => onSelect(choice.value)
334
+ : () => {
335
+ setSelectedRef(optionRefs.current[i]);
336
+ onSelect(choice.value);
337
+ }
308
338
  }
309
339
  selected={choice.value === value}
340
+ aria-selected={choice.value === value}
310
341
  disabled={disabledValues.includes(choice.value)}
311
342
  data-qa={choice.text}
312
343
  themeValues={themeValues}
313
344
  title={hasTitles ? choice.text : null}
345
+ role="option"
314
346
  >
315
347
  <Text
316
348
  variant="p"
@@ -58,7 +58,7 @@ const FormSelect = ({
58
58
  </Cluster>
59
59
  </Box>
60
60
  <Dropdown
61
- aria-labelledby={labelTextWhenNoError.replace(/\s+/g, "-")}
61
+ ariaLabelledby={labelTextWhenNoError.replace(/\s+/g, "-")}
62
62
  maxHeight={dropdownMaxHeight}
63
63
  hasTitles={hasTitles}
64
64
  placeholder={options[0] ? options[0].text : ""}