@workday/canvas-kit-docs 9.0.0-alpha.419-next.21 → 9.0.0-alpha.420-next.22

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.
@@ -207,6 +207,302 @@ module.exports = {specifications: [
207
207
  }
208
208
  ]
209
209
  },
210
+ {
211
+ "type": "file",
212
+ "name": "Autocomplete.spec.ts",
213
+ "children": [
214
+ {
215
+ "type": "describe",
216
+ "name": "Autocomplete",
217
+ "children": [
218
+ {
219
+ "type": "describe",
220
+ "name": "given the 'Autocomplete' story is rendered",
221
+ "children": [
222
+ {
223
+ "type": "it",
224
+ "name": "should have aria-haspopup set to true"
225
+ },
226
+ {
227
+ "type": "it",
228
+ "name": "should have aria-expanded set to false"
229
+ },
230
+ {
231
+ "type": "it",
232
+ "name": "should not have an aria-activedescendant attribute"
233
+ },
234
+ {
235
+ "type": "it",
236
+ "name": "should have an aria-autocomplete attribute set to \"list\""
237
+ },
238
+ {
239
+ "type": "it",
240
+ "name": "should not set aria-owns"
241
+ },
242
+ {
243
+ "type": "it",
244
+ "name": "should not show menu"
245
+ },
246
+ {
247
+ "type": "it",
248
+ "name": "should not show the clear button"
249
+ },
250
+ {
251
+ "type": "describe",
252
+ "name": "when the combobox is opened",
253
+ "children": [
254
+ {
255
+ "type": "it",
256
+ "name": "should set the aria-owns to reference the listbox element"
257
+ },
258
+ {
259
+ "type": "it",
260
+ "name": "should show menu"
261
+ },
262
+ {
263
+ "type": "it",
264
+ "name": "should not have activedescendant set"
265
+ },
266
+ {
267
+ "type": "it",
268
+ "name": "should not have aria-selected=true on any elements"
269
+ },
270
+ {
271
+ "type": "describe",
272
+ "name": "when the user types a printable character \"b\"",
273
+ "children": [
274
+ {
275
+ "type": "it",
276
+ "name": "should clear activedescendant"
277
+ },
278
+ {
279
+ "type": "it",
280
+ "name": "should not set aria-selected to the first option"
281
+ }
282
+ ]
283
+ },
284
+ {
285
+ "type": "describe",
286
+ "name": "when a value is entered",
287
+ "children": [
288
+ {
289
+ "type": "it",
290
+ "name": "should have the value entered as the value"
291
+ },
292
+ {
293
+ "type": "describe",
294
+ "name": "when escape key is pressed",
295
+ "children": [
296
+ {
297
+ "type": "it",
298
+ "name": "should clear the combobox"
299
+ },
300
+ {
301
+ "type": "it",
302
+ "name": "should close the listbox"
303
+ },
304
+ {
305
+ "type": "it",
306
+ "name": "should keep focus on the combobox"
307
+ },
308
+ {
309
+ "type": "it",
310
+ "name": "should not show the clear button"
311
+ }
312
+ ]
313
+ },
314
+ {
315
+ "type": "describe",
316
+ "name": "when the clear button is clicked",
317
+ "children": [
318
+ {
319
+ "type": "it",
320
+ "name": "should clear the combobox"
321
+ },
322
+ {
323
+ "type": "it",
324
+ "name": "should close the listbox"
325
+ },
326
+ {
327
+ "type": "it",
328
+ "name": "should keep focus on the combobox"
329
+ }
330
+ ]
331
+ },
332
+ {
333
+ "type": "describe",
334
+ "name": "when down arrow key is pressed",
335
+ "children": [
336
+ {
337
+ "type": "it",
338
+ "name": "should have activedecendant set to the first option"
339
+ },
340
+ {
341
+ "type": "it",
342
+ "name": "should set aria-selected to the first option"
343
+ },
344
+ {
345
+ "type": "describe",
346
+ "name": "when the user presses the enter key",
347
+ "children": [
348
+ {
349
+ "type": "it",
350
+ "name": "should set the combobox value to the option text value"
351
+ },
352
+ {
353
+ "type": "it",
354
+ "name": "should close the listbox"
355
+ },
356
+ {
357
+ "type": "describe",
358
+ "name": "when the use hits the \"2\" key",
359
+ "children": [
360
+ {
361
+ "type": "it",
362
+ "name": "should open the listbox"
363
+ },
364
+ {
365
+ "type": "it",
366
+ "name": "should change the combobox value to reflect the key entered"
367
+ },
368
+ {
369
+ "type": "it",
370
+ "name": "should change the filtered results"
371
+ }
372
+ ]
373
+ }
374
+ ]
375
+ },
376
+ {
377
+ "type": "describe",
378
+ "name": "when the user presses metaKey + enter key",
379
+ "children": [
380
+ {
381
+ "type": "it",
382
+ "name": "should not set the combobox value to the option text value"
383
+ },
384
+ {
385
+ "type": "it",
386
+ "name": "should not close the listbox"
387
+ }
388
+ ]
389
+ }
390
+ ]
391
+ },
392
+ {
393
+ "type": "describe",
394
+ "name": "when the user clicks on the first option",
395
+ "children": [
396
+ {
397
+ "type": "it",
398
+ "name": "should set the combobox value to the option text value"
399
+ },
400
+ {
401
+ "type": "it",
402
+ "name": "should close the listbox"
403
+ },
404
+ {
405
+ "type": "it",
406
+ "name": "should keep focus on combobox"
407
+ },
408
+ {
409
+ "type": "describe",
410
+ "name": "when the user clicks on the combobox",
411
+ "children": [
412
+ {
413
+ "type": "it",
414
+ "name": "should open the listbox again"
415
+ }
416
+ ]
417
+ }
418
+ ]
419
+ },
420
+ {
421
+ "type": "describe",
422
+ "name": "when down arrow key is pressed two times",
423
+ "children": [
424
+ {
425
+ "type": "it",
426
+ "name": "should have activedecendant set to the second option"
427
+ },
428
+ {
429
+ "type": "it",
430
+ "name": "should set aria-selected to the second option"
431
+ }
432
+ ]
433
+ },
434
+ {
435
+ "type": "describe",
436
+ "name": "when the value is \"Red Apple 1\"",
437
+ "children": [
438
+ {
439
+ "type": "describe",
440
+ "name": "when the value is \"Red Apple 1\" and down arrow key is pressed six times",
441
+ "children": [
442
+ {
443
+ "type": "it",
444
+ "name": "should have activedecendant set to the first option"
445
+ },
446
+ {
447
+ "type": "it",
448
+ "name": "should set aria-selected to the first option"
449
+ }
450
+ ]
451
+ },
452
+ {
453
+ "type": "describe",
454
+ "name": "when up arrow key is pressed",
455
+ "children": [
456
+ {
457
+ "type": "it",
458
+ "name": "should have activedecendant set to the last option"
459
+ },
460
+ {
461
+ "type": "it",
462
+ "name": "should set aria-selected to the last option"
463
+ }
464
+ ]
465
+ },
466
+ {
467
+ "type": "describe",
468
+ "name": "when up arrow key is pressed two times",
469
+ "children": [
470
+ {
471
+ "type": "it",
472
+ "name": "should have activedecendant set to the third option"
473
+ },
474
+ {
475
+ "type": "it",
476
+ "name": "should set aria-selected to the third option"
477
+ }
478
+ ]
479
+ },
480
+ {
481
+ "type": "describe",
482
+ "name": "when up arrow key is pressed four times",
483
+ "children": [
484
+ {
485
+ "type": "it",
486
+ "name": "should have activedecendant set to the first option"
487
+ },
488
+ {
489
+ "type": "it",
490
+ "name": "should set aria-selected to the first option"
491
+ }
492
+ ]
493
+ }
494
+ ]
495
+ }
496
+ ]
497
+ }
498
+ ]
499
+ }
500
+ ]
501
+ }
502
+ ]
503
+ }
504
+ ]
505
+ },
210
506
  {
211
507
  "type": "file",
212
508
  "name": "Avatar.spec.ts",
@@ -55,7 +55,7 @@ registerWidget('enhancedComponent', ({ value, doc, meta }) => {
55
55
  value.styleComponent ? (React.createElement(React.Fragment, null,
56
56
  React.createElement(Heading, { headingOffset: 1 }, "Layout Component"),
57
57
  React.createElement(MDX, { as: "p" },
58
- React.createElement("code", null, value.displayName),
58
+ React.createElement("code", null, value.displayName || parentComponentName),
59
59
  " supports all props from the",
60
60
  React.createElement("code", null,
61
61
  React.createElement(ParentComponentJSDocContext.Provider, { value: defaultJSDoc },
@@ -67,9 +67,9 @@ The collection system comes with a data loader to help with dynamic collections.
67
67
  when the user navigates the collection and needs more data. This example shows how to hook up a
68
68
  simple data loader and mocks a `load` function to simulate an asynchronous response.
69
69
 
70
- The data loader also takes a model argument to know which model to create. The loader configures
71
- the model to handle asynchronous keyboard navigation and will return the configured model to you
72
- to pass along to the collection component.
70
+ The data loader also takes a model argument to know which model to create. The loader configures the
71
+ model to handle asynchronous keyboard navigation and will return the configured model to you to pass
72
+ along to the collection component.
73
73
 
74
74
  <ExampleCodeBlock code={DataLoader} />
75
75
 
@@ -106,9 +106,9 @@ uses `ListBox` and creates a custom `SelectableItem` elemProps hook and componen
106
106
 
107
107
  Sometimes it is desired to allow the string children to be the identifiers for each item. This could
108
108
  be useful for autocomplete components where the item's text is the desired identifier. Normally, if
109
- no `data-id` is provided to the item, the system will choose the registration index. This would be `'0'`, `'1'`, and so on.
110
- By passing `useListItemAllowChildStrings` to an item component, it will change this behavior to use the child text if no
111
- `data-id` is provided.
109
+ no `data-id` is provided to the item, the system will choose the registration index. This would be
110
+ `'0'`, `'1'`, and so on. By passing `useListItemAllowChildStrings` to an item component, it will
111
+ change this behavior to use the child text if no `data-id` is provided.
112
112
 
113
113
  <ExampleCodeBlock code={StringChildren} />
114
114
 
@@ -141,10 +141,8 @@ cursor wraps around columns and rows when an edge of a column or row is encounte
141
141
 
142
142
  ### ListBox
143
143
 
144
- <>
145
144
  <SymbolDoc name="ListBox" fileName="/react/" />
146
145
  <SymbolDoc name="useGridModel" fileName="/react/" />
147
- </>
148
146
 
149
147
  ### Navigation Manager
150
148
 
@@ -168,7 +166,6 @@ columns, but not rows. This is the default navigation manager for lists.
168
166
 
169
167
  ## Hooks
170
168
 
171
- <>
172
169
  <SymbolDoc name="useListItemRegister" fileName="/react/" />
173
170
  <SymbolDoc name="useListItemAllowChildStrings" fileName="/react/" />
174
171
  <SymbolDoc name="useListItemRovingFocus" fileName="/react/" />
@@ -178,5 +175,4 @@ columns, but not rows. This is the default navigation manager for lists.
178
175
  <SymbolDoc name="useOverflowListItemMeasure" fileName="/react/" />
179
176
  <SymbolDoc name="useOverflowListMeasure" fileName="/react/" />
180
177
  <SymbolDoc name="useOverflowListTarget" fileName="/react/" />
181
- <SymbolDoc name="useListLoader" fileName="/react/" />
182
- </>
178
+ <SymbolDoc name="useListLoader" fileName="/react/" />
@@ -0,0 +1,47 @@
1
+ import {SymbolDoc, Specifications} from '@workday/canvas-kit-docs';
2
+
3
+ import {Combobox} from '@workday/canvas-kit-react/combobox';
4
+ import Autocomplete from './examples/Autocomplete';
5
+
6
+
7
+ # Combobox
8
+
9
+ Combobox is an _abstract_ compound component - it should not be used on its own, but used as a base
10
+ to create combobox components. The Combobox system provides components, models, loaders, and
11
+ elemProps hooks.
12
+
13
+ The term "Combobox" is based on the
14
+ [Combobox Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) as defined in the ARIA
15
+ Authoring Practices Guide (APG):
16
+
17
+ > A [combobox](https://w3c.github.io/aria/#combobox) is an input widget with an associated popup
18
+ > that enables users to select a value for the combobox from a collection of possible values.
19
+
20
+ Examples of a "combobox" would be date pickers, autocomplete, and select components.
21
+
22
+ ## Installation
23
+
24
+ ```sh
25
+ yarn add @workday/canvas-kit-react
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ### Autocomplete
31
+
32
+ This example shows an Autocomplete example using `FormField`, `InputGroup`, and the `Combobox`
33
+ components to make an autocomplete form field. It uses `useComboboxLoader` to make mock API calls
34
+ using `setTimeout`. Your application may use
35
+ [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API),
36
+ [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API), or other means of
37
+ communicating with a server.
38
+
39
+ <ExampleCodeBlock code={Autocomplete} />
40
+
41
+ ## Component API
42
+
43
+ <SymbolDoc name="Combobox" fileName="/react/" hideDescription />
44
+
45
+ ## Hooks
46
+
47
+ <SymbolDoc name="useComboboxLoader" fileName="/react/" />
@@ -0,0 +1,125 @@
1
+ import React from 'react';
2
+
3
+ import {
4
+ createElemPropsHook,
5
+ createSubcomponent,
6
+ composeHooks,
7
+ ExtractProps,
8
+ } from '@workday/canvas-kit-react/common';
9
+ import {LoadReturn} from '@workday/canvas-kit-react/collection';
10
+ import {
11
+ Combobox,
12
+ useComboboxModel,
13
+ useComboboxLoader,
14
+ useComboboxInput,
15
+ } from '@workday/canvas-kit-react/combobox';
16
+ import {FormField} from '@workday/canvas-kit-preview-react/form-field';
17
+ import {StyledMenuItem} from '@workday/canvas-kit-react/menu';
18
+ import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
19
+ import {InputGroup, TextInput} from '@workday/canvas-kit-react/text-input';
20
+
21
+ const colors = ['Red', 'Blue', 'Purple', 'Green', 'Pink'];
22
+ const fruits = ['Apple', 'Orange', 'Banana', 'Grape', 'Lemon', 'Lime'];
23
+ const options = Array(1000)
24
+ .fill('')
25
+ .map((_, index) => {
26
+ return `${colors[index % colors.length]} ${fruits[index % fruits.length]} ${index + 1}`;
27
+ });
28
+
29
+ const useAutocompleteInput = composeHooks(
30
+ createElemPropsHook(useComboboxModel)(model => {
31
+ console.log('model', model);
32
+ return {
33
+ onKeyPress(event: React.KeyboardEvent) {
34
+ model.events.show(event);
35
+ },
36
+ };
37
+ }),
38
+ useComboboxInput
39
+ );
40
+
41
+ const AutoCompleteInput = createSubcomponent(TextInput)({
42
+ modelHook: useComboboxModel,
43
+ elemPropsHook: useAutocompleteInput,
44
+ })<ExtractProps<typeof Combobox.Input, never>>((elemProps, Element) => {
45
+ return <Combobox.Input as={Element} {...elemProps} />;
46
+ });
47
+
48
+ export default () => {
49
+ const {model, loader} = useComboboxLoader(
50
+ {
51
+ // You can start with any number that makes sense.
52
+ total: 0,
53
+
54
+ // Pick whatever number makes sense for your API
55
+ pageSize: 20,
56
+
57
+ // A load function that will be called by the loader. You must return a promise that returns
58
+ // an object like `{items: [], total: 0}`. The `items` will be merged into the loader's cache
59
+ async load({pageNumber, pageSize, filter}) {
60
+ return new Promise<LoadReturn<string>>(resolve => {
61
+ // simulate a server response by resolving after a period of time
62
+ setTimeout(() => {
63
+ // simulate paging and filtering based on pre-computed items
64
+ const start = (pageNumber - 1) * pageSize;
65
+ const end = start + pageSize;
66
+ const filteredItems = options.filter(item => {
67
+ if (filter === '' || typeof filter !== 'string') {
68
+ return true;
69
+ }
70
+ return item.toLowerCase().includes(filter.toLowerCase());
71
+ });
72
+
73
+ const total = filteredItems.length;
74
+ const items = filteredItems.slice(start, end);
75
+
76
+ resolve({
77
+ items,
78
+ total,
79
+ });
80
+ }, 300);
81
+ });
82
+ },
83
+ onShow() {
84
+ // The `shouldLoad` cancels while the combobox menu is hidden, so let's load when it is
85
+ // visible
86
+ loader.load();
87
+ },
88
+ },
89
+ useComboboxModel
90
+ );
91
+
92
+ return (
93
+ <FormField orientation="horizontal" hasError isRequired>
94
+ <FormField.Label>Fruit</FormField.Label>
95
+ <Combobox model={model} onChange={event => console.log('input', event.currentTarget.value)}>
96
+ <InputGroup>
97
+ <InputGroup.Input as={FormField.Input.as(AutoCompleteInput)} />
98
+ <InputGroup.InnerEnd
99
+ pointerEvents="none"
100
+ style={{opacity: loader.isLoading ? 1 : 0, transition: 'opacity 100ms ease'}}
101
+ width={20}
102
+ data-loading={loader.isLoading}
103
+ >
104
+ <LoadingDots style={{display: 'flex', transform: 'scale(0.3)'}} />
105
+ </InputGroup.InnerEnd>
106
+ <InputGroup.InnerEnd>
107
+ <InputGroup.ClearButton data-testid="clear" />
108
+ </InputGroup.InnerEnd>
109
+ </InputGroup>
110
+ <Combobox.Menu.Popper>
111
+ <Combobox.Menu.Card>
112
+ {model.state.items.length === 0 && (
113
+ <StyledMenuItem as="span">No Results Found</StyledMenuItem>
114
+ )}
115
+ {model.state.items.length > 0 && (
116
+ <Combobox.Menu.List maxHeight={200}>
117
+ {item => <Combobox.Menu.Item>{item}</Combobox.Menu.Item>}
118
+ </Combobox.Menu.List>
119
+ )}
120
+ </Combobox.Menu.Card>
121
+ </Combobox.Menu.Popper>
122
+ </Combobox>
123
+ </FormField>
124
+ );
125
+ };
@@ -49,6 +49,13 @@ using roving tabindex. Below is table of supported keyboard shortcuts and associ
49
49
 
50
50
  ### Icons
51
51
 
52
+ Menu supports more complex children, including icons, but the text of the item will no longer be
53
+ known. In this case, add a `data-text` attribute to inform the collection system what the text of
54
+ the item is. The text is used for components that filter based on text. For example, a Select
55
+ component will jump to an item based on the keys the user types. If the user types "C", the
56
+ component will jump to the first item that starts with a "C". This functionality requires knowledge
57
+ about the text of the item.
58
+
52
59
  <ExampleCodeBlock code={Icons} />
53
60
 
54
61
  ## Component API
@@ -16,25 +16,25 @@ export default () => {
16
16
  <Menu.Popper>
17
17
  <Menu.Card>
18
18
  <Menu.List>
19
- <Menu.Item>
19
+ <Menu.Item data-text="First Item">
20
20
  <Menu.Item.Icon icon={uploadCloudIcon} />
21
21
  <Menu.Item.Text>First Item</Menu.Item.Text>
22
22
  </Menu.Item>
23
- <Menu.Item>
23
+ <Menu.Item data-text="Second Item (with a really really really long label)">
24
24
  <Menu.Item.Icon icon={setupIcon} />
25
25
  <Menu.Item.Text>Second Item (with a really really really long label)</Menu.Item.Text>
26
26
  </Menu.Item>
27
- <Menu.Item aria-disabled>
27
+ <Menu.Item aria-disabled data-text="Third Item">
28
28
  <Menu.Item.Icon icon={uploadCloudIcon} />
29
29
  <Menu.Item.Text>Third Item</Menu.Item.Text>
30
30
  <Menu.Item.Icon icon={taskContactIcon} />
31
31
  </Menu.Item>
32
- <Menu.Item>
32
+ <Menu.Item data-text="User">
33
33
  <Menu.Item.Icon icon={userIcon} />
34
34
  <Menu.Item.Text></Menu.Item.Text>
35
35
  </Menu.Item>
36
36
  <Menu.Divider />
37
- <Menu.Item>
37
+ <Menu.Item data-text="Fifth Item (with divider)">
38
38
  <Menu.Item.Icon icon={taskContactIcon} />
39
39
  <Menu.Item.Text>Fifth Item (with divider)</Menu.Item.Text>
40
40
  </Menu.Item>
@@ -70,7 +70,7 @@ registerWidget<EnhancedComponentValue>('enhancedComponent', ({value, doc, meta})
70
70
  <>
71
71
  <Heading headingOffset={1}>Layout Component</Heading>
72
72
  <MDX as="p">
73
- <code>{value.displayName}</code> supports all props from the
73
+ <code>{value.displayName || parentComponentName}</code> supports all props from the
74
74
  <code>
75
75
  <ParentComponentJSDocContext.Provider value={defaultJSDoc}>
76
76
  <SymbolDialog value={value.styleComponent} />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workday/canvas-kit-docs",
3
- "version": "9.0.0-alpha.419-next.21+2436a0cd",
3
+ "version": "9.0.0-alpha.420-next.22+87587db5",
4
4
  "description": "Documentation components of Canvas Kit components",
5
5
  "author": "Workday, Inc. (https://www.workday.com)",
6
6
  "license": "Apache-2.0",
@@ -44,9 +44,9 @@
44
44
  "dependencies": {
45
45
  "@emotion/styled": "^11.6.0",
46
46
  "@storybook/csf": "0.0.1",
47
- "@workday/canvas-kit-labs-react": "^9.0.0-alpha.419-next.21+2436a0cd",
48
- "@workday/canvas-kit-preview-react": "^9.0.0-alpha.419-next.21+2436a0cd",
49
- "@workday/canvas-kit-react": "^9.0.0-alpha.419-next.21+2436a0cd",
47
+ "@workday/canvas-kit-labs-react": "^9.0.0-alpha.420-next.22+87587db5",
48
+ "@workday/canvas-kit-preview-react": "^9.0.0-alpha.420-next.22+87587db5",
49
+ "@workday/canvas-kit-react": "^9.0.0-alpha.420-next.22+87587db5",
50
50
  "@workday/canvas-system-icons-web": "^3.0.0",
51
51
  "markdown-to-jsx": "^6.10.3",
52
52
  "ts-node": "^10.9.1"
@@ -57,5 +57,5 @@
57
57
  "mkdirp": "^1.0.3",
58
58
  "typescript": "4.2"
59
59
  },
60
- "gitHead": "2436a0cd3dc23fd2d4f6350af6f76a9591f83e30"
60
+ "gitHead": "87587db5b8bc197a9b1a544d8851b884848647e9"
61
61
  }