@workday/canvas-kit-docs 12.0.0-alpha.918-next.0 → 12.0.0-alpha.919-next.0
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/dist/es6/lib/docs.js +9890 -308
- package/dist/mdx/12.0-UPGRADE-GUIDE.mdx +18 -3
- package/dist/mdx/preview-react/multi-select/MultiSelect.mdx +98 -0
- package/dist/mdx/preview-react/multi-select/examples/Basic.tsx +30 -0
- package/dist/mdx/preview-react/multi-select/examples/Complex.tsx +75 -0
- package/dist/mdx/preview-react/multi-select/examples/Controlled.tsx +92 -0
- package/dist/mdx/preview-react/multi-select/examples/Icons.tsx +43 -0
- package/dist/mdx/preview-react/multi-select/examples/Searching.tsx +123 -0
- package/dist/mdx/react/action-bar/examples/OverflowActionBar.tsx +1 -0
- package/dist/mdx/react/button/button/Button.mdx +3 -2
- package/dist/mdx/react/combobox/Combobox.mdx +4 -1
- package/package.json +6 -6
|
@@ -43,16 +43,17 @@ A note to the reader:
|
|
|
43
43
|
- [Component Updates](#component-updates)
|
|
44
44
|
- [Styling API and CSS Tokens](#styling-api-and-css-tokens)
|
|
45
45
|
- [Avatar](#avatar)
|
|
46
|
+
- [Collections](#collections)
|
|
46
47
|
- [Combobox](#combmbox)
|
|
47
48
|
- [Form Field](#form-field)
|
|
48
49
|
- [Form Field Group](#form-field-group)
|
|
49
50
|
- [Form Field Field](#form-field-field)
|
|
50
51
|
- [Menu Item](#menu-item)
|
|
52
|
+
- [MultiSelect](#multiselect)
|
|
51
53
|
- [Search Form](#search-form)
|
|
52
54
|
- [Select](#select)
|
|
53
55
|
- [Text Area](#text-area)
|
|
54
56
|
- [Text Input](#text-input)
|
|
55
|
-
- [Collections](#collections)
|
|
56
57
|
- [Utility Updates](#utility-updates)
|
|
57
58
|
- [Troubleshooting](#troubleshooting)
|
|
58
59
|
- [Glossary](#glossary)
|
|
@@ -487,9 +488,9 @@ this sub-component when using `FormField`. This component also exists on `FormFi
|
|
|
487
488
|
|
|
488
489
|
### Menu Item
|
|
489
490
|
|
|
490
|
-
**PR
|
|
491
|
+
**PR:** [2969](https://github.com/Workday/canvas-kit/pull/2969)
|
|
491
492
|
|
|
492
|
-
`Menu.Item` was converted to use Stencils for styling and uses SystemIcon stencil variables to
|
|
493
|
+
`Menu.Item` was converted to use Stencils for styling and uses `SystemIcon` stencil variables to
|
|
493
494
|
change icon color instead of deeply nested selectors. We also added `Menu.Option` component for
|
|
494
495
|
menus that have a selected visual state. `Menu.Option` will need more accessibility affordances that
|
|
495
496
|
depend on the nature of your use of the `Menu` component. For example, `<Combobox>` and `<Select>`
|
|
@@ -505,6 +506,20 @@ We've removed the `MenuItemProps` export from `@workday/canvas-kit-react/menu`.
|
|
|
505
506
|
polymorphic components. The `never` means "don't add element props". The second parameter is used to
|
|
506
507
|
pass the interface that the `as` prop is pointing to.
|
|
507
508
|
|
|
509
|
+
`Menu.Item` no longer sets `aria-selected` since that attribute is not valid on a `role=menuitem`.
|
|
510
|
+
The `Menu.Option` was added to support the role of a `role=option` for going inside a
|
|
511
|
+
`role=listbox`. The `Combobox` family of components uses a `role=listbox` for menu options. The
|
|
512
|
+
`Menu.Option` renders a checkmark for a visual indication of selected options.
|
|
513
|
+
|
|
514
|
+
### MultiSelect
|
|
515
|
+
|
|
516
|
+
**PR:** [2911](https://github.com/Workday/canvas-kit/pull/2911)
|
|
517
|
+
|
|
518
|
+
Added the `MultiSelect` component to select more than one option from a list of options. The
|
|
519
|
+
`MultiSelect` is similar in API to the `Select` component, except the values are comma delimited
|
|
520
|
+
with a space. If the ids represented are `['1', '2']`, then the string value of the form field is
|
|
521
|
+
`'1, 2'`.
|
|
522
|
+
|
|
508
523
|
### Search Form (Labs)
|
|
509
524
|
|
|
510
525
|
**PRs:** [#2934](https://github.com/Workday/canvas-kit/pull/2934),
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExampleCodeBlock,
|
|
3
|
+
InformationHighlight,
|
|
4
|
+
SymbolDoc,
|
|
5
|
+
Specifications,
|
|
6
|
+
} from '@workday/canvas-kit-docs';
|
|
7
|
+
|
|
8
|
+
import Basic from './examples/Basic';
|
|
9
|
+
import Complex from './examples/Complex';
|
|
10
|
+
import Icons from './examples/Icons';
|
|
11
|
+
import Controlled from './examples/Controlled';
|
|
12
|
+
import Searching from './examples/Searching';
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Canvas Kit MultiSelect
|
|
16
|
+
|
|
17
|
+
MultiSelect inputs allow users to choose multiple options from a list of items.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
yarn add @workday/canvas-kit-preview-react
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Basic Example
|
|
28
|
+
|
|
29
|
+
`MultiSelect` supports a
|
|
30
|
+
[dynamic API](/getting-started/for-developers/resources/collection-api/#dynamic-items) where you
|
|
31
|
+
pass an array of items via the `items` prop and provide a render function to display the items. The
|
|
32
|
+
items may be provided as an
|
|
33
|
+
[array of strings](/getting-started/for-developers/resources/collection-api/#array-of-strings) or an
|
|
34
|
+
[array of objects](/getting-started/for-developers/resources/collection-api/#array-of-objects).
|
|
35
|
+
|
|
36
|
+
`MultiSelect` should be used in tandem with [Form Field](/components/inputs/form-field/) where the
|
|
37
|
+
`MultiSelect` wraps the `FormField` element and the `FormField` element wraps the children of
|
|
38
|
+
`MultiSelect` to meet accessibility standards. This ensures the `label` text from `FormField` is
|
|
39
|
+
attached to the `MultiSelect.Input` and read out as a group for voiceover.
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
<MultiSelect items={options}>
|
|
43
|
+
<FormField label="Your Label">
|
|
44
|
+
<MultiSelect.Input onChange={e => handleChange(e)} id="contact-multi-select" />
|
|
45
|
+
<MultiSelect.Popper>
|
|
46
|
+
<MultiSelect.Card>
|
|
47
|
+
<MultiSelect.List>
|
|
48
|
+
{item => <MultiSelect.Item>{item.id}</MultiSelect.Item>}
|
|
49
|
+
</MultiSelect.List>
|
|
50
|
+
</MultiSelect.Card>
|
|
51
|
+
</MultiSelect.Popper>
|
|
52
|
+
</FormField>
|
|
53
|
+
</MultiSelect>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
<ExampleCodeBlock code={Basic} />
|
|
57
|
+
|
|
58
|
+
### Complex
|
|
59
|
+
|
|
60
|
+
When registering items in an array of objects, it's common to have the text that is displayed to the
|
|
61
|
+
user be different than an id. In this example, `serverId` and `label` properties need to be remapped
|
|
62
|
+
to `id` and `text` hence the usage of `getId` and `getTextValue`. If your object has the properties
|
|
63
|
+
`text` and `id`, there would be no need for this.
|
|
64
|
+
|
|
65
|
+
<ExampleCodeBlock code={Complex} />
|
|
66
|
+
|
|
67
|
+
### With Icons
|
|
68
|
+
|
|
69
|
+
Use `MultiSelect.Item.Icon` to render an icon for a `MultiSelect.Item`. The `icon` prop for
|
|
70
|
+
`MultiSelect.Item.Icon` accepts [system icons](/assets/system-icons/) from
|
|
71
|
+
`@workday/canvas-system-icons-web`.
|
|
72
|
+
|
|
73
|
+
> **Note: `data-id` on `MultiSelect.Item` must match the `id` property in your array of objects.
|
|
74
|
+
> This ensures proper keyboard handling and type-ahead.**
|
|
75
|
+
|
|
76
|
+
<ExampleCodeBlock code={Icons} />
|
|
77
|
+
|
|
78
|
+
### Controlled
|
|
79
|
+
|
|
80
|
+
The MultiSelect can be a controlled input component by passing the `value` and `onChange` to either
|
|
81
|
+
the `<MultiSelect>` component or the `<MultiSelect.Input>` component. Internally, the
|
|
82
|
+
`MultiSelect.Input` watches for changes on the `value` React prop as well as the `value` DOM
|
|
83
|
+
property and will update the model accordingly.
|
|
84
|
+
|
|
85
|
+
<ExampleCodeBlock code={Controlled} />
|
|
86
|
+
|
|
87
|
+
### Searching
|
|
88
|
+
|
|
89
|
+
A MultiSelect input can be used as a filter for results. Most likely this also means there are many
|
|
90
|
+
items that may not be all be loaded from the server at once. The `useComboboxLoader` can be used to
|
|
91
|
+
dynamically load items as the user navigates the available options.
|
|
92
|
+
|
|
93
|
+
> **Note:** The behavior of search is experimental. The example should continue to work without
|
|
94
|
+
> modification, but how the searchable input is presented to the user may change with user testing.
|
|
95
|
+
> Don't rely too much on the exact behavior of the search input. For example, the search input may
|
|
96
|
+
> be cleared when the user blurs the field.
|
|
97
|
+
|
|
98
|
+
<ExampleCodeBlock code={Searching} />
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {FormField} from '@workday/canvas-kit-react/form-field';
|
|
4
|
+
import {MultiSelect} from '@workday/canvas-kit-preview-react/multi-select';
|
|
5
|
+
|
|
6
|
+
const items = ['Cheese', 'Olives', 'Onions', 'Pepperoni', 'Peppers'];
|
|
7
|
+
|
|
8
|
+
export default () => {
|
|
9
|
+
return (
|
|
10
|
+
<>
|
|
11
|
+
<MultiSelect items={items}>
|
|
12
|
+
<FormField orientation="horizontal">
|
|
13
|
+
<FormField.Label>Toppings</FormField.Label>
|
|
14
|
+
<FormField.Input as={MultiSelect.Input} placeholder="Select Multiple" />
|
|
15
|
+
<MultiSelect.Popper>
|
|
16
|
+
<MultiSelect.Card>
|
|
17
|
+
<MultiSelect.List>
|
|
18
|
+
{item => (
|
|
19
|
+
<MultiSelect.Item data-id={item}>
|
|
20
|
+
<MultiSelect.Item.Text>{item}</MultiSelect.Item.Text>
|
|
21
|
+
</MultiSelect.Item>
|
|
22
|
+
)}
|
|
23
|
+
</MultiSelect.List>
|
|
24
|
+
</MultiSelect.Card>
|
|
25
|
+
</MultiSelect.Popper>
|
|
26
|
+
</FormField>
|
|
27
|
+
</MultiSelect>
|
|
28
|
+
</>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {CanvasProvider} from '@workday/canvas-kit-react/common';
|
|
4
|
+
import {createStyles} from '@workday/canvas-kit-styling';
|
|
5
|
+
import {FormField} from '@workday/canvas-kit-react/form-field';
|
|
6
|
+
|
|
7
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
8
|
+
|
|
9
|
+
import {MultiSelect} from '@workday/canvas-kit-preview-react/multi-select';
|
|
10
|
+
|
|
11
|
+
const mainContentStyles = createStyles({
|
|
12
|
+
padding: system.space.x4,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const items = [
|
|
16
|
+
{id: '1', text: 'Cheese'},
|
|
17
|
+
{id: '2', text: 'Olives'},
|
|
18
|
+
{id: '3', text: 'Onions'},
|
|
19
|
+
{id: '4', text: 'Pepperoni'},
|
|
20
|
+
{id: '5', text: 'Peppers'},
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
export default () => {
|
|
24
|
+
const [value, setValue] = React.useState('');
|
|
25
|
+
const [label, setLabel] = React.useState('');
|
|
26
|
+
return (
|
|
27
|
+
<CanvasProvider>
|
|
28
|
+
<>
|
|
29
|
+
<form
|
|
30
|
+
onSubmit={e => {
|
|
31
|
+
console.log('form submitted');
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
<main className={mainContentStyles}>
|
|
36
|
+
<MultiSelect items={items} getId={i => i.id} getTextValue={i => i.text}>
|
|
37
|
+
<FormField orientation="horizontal">
|
|
38
|
+
<FormField.Label>Toppings</FormField.Label>
|
|
39
|
+
<FormField.Input
|
|
40
|
+
as={MultiSelect.Input}
|
|
41
|
+
placeholder="Select Multiple"
|
|
42
|
+
name="toppings"
|
|
43
|
+
onChange={e => {
|
|
44
|
+
const value = e.currentTarget.value;
|
|
45
|
+
setValue(value);
|
|
46
|
+
setLabel(
|
|
47
|
+
value
|
|
48
|
+
.split(', ')
|
|
49
|
+
.map(item => items.find(i => i.id === item)?.text || 'Not Found')
|
|
50
|
+
.join(', ')
|
|
51
|
+
);
|
|
52
|
+
}}
|
|
53
|
+
value={value}
|
|
54
|
+
/>
|
|
55
|
+
<MultiSelect.Popper>
|
|
56
|
+
<MultiSelect.Card>
|
|
57
|
+
<MultiSelect.List>
|
|
58
|
+
{item => (
|
|
59
|
+
<MultiSelect.Item data-id={item.id}>
|
|
60
|
+
<MultiSelect.Item.Text>{item.text}</MultiSelect.Item.Text>
|
|
61
|
+
</MultiSelect.Item>
|
|
62
|
+
)}
|
|
63
|
+
</MultiSelect.List>
|
|
64
|
+
</MultiSelect.Card>
|
|
65
|
+
</MultiSelect.Popper>
|
|
66
|
+
</FormField>
|
|
67
|
+
</MultiSelect>
|
|
68
|
+
</main>
|
|
69
|
+
</form>
|
|
70
|
+
<div>Selected IDs: {value}</div>
|
|
71
|
+
<div>Selected Labels: {label}</div>
|
|
72
|
+
</>
|
|
73
|
+
</CanvasProvider>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {FormField} from '@workday/canvas-kit-react/form-field';
|
|
4
|
+
import {PrimaryButton, SecondaryButton} from '@workday/canvas-kit-react/button';
|
|
5
|
+
import {Flex} from '@workday/canvas-kit-react/layout';
|
|
6
|
+
|
|
7
|
+
import {MultiSelect} from '@workday/canvas-kit-preview-react/multi-select';
|
|
8
|
+
|
|
9
|
+
const items = [
|
|
10
|
+
{id: '1', text: 'Cheese'},
|
|
11
|
+
{id: '2', text: 'Olives'},
|
|
12
|
+
{id: '3', text: 'Onions'},
|
|
13
|
+
{id: '4', text: 'Pepperoni'},
|
|
14
|
+
{id: '5', text: 'Peppers'},
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
export default () => {
|
|
18
|
+
const formRef = React.useRef<HTMLFormElement>(null);
|
|
19
|
+
const [value, setValue] = React.useState('1');
|
|
20
|
+
const [label, setLabel] = React.useState('Cheese');
|
|
21
|
+
|
|
22
|
+
function handleOnChange(event: React.ChangeEvent<HTMLInputElement>) {
|
|
23
|
+
const value = event.currentTarget.value;
|
|
24
|
+
setValue(value);
|
|
25
|
+
setLabel(
|
|
26
|
+
value
|
|
27
|
+
.split(', ')
|
|
28
|
+
.map(item => items.find(i => i.id === item)?.text || 'Not Found')
|
|
29
|
+
.join(', ')
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<>
|
|
35
|
+
<form
|
|
36
|
+
onSubmit={e => {
|
|
37
|
+
console.log('form submitted');
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
}}
|
|
40
|
+
ref={formRef}
|
|
41
|
+
>
|
|
42
|
+
<Flex gap="s" flexDirection="column">
|
|
43
|
+
<MultiSelect items={items}>
|
|
44
|
+
<FormField orientation="horizontal">
|
|
45
|
+
<FormField.Label>Toppings</FormField.Label>
|
|
46
|
+
<FormField.Input
|
|
47
|
+
as={MultiSelect.Input}
|
|
48
|
+
placeholder="Select Multiple"
|
|
49
|
+
name="toppings"
|
|
50
|
+
onChange={handleOnChange}
|
|
51
|
+
value={value}
|
|
52
|
+
/>
|
|
53
|
+
<MultiSelect.Popper>
|
|
54
|
+
<MultiSelect.Card>
|
|
55
|
+
<MultiSelect.List>
|
|
56
|
+
{item => (
|
|
57
|
+
<MultiSelect.Item data-id={item.id}>
|
|
58
|
+
<MultiSelect.Item.Text>{item.text}</MultiSelect.Item.Text>
|
|
59
|
+
</MultiSelect.Item>
|
|
60
|
+
)}
|
|
61
|
+
</MultiSelect.List>
|
|
62
|
+
</MultiSelect.Card>
|
|
63
|
+
</MultiSelect.Popper>
|
|
64
|
+
</FormField>
|
|
65
|
+
</MultiSelect>
|
|
66
|
+
<Flex gap="s">
|
|
67
|
+
<SecondaryButton
|
|
68
|
+
onClick={e => {
|
|
69
|
+
setValue('1, 2, 3');
|
|
70
|
+
}}
|
|
71
|
+
>
|
|
72
|
+
Set to "Cheese, Olives, Onions" via React `value`
|
|
73
|
+
</SecondaryButton>
|
|
74
|
+
<SecondaryButton
|
|
75
|
+
onClick={e => {
|
|
76
|
+
const input = formRef.current.querySelector('[name=toppings]') as HTMLInputElement;
|
|
77
|
+
input.value = '1, 2';
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
Set to "Cheese, Olives" via DOM `value`
|
|
81
|
+
</SecondaryButton>
|
|
82
|
+
</Flex>
|
|
83
|
+
<div>
|
|
84
|
+
<PrimaryButton type="submit">Submit</PrimaryButton>
|
|
85
|
+
</div>
|
|
86
|
+
<div>Selected ID: {value}</div>
|
|
87
|
+
<div>Selected Label: {label}</div>
|
|
88
|
+
</Flex>
|
|
89
|
+
</form>
|
|
90
|
+
</>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {FormField} from '@workday/canvas-kit-react/form-field';
|
|
4
|
+
import {
|
|
5
|
+
mediaPauseIcon,
|
|
6
|
+
mediaPlayIcon,
|
|
7
|
+
mediaTopicsIcon,
|
|
8
|
+
skipIcon,
|
|
9
|
+
previousIcon,
|
|
10
|
+
} from '@workday/canvas-system-icons-web';
|
|
11
|
+
|
|
12
|
+
import {MultiSelect} from '@workday/canvas-kit-preview-react/multi-select';
|
|
13
|
+
|
|
14
|
+
const items = [
|
|
15
|
+
{id: '1', text: 'Pause', icon: mediaPauseIcon},
|
|
16
|
+
{id: '2', text: 'Play', icon: mediaPlayIcon},
|
|
17
|
+
{id: '3', text: 'Skip', icon: skipIcon},
|
|
18
|
+
{id: '4', text: 'Previous', icon: previousIcon},
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
export default () => {
|
|
22
|
+
return (
|
|
23
|
+
<MultiSelect items={items}>
|
|
24
|
+
<FormField orientation="horizontal">
|
|
25
|
+
<FormField.Label>Controls</FormField.Label>
|
|
26
|
+
<FormField.Input as={MultiSelect.Input} placeholder="Select Multiple" />
|
|
27
|
+
<MultiSelect.Popper>
|
|
28
|
+
<MultiSelect.Card>
|
|
29
|
+
<MultiSelect.List>
|
|
30
|
+
{item => (
|
|
31
|
+
<MultiSelect.Item data-id={item.id}>
|
|
32
|
+
<MultiSelect.Item.Icon icon={item.icon} />
|
|
33
|
+
<MultiSelect.Item.Text>{item.text}</MultiSelect.Item.Text>
|
|
34
|
+
<MultiSelect.Item.Icon icon={mediaTopicsIcon} />
|
|
35
|
+
</MultiSelect.Item>
|
|
36
|
+
)}
|
|
37
|
+
</MultiSelect.List>
|
|
38
|
+
</MultiSelect.Card>
|
|
39
|
+
</MultiSelect.Popper>
|
|
40
|
+
</FormField>
|
|
41
|
+
</MultiSelect>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
|
|
5
|
+
import {createStyles} from '@workday/canvas-kit-styling';
|
|
6
|
+
import {LoadReturn} from '@workday/canvas-kit-react/collection';
|
|
7
|
+
import {CanvasProvider} from '@workday/canvas-kit-react/common';
|
|
8
|
+
import {useComboboxLoader} from '@workday/canvas-kit-react/combobox';
|
|
9
|
+
import {FormField} from '@workday/canvas-kit-react/form-field';
|
|
10
|
+
|
|
11
|
+
import {MultiSelect, useMultiSelectModel} from '@workday/canvas-kit-preview-react/multi-select';
|
|
12
|
+
import {StyledMenuItem} from '@workday/canvas-kit-react/menu';
|
|
13
|
+
|
|
14
|
+
const mainContentStyles = createStyles({
|
|
15
|
+
padding: system.space.x4,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const colors = ['Red', 'Blue', 'Purple', 'Green', 'Pink'];
|
|
19
|
+
const fruits = ['Apple', 'Orange', 'Banana', 'Grape', 'Lemon', 'Lime'];
|
|
20
|
+
const options = Array(1000)
|
|
21
|
+
.fill('')
|
|
22
|
+
.map((_, index) => {
|
|
23
|
+
return {
|
|
24
|
+
id: `${index + 1}`,
|
|
25
|
+
text: `${colors[index % colors.length]} ${fruits[index % fruits.length]} ${index + 1}`,
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export default () => {
|
|
30
|
+
const [value, setValue] = React.useState('');
|
|
31
|
+
|
|
32
|
+
const {model, loader} = useComboboxLoader(
|
|
33
|
+
{
|
|
34
|
+
// You can start with any number that makes sense.
|
|
35
|
+
total: 0,
|
|
36
|
+
|
|
37
|
+
// Pick whatever number makes sense for your API
|
|
38
|
+
pageSize: 20,
|
|
39
|
+
|
|
40
|
+
// A load function that will be called by the loader. You must return a promise that returns
|
|
41
|
+
// an object like `{items: [], total: 0}`. The `items` will be merged into the loader's cache
|
|
42
|
+
async load({pageNumber, pageSize, filter}) {
|
|
43
|
+
return new Promise<LoadReturn<(typeof options)[0]>>(resolve => {
|
|
44
|
+
// simulate a server response by resolving after a period of time
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
// simulate paging and filtering based on pre-computed items
|
|
47
|
+
const start = (pageNumber - 1) * pageSize;
|
|
48
|
+
const end = start + pageSize;
|
|
49
|
+
const filteredItems = options.filter(item => {
|
|
50
|
+
if (filter === '' || typeof filter !== 'string') {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return item.text.toLowerCase().includes(filter.toLowerCase());
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const total = filteredItems.length;
|
|
57
|
+
const items = filteredItems.slice(start, end);
|
|
58
|
+
|
|
59
|
+
resolve({
|
|
60
|
+
items,
|
|
61
|
+
total,
|
|
62
|
+
});
|
|
63
|
+
}, 300);
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
onShow() {
|
|
67
|
+
// The `shouldLoad` cancels while the combobox menu is hidden, so let's load when it is
|
|
68
|
+
// visible
|
|
69
|
+
loader.load();
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
useMultiSelectModel
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<CanvasProvider>
|
|
77
|
+
<>
|
|
78
|
+
<form
|
|
79
|
+
onSubmit={e => {
|
|
80
|
+
console.log('form submitted');
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
<main className={mainContentStyles}>
|
|
85
|
+
<MultiSelect model={model}>
|
|
86
|
+
<FormField orientation="horizontal">
|
|
87
|
+
<FormField.Label>Fruits</FormField.Label>
|
|
88
|
+
<FormField.Input
|
|
89
|
+
as={MultiSelect.SearchInput}
|
|
90
|
+
placeholder="Search"
|
|
91
|
+
name="toppings"
|
|
92
|
+
onChange={e => {
|
|
93
|
+
setValue(e.currentTarget.value);
|
|
94
|
+
}}
|
|
95
|
+
value={value}
|
|
96
|
+
/>
|
|
97
|
+
<MultiSelect.Popper>
|
|
98
|
+
<MultiSelect.Card>
|
|
99
|
+
{model.state.items.length === 0 && (
|
|
100
|
+
<StyledMenuItem as="span">No Results Found</StyledMenuItem>
|
|
101
|
+
)}
|
|
102
|
+
{model.state.items.length > 0 && (
|
|
103
|
+
<MultiSelect.List maxHeight={200}>
|
|
104
|
+
{item =>
|
|
105
|
+
item ? (
|
|
106
|
+
<MultiSelect.Item data-id={item.id}>
|
|
107
|
+
<MultiSelect.Item.Text>{item.text}</MultiSelect.Item.Text>
|
|
108
|
+
</MultiSelect.Item>
|
|
109
|
+
) : undefined
|
|
110
|
+
}
|
|
111
|
+
</MultiSelect.List>
|
|
112
|
+
)}
|
|
113
|
+
</MultiSelect.Card>
|
|
114
|
+
</MultiSelect.Popper>
|
|
115
|
+
</FormField>
|
|
116
|
+
</MultiSelect>
|
|
117
|
+
</main>
|
|
118
|
+
</form>
|
|
119
|
+
<div>Selected: {value}</div>
|
|
120
|
+
</>
|
|
121
|
+
</CanvasProvider>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
@@ -78,7 +78,8 @@ on a dark or colorful background such as `blueberry400`.
|
|
|
78
78
|
|
|
79
79
|
### Grow Prop
|
|
80
80
|
|
|
81
|
-
The example below shows the use of the `grow` prop on different variants of buttons. This will set
|
|
81
|
+
The example below shows the use of the `grow` prop on different variants of buttons. This will set
|
|
82
|
+
the width of the button to the width of its container.
|
|
82
83
|
|
|
83
84
|
<ExampleCodeBlock code={Grow} />
|
|
84
85
|
|
|
@@ -106,4 +107,4 @@ should be used for navigation.
|
|
|
106
107
|
|
|
107
108
|
## Specifications
|
|
108
109
|
|
|
109
|
-
<Specifications file="Button.spec.
|
|
110
|
+
<Specifications file="Button.spec.tsx" name="Button" />
|
|
@@ -36,13 +36,16 @@ two separate `input` elements.
|
|
|
36
36
|
the same as the user input. Any prop related to the function of forms will be passed here. For
|
|
37
37
|
example, the `name` attribute will be passed here. The `ref` will be pointed to this element.
|
|
38
38
|
|
|
39
|
+
`Select` and `MultiSelect` are examples of constrained comboboxes.
|
|
40
|
+
|
|
39
41
|
### Arbitrary
|
|
40
42
|
|
|
41
43
|
An arbitrary combobox allows the user to enter any value. The list of options are presented as
|
|
42
44
|
suggestions and selecting an option will prefill the combobox with the value of the option. The user
|
|
43
45
|
is still allowed to modify the combobox even after an option is entered. With arbitrary comboboxes,
|
|
44
46
|
there is only one `input` element. Arbitrary combobox inputs should use the
|
|
45
|
-
[useComboboxInputArbitrary](#usecomboboxinputarbirary) hook.
|
|
47
|
+
[useComboboxInputArbitrary](#usecomboboxinputarbirary) hook. Typeahead or `Autocomplete` are
|
|
48
|
+
examples are arbitrary value comboboxes.
|
|
46
49
|
|
|
47
50
|
## Installation
|
|
48
51
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workday/canvas-kit-docs",
|
|
3
|
-
"version": "12.0.0-alpha.
|
|
3
|
+
"version": "12.0.0-alpha.919-next.0",
|
|
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,10 +44,10 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@emotion/styled": "^11.6.0",
|
|
46
46
|
"@storybook/csf": "0.0.1",
|
|
47
|
-
"@workday/canvas-kit-labs-react": "^12.0.0-alpha.
|
|
48
|
-
"@workday/canvas-kit-preview-react": "^12.0.0-alpha.
|
|
49
|
-
"@workday/canvas-kit-react": "^12.0.0-alpha.
|
|
50
|
-
"@workday/canvas-kit-styling": "^12.0.0-alpha.
|
|
47
|
+
"@workday/canvas-kit-labs-react": "^12.0.0-alpha.919-next.0",
|
|
48
|
+
"@workday/canvas-kit-preview-react": "^12.0.0-alpha.919-next.0",
|
|
49
|
+
"@workday/canvas-kit-react": "^12.0.0-alpha.919-next.0",
|
|
50
|
+
"@workday/canvas-kit-styling": "^12.0.0-alpha.919-next.0",
|
|
51
51
|
"@workday/canvas-system-icons-web": "^3.0.0",
|
|
52
52
|
"@workday/canvas-tokens-web": "^2.0.1",
|
|
53
53
|
"markdown-to-jsx": "^7.2.0",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"mkdirp": "^1.0.3",
|
|
61
61
|
"typescript": "5.0"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "4fa21d7c07d138e03daf228f4a6a17fcbf379a3f"
|
|
64
64
|
}
|