@fluentui/react-combobox 9.0.0-beta.18 → 9.0.0-beta.19
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/CHANGELOG.json +48 -1
- package/CHANGELOG.md +15 -2
- package/package.json +5 -5
- package/Spec-migration.md +0 -13
- package/Spec.md +0 -520
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,54 @@
|
|
|
2
2
|
"name": "@fluentui/react-combobox",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "
|
|
5
|
+
"date": "Wed, 21 Dec 2022 10:17:11 GMT",
|
|
6
|
+
"tag": "@fluentui/react-combobox_v9.0.0-beta.19",
|
|
7
|
+
"version": "9.0.0-beta.19",
|
|
8
|
+
"comments": {
|
|
9
|
+
"prerelease": [
|
|
10
|
+
{
|
|
11
|
+
"author": "tristan.watanabe@gmail.com",
|
|
12
|
+
"package": "@fluentui/react-combobox",
|
|
13
|
+
"commit": "d301e75ec1f47418ebabdc63e608f3fb5a37b6d9",
|
|
14
|
+
"comment": "chore: Migrate to new package structure."
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"author": "beachball",
|
|
18
|
+
"package": "@fluentui/react-combobox",
|
|
19
|
+
"comment": "Bump @fluentui/react-field to v9.0.0-alpha.12",
|
|
20
|
+
"commit": "66bf89f634cad4a275e957d7a2214c7e73ff8c2e"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"author": "beachball",
|
|
24
|
+
"package": "@fluentui/react-combobox",
|
|
25
|
+
"comment": "Bump @fluentui/react-portal to v9.0.14",
|
|
26
|
+
"commit": "66bf89f634cad4a275e957d7a2214c7e73ff8c2e"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"author": "beachball",
|
|
30
|
+
"package": "@fluentui/react-combobox",
|
|
31
|
+
"comment": "Bump @fluentui/react-positioning to v9.3.5",
|
|
32
|
+
"commit": "66bf89f634cad4a275e957d7a2214c7e73ff8c2e"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"author": "beachball",
|
|
36
|
+
"package": "@fluentui/react-combobox",
|
|
37
|
+
"comment": "Bump @fluentui/react-theme to v9.1.5",
|
|
38
|
+
"commit": "66bf89f634cad4a275e957d7a2214c7e73ff8c2e"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"none": [
|
|
42
|
+
{
|
|
43
|
+
"author": "behowell@microsoft.com",
|
|
44
|
+
"package": "@fluentui/react-combobox",
|
|
45
|
+
"commit": "68505ab8eb1b05f45ab09c21b9d66c177d1e50f5",
|
|
46
|
+
"comment": "chore: Add bundle size tests for Fields"
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"date": "Tue, 20 Dec 2022 14:59:22 GMT",
|
|
6
53
|
"tag": "@fluentui/react-combobox_v9.0.0-beta.18",
|
|
7
54
|
"version": "9.0.0-beta.18",
|
|
8
55
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
# Change Log - @fluentui/react-combobox
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Wed, 21 Dec 2022 10:17:11 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## [9.0.0-beta.19](https://github.com/microsoft/fluentui/tree/@fluentui/react-combobox_v9.0.0-beta.19)
|
|
8
|
+
|
|
9
|
+
Wed, 21 Dec 2022 10:17:11 GMT
|
|
10
|
+
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-combobox_v9.0.0-beta.18..@fluentui/react-combobox_v9.0.0-beta.19)
|
|
11
|
+
|
|
12
|
+
### Changes
|
|
13
|
+
|
|
14
|
+
- chore: Migrate to new package structure. ([PR #26037](https://github.com/microsoft/fluentui/pull/26037) by tristan.watanabe@gmail.com)
|
|
15
|
+
- Bump @fluentui/react-field to v9.0.0-alpha.12 ([commit](https://github.com/microsoft/fluentui/commit/66bf89f634cad4a275e957d7a2214c7e73ff8c2e) by beachball)
|
|
16
|
+
- Bump @fluentui/react-portal to v9.0.14 ([commit](https://github.com/microsoft/fluentui/commit/66bf89f634cad4a275e957d7a2214c7e73ff8c2e) by beachball)
|
|
17
|
+
- Bump @fluentui/react-positioning to v9.3.5 ([commit](https://github.com/microsoft/fluentui/commit/66bf89f634cad4a275e957d7a2214c7e73ff8c2e) by beachball)
|
|
18
|
+
- Bump @fluentui/react-theme to v9.1.5 ([commit](https://github.com/microsoft/fluentui/commit/66bf89f634cad4a275e957d7a2214c7e73ff8c2e) by beachball)
|
|
19
|
+
|
|
7
20
|
## [9.0.0-beta.18](https://github.com/microsoft/fluentui/tree/@fluentui/react-combobox_v9.0.0-beta.18)
|
|
8
21
|
|
|
9
|
-
Tue, 20 Dec 2022 14:
|
|
22
|
+
Tue, 20 Dec 2022 14:59:22 GMT
|
|
10
23
|
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-combobox_v9.0.0-beta.17..@fluentui/react-combobox_v9.0.0-beta.18)
|
|
11
24
|
|
|
12
25
|
### Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluentui/react-combobox",
|
|
3
|
-
"version": "9.0.0-beta.
|
|
3
|
+
"version": "9.0.0-beta.19",
|
|
4
4
|
"description": "Fluent UI React Combobox component",
|
|
5
5
|
"main": "lib-commonjs/index.js",
|
|
6
6
|
"module": "lib/index.js",
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@fluentui/keyboard-keys": "^9.0.1",
|
|
35
35
|
"@fluentui/react-context-selector": "^9.1.3",
|
|
36
|
-
"@fluentui/react-field": "9.0.0-alpha.
|
|
36
|
+
"@fluentui/react-field": "9.0.0-alpha.12",
|
|
37
37
|
"@fluentui/react-icons": "^2.0.175",
|
|
38
|
-
"@fluentui/react-portal": "^9.0.
|
|
39
|
-
"@fluentui/react-positioning": "^9.3.
|
|
40
|
-
"@fluentui/react-theme": "^9.1.
|
|
38
|
+
"@fluentui/react-portal": "^9.0.14",
|
|
39
|
+
"@fluentui/react-positioning": "^9.3.5",
|
|
40
|
+
"@fluentui/react-theme": "^9.1.5",
|
|
41
41
|
"@fluentui/react-utilities": "^9.3.0",
|
|
42
42
|
"@griffel/react": "^1.4.2",
|
|
43
43
|
"tslib": "^2.1.0"
|
package/Spec-migration.md
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# @fluentui/react-combobox Migration Spec
|
|
2
|
-
|
|
3
|
-
## STATUS: WIP
|
|
4
|
-
|
|
5
|
-
This Migration guide is a work in progress and is not yet ready for use. It will be fleshed out once the Combobox spec is finalized.
|
|
6
|
-
|
|
7
|
-
## From v0 Dropdown
|
|
8
|
-
|
|
9
|
-
## From v8 Dropdown
|
|
10
|
-
|
|
11
|
-
## From v8 Combobox
|
|
12
|
-
|
|
13
|
-
## From v8 Pickers
|
package/Spec.md
DELETED
|
@@ -1,520 +0,0 @@
|
|
|
1
|
-
# @fluentui/react-combobox Spec
|
|
2
|
-
|
|
3
|
-
## Background
|
|
4
|
-
|
|
5
|
-
The basic purpose of a Combobox is to allow users to select one or more values from among a set of options. The semantics and behavior are roughly similar to a more complex version of an HTML `<select>` element, with more functionality and styling control.
|
|
6
|
-
|
|
7
|
-
A combobox can be single or multi-select, and it can be editable or select-only. More options are covered in the [Variants section](#variants).
|
|
8
|
-
|
|
9
|
-
The basic structure of a Combobox has two pieces: the faceplate, which is always rendered on the page, and displays the current selection, and the popup Listbox, which contains the set of options.
|
|
10
|
-
|
|
11
|
-
The Listbox can also be used as a standalone inline selection widget, similar to a `<select size="n > 1">` or `<select multiple>`. The Listbox has the same options and functionality whether used on its own, or within a Combobox.
|
|
12
|
-
|
|
13
|
-
### Combobox vs. Select vs. Menu
|
|
14
|
-
|
|
15
|
-
Combobox, Select, and Menu all share some common pieces of interaction: a trigger element opens a popup with a list of interactive items. Despite that similarity, they cannot be used interchangeably.
|
|
16
|
-
|
|
17
|
-
### When to use Select
|
|
18
|
-
|
|
19
|
-
The [Select component](https://github.com/microsoft/fluentui/blob/master/packages/react-select/Spec.md) shares most of its underlying semantics with the Combobox. The main difference is that under the hood it uses the HTML `<select>` element, so its functionality is more limited.
|
|
20
|
-
|
|
21
|
-
Select provides better mobile support and accessibility than Combobox, and has the same visual appearance when collapsed. When expanded, it displays the native OS select menu, which cannot be styled.
|
|
22
|
-
|
|
23
|
-
Use Select when a basic single-select form component with no freeform text input or filtering is needed.
|
|
24
|
-
|
|
25
|
-
### When to use Combobox
|
|
26
|
-
|
|
27
|
-
Combobox is a more feature-rich version of Select, which comes at the cost a larger code footprint, and less robust support for accessibility compared to the native `<select>` element.
|
|
28
|
-
|
|
29
|
-
Use Combobox when any of the following are required:
|
|
30
|
-
|
|
31
|
-
- Filtering or freeform text input
|
|
32
|
-
- Virtualization
|
|
33
|
-
- Control over styling the dropdown and options
|
|
34
|
-
- Multiple selection
|
|
35
|
-
|
|
36
|
-
### When to use Menu
|
|
37
|
-
|
|
38
|
-
Unlike Select and Combobox, [Menu](https://github.com/microsoft/fluentui/blob/master/packages/react-menu/Spec.md) is not primarily a selection component or a form component. Menu should be used when the purpose is to allow the user to perform an immediate action on the page, rather than save a selected value.
|
|
39
|
-
|
|
40
|
-
Examples of appropriate Menu usage include:
|
|
41
|
-
|
|
42
|
-
- Application menus
|
|
43
|
-
- Context menus
|
|
44
|
-
- Editor menubars
|
|
45
|
-
|
|
46
|
-
## Prior Art
|
|
47
|
-
|
|
48
|
-
The [Open UI research on Select](https://open-ui.org/components/select.research) includes Combobox functionality in addition to basic Select functionality.
|
|
49
|
-
|
|
50
|
-
### Comparison of v8 and v0
|
|
51
|
-
|
|
52
|
-
`@fluentui/react` (v8) has three different controls that are different flavors of select/combobox:
|
|
53
|
-
|
|
54
|
-
- [Combobox](https://developer.microsoft.com/en-us/fluentui#/controls/web/combobox): an editable combobox with a textfield and dropdown listbox
|
|
55
|
-
- [Dropdown](https://developer.microsoft.com/en-us/fluentui#/controls/web/dropdown): a non-editable combobox with dropdown listbox
|
|
56
|
-
- [Pickers](https://developer.microsoft.com/en-us/fluentui#/controls/web/pickers): an editable combobox with greater customization, particularly in displaying selected items
|
|
57
|
-
|
|
58
|
-
`@fluentui/react-northstar` (v0) has one combobox control:
|
|
59
|
-
|
|
60
|
-
- [Dropdown](https://fluentsite.z22.web.core.windows.net/0.51.2/components/dropdown/definition): either an editable or non-editable combobox with a tag-like approach to selected items
|
|
61
|
-
|
|
62
|
-
#### Defining options
|
|
63
|
-
|
|
64
|
-
v8's Combobox and Dropdown, and v0's Dropdown allow options to be passed in through a prop:
|
|
65
|
-
|
|
66
|
-
```tsx
|
|
67
|
-
// v7/v8 Combobox and Dropdown
|
|
68
|
-
<Combobox options={[{ key: 'A', text: 'Option A' }, { key: 'B', text: 'Option B' }]} />
|
|
69
|
-
|
|
70
|
-
<Dropdown options={[{ key: 'A', text: 'Option A' }, { key: 'B', text: 'Option B' }]} />
|
|
71
|
-
|
|
72
|
-
// v0 Dropdown
|
|
73
|
-
<Dropdown items={['Option A', 'Option B']} />
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
The v8 Pickers defined options through an `onResolveSuggestions` callback:
|
|
77
|
-
|
|
78
|
-
```tsx
|
|
79
|
-
const options = [
|
|
80
|
-
{ key: 'A', name: 'Option A' },
|
|
81
|
-
{ key: 'B', name: 'Option B' },
|
|
82
|
-
];
|
|
83
|
-
const filterSuggestedOptions = (filterText: string, tagList: ITag[]): ITag[] => options;
|
|
84
|
-
|
|
85
|
-
<TagPicker onResolveSuggestions={filterSuggestedOptions} />;
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
In contrast, v9 defines options as children of the Combobox control:
|
|
89
|
-
|
|
90
|
-
```tsx
|
|
91
|
-
<Combobox>
|
|
92
|
-
<Option>Option A</Option>
|
|
93
|
-
<Option>Option B</Option>
|
|
94
|
-
</Combobox>
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Groups of options in v9 are also defined as children, rather than through the `options` or `items` prop:
|
|
98
|
-
|
|
99
|
-
```tsx
|
|
100
|
-
<Combobox>
|
|
101
|
-
<OptionGroup label="Group 1">
|
|
102
|
-
<Option>Option A</Option>
|
|
103
|
-
<Option>Option B</Option>
|
|
104
|
-
</OptionGroup>
|
|
105
|
-
<OptionGroup label="Group 2">
|
|
106
|
-
<Option>Option C</Option>
|
|
107
|
-
<Option>Option D</Option>
|
|
108
|
-
</OptionGroup>
|
|
109
|
-
</Combobox>
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
#### Customizing Option Render
|
|
113
|
-
|
|
114
|
-
Because v8 and v0 Combobox, Dropdown, and Pickers defined options as props, they used `onRenderX` props to customize option render:
|
|
115
|
-
|
|
116
|
-
| v8 Dropdown | v8 Combobox | v8 Pickers | v0 Dropdown |
|
|
117
|
-
| -------------- | -------------- | ------------------ | ------------------ |
|
|
118
|
-
| onRenderOption | onRenderOption | onRenderSuggestion | renderItem |
|
|
119
|
-
| onRenderItem | onRenderItem | | renderSelectedItem |
|
|
120
|
-
|
|
121
|
-
The v9 Combobox approach of options as children allows option render to be directly customized through the `<Option>` JSX and the Option's own children:
|
|
122
|
-
|
|
123
|
-
```tsx
|
|
124
|
-
<Combobox>
|
|
125
|
-
<Option key="A">
|
|
126
|
-
Option A <CalendarIcon />
|
|
127
|
-
</Option>
|
|
128
|
-
<Option key="B" style={{ color: 'red' }}>
|
|
129
|
-
Option <i>B</i>
|
|
130
|
-
</Option>
|
|
131
|
-
</Combobox>
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
#### Positioning
|
|
135
|
-
|
|
136
|
-
Combobox uses [Popper JS](https://popper.js.org/) through `@fluentui/react-positioning` for positioning the dropdown listbox. It can be customized through the `positioning` property. The [`react-popover` spec](https://github.com/microsoft/fluentui/blob/master/packages/react-popover/Spec.md) contains details on positioning options and migration from v8/v0.
|
|
137
|
-
|
|
138
|
-
#### Selection
|
|
139
|
-
|
|
140
|
-
Combobox in v9 allows both controlled and uncontrolled selection, as do the corresponding v8 and v0 components.
|
|
141
|
-
|
|
142
|
-
| Concept | v9 Combobox | v8 Dropdown | v8 Combobox | v8 Pickers | v0 Dropdown |
|
|
143
|
-
| -------------------- | ------------------- | ------------------- | ------------------ | -------------------- | ------------ |
|
|
144
|
-
| Initial selection | initialSelectedKeys | defaultSelectedKeys | defaultSelectedKey | defaultSelectedItems | defaultValue |
|
|
145
|
-
| Controlled selection | selectedKeys | selectedKey | selectedKey | selectedItems | value |
|
|
146
|
-
| Callback | onOptionSelect | onChange | onChange | onChange | onChange |
|
|
147
|
-
|
|
148
|
-
The reason to move to `onOptionSelect` over `onChange` in the v9 Combobox is because the editable Combobox uses an `<input>` element as its primary slot. Using `onOptionSelect` allows the input to retain it's built-in `onChange` event.
|
|
149
|
-
|
|
150
|
-
## Sample Code
|
|
151
|
-
|
|
152
|
-
The following example code will not necessarily work in the current package, and is subject to change.
|
|
153
|
-
|
|
154
|
-
### Basic Combobox
|
|
155
|
-
|
|
156
|
-
```tsx
|
|
157
|
-
<label id="pets">Best pet</label>
|
|
158
|
-
<Combobox aria-labelledby="pets" placeholder="Select an animal">
|
|
159
|
-
<Option key="cat">Cat</Option>
|
|
160
|
-
<Option key="dog">Dog</Option>
|
|
161
|
-
<Option key="ferret">Ferret</Option>
|
|
162
|
-
<Option key="fish">Fish</Option>
|
|
163
|
-
</Combobox>
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Grouped Options
|
|
167
|
-
|
|
168
|
-
```tsx
|
|
169
|
-
<label id="pets">Best pet</label>
|
|
170
|
-
<Combobox aria-labelledby="pets">
|
|
171
|
-
<OptionGroup label="Land">
|
|
172
|
-
<Option key="cat">Cat</Option>
|
|
173
|
-
<Option key="dog">Dog</Option>
|
|
174
|
-
<Option key="ferret">Ferret</Option>
|
|
175
|
-
</OptionGroup>
|
|
176
|
-
<OptionGroup label="Water">
|
|
177
|
-
<Option key="fish">Fish</Option>
|
|
178
|
-
<Option key="turtle">Turtle</Option>
|
|
179
|
-
</OptionGroup>
|
|
180
|
-
</Combobox>
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
### Multiple Selection
|
|
184
|
-
|
|
185
|
-
```tsx
|
|
186
|
-
<label id="pets">Best pet</label>
|
|
187
|
-
<Combobox aria-labelledby="pets" multiselect={true}>
|
|
188
|
-
<Option key="cat">Cat</Option>
|
|
189
|
-
<Option key="dog">Dog</Option>
|
|
190
|
-
<Option key="ferret">Ferret</Option>
|
|
191
|
-
<Option key="fish">Fish</Option>
|
|
192
|
-
</Combobox>
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### Option with icon and description
|
|
196
|
-
|
|
197
|
-
```tsx
|
|
198
|
-
<label id="pets">Best pet</label>
|
|
199
|
-
<Combobox aria-labelledby="pets">
|
|
200
|
-
<Option key="cat" icon={<CatIcon />} description="Felis catus">Cat</Option>
|
|
201
|
-
<Option key="dog" icon={<DogIcon />} description="Canis familiaris">Dog</Option>
|
|
202
|
-
</Combobox>
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
### Standalone Listbox
|
|
206
|
-
|
|
207
|
-
This will render a listbox inline in the page, rather than as a popup. This component does not have a separate trigger/faceplate displaying selected items.
|
|
208
|
-
|
|
209
|
-
```tsx
|
|
210
|
-
<label id="pets">Best pet</label>
|
|
211
|
-
<Listbox aria-labelledby="pets">
|
|
212
|
-
<Option key="cat">Cat</Option>
|
|
213
|
-
<Option key="dog">Dog</Option>
|
|
214
|
-
<Option key="ferret">Ferret</Option>
|
|
215
|
-
<Option key="fish">Fish</Option>
|
|
216
|
-
</Listbox>
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Select-only Combobox
|
|
220
|
-
|
|
221
|
-
Note: the approach for authoring editable vs. select-only comboboxes is still undecided. There are roughly two likely ways this could be authored.
|
|
222
|
-
|
|
223
|
-
Option 1 (preferred), using a separate Dropdown component that shares all functionality apart from the trigger with Combobox:
|
|
224
|
-
|
|
225
|
-
```tsx
|
|
226
|
-
<label id="pets">Best pet</label>
|
|
227
|
-
<Dropdown aria-labelledby="pets">
|
|
228
|
-
<Option key="cat">Cat</Option>
|
|
229
|
-
<Option key="dog">Dog</Option>
|
|
230
|
-
<Option key="ferret">Ferret</Option>
|
|
231
|
-
<Option key="fish">Fish</Option>
|
|
232
|
-
</Dropdown>
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
Option 2, using slots:
|
|
236
|
-
|
|
237
|
-
```tsx
|
|
238
|
-
<label id="pets">Best pet</label>
|
|
239
|
-
<Combobox aria-labelledby="pets" trigger={<ComboInput>}>
|
|
240
|
-
<Option key="cat">Cat</Option>
|
|
241
|
-
<Option key="dog">Dog</Option>
|
|
242
|
-
<Option key="ferret">Ferret</Option>
|
|
243
|
-
<Option key="fish">Fish</Option>
|
|
244
|
-
</Combobox>
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## Variants
|
|
248
|
-
|
|
249
|
-
### Visual variants
|
|
250
|
-
|
|
251
|
-
Visual variants are very similar to `@fluentui/react-select` and `@fluentui/react-input` variants. They can be controlled through the `inline`, `size`, and `appearance` props:
|
|
252
|
-
|
|
253
|
-
### Inline
|
|
254
|
-
|
|
255
|
-
- `true`/Inline: the Combobox is rendered inline with text and other controls
|
|
256
|
-
- `false`/Block (default): the Combobox has a block layout
|
|
257
|
-
|
|
258
|
-
### Size
|
|
259
|
-
|
|
260
|
-
- `small`
|
|
261
|
-
- `medium` (default)
|
|
262
|
-
- `large`
|
|
263
|
-
|
|
264
|
-
### Appearance
|
|
265
|
-
|
|
266
|
-
- `outline` (default)
|
|
267
|
-
- `filledDarker`
|
|
268
|
-
- `filledLighter`
|
|
269
|
-
- `transparent`
|
|
270
|
-
|
|
271
|
-
The design spec for Combobox has more visual details on each of these.
|
|
272
|
-
|
|
273
|
-
### Editable vs. Select-only
|
|
274
|
-
|
|
275
|
-
A Combobox can allow text input, or be select-only. If it allows text input, the focusable element and slot will be an `<input>`. If select-only, the primary slot will be a `<button>` element.
|
|
276
|
-
|
|
277
|
-
### Multiple selection
|
|
278
|
-
|
|
279
|
-
A Combobox supports single and multiple selection through the `multiselect` prop. Multiselect Combobox options have a slightly different visual check style, and the listbox popup does not close when individual options are selected or deselected.
|
|
280
|
-
|
|
281
|
-
### Disabled options
|
|
282
|
-
|
|
283
|
-
Individual Option children may be set to a disabled state using the `disabled` prop on the `<Option>` itself. Disabled options cannot be selected, but are still reachable via keyboard arrow keys.
|
|
284
|
-
|
|
285
|
-
### Grouped options
|
|
286
|
-
|
|
287
|
-
Options may be grouped with an optional group label using the `<OptionGroup>` component. This creates a semantic grouping for options in addition to the visual style.
|
|
288
|
-
|
|
289
|
-
While visual groupings of options could be achieved with a divider and static header text, using `<OptionGroup>` is recommended because it provides group and label semantics to screen readers.
|
|
290
|
-
|
|
291
|
-
### Non-Option children
|
|
292
|
-
|
|
293
|
-
Combobox supports arbitrary non-Option and non-OptionGroup children, but for screen reader and keyboard accessibility, this should be used with caution.
|
|
294
|
-
|
|
295
|
-
Interactive, focusable elements (aside from `<Option>`) should never be added as children, since they will not be reachable with the keyboard, and may interfere with screen reader accessibility. It is recommended to add `role="presentation"` or `role="none"` to any static children added to Combobox to avoid unintentional side effects for screen reader users:
|
|
296
|
-
|
|
297
|
-
```tsx
|
|
298
|
-
<Combobox>
|
|
299
|
-
<Option key="A">Option A</Option>
|
|
300
|
-
<span role="none" className="my-fancy-divider" />
|
|
301
|
-
<Option key="B">Option B</Option>
|
|
302
|
-
</Combobox>
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
## API
|
|
306
|
-
|
|
307
|
-
### Combobox
|
|
308
|
-
|
|
309
|
-
The primary slot for combobox is the `trigger`, which is a `<button>` element for select-only comboboxes, and an `<input>` element for editable comboboxes. More slot information is provided in the [Structure section](#structure).
|
|
310
|
-
|
|
311
|
-
For the full current set of props, see the [Combobox types file](https://github.com/microsoft/fluentui/blob/master/packages/react-combobox/src/components/Combobox/Combobox.types.ts) and [Selection types file](https://github.com/microsoft/fluentui/blob/master/packages/react-combobox/src/utils/Selection.types.ts).
|
|
312
|
-
|
|
313
|
-
```ts
|
|
314
|
-
// A simplified version of relevant props
|
|
315
|
-
type SimpleComboboxProps = {
|
|
316
|
-
/** Controls the colors and borders of the field (default `outline`) */
|
|
317
|
-
appearance?: 'outline' | 'underline' | 'filledDarker' | 'filledLighter';
|
|
318
|
-
|
|
319
|
-
/* For an uncontrolled component, sets the initial selection */
|
|
320
|
-
initialSelectedKeys?: string[];
|
|
321
|
-
|
|
322
|
-
/** Render the listbox popup inline in the DOM, for accessibility-related edge cases (default false) */
|
|
323
|
-
inline?: boolean;
|
|
324
|
-
|
|
325
|
-
/** Sets the selection type to multiselect */
|
|
326
|
-
multiselect?: boolean;
|
|
327
|
-
|
|
328
|
-
/** Controlled open state */
|
|
329
|
-
open?: boolean;
|
|
330
|
-
|
|
331
|
-
/** The placeholder will show when no value is selected */
|
|
332
|
-
placeholder?: string;
|
|
333
|
-
|
|
334
|
-
/** Controlled array of selected option keys. */
|
|
335
|
-
selectedKeys?: string[];
|
|
336
|
-
|
|
337
|
-
/** Size of the trigger (default `medium`) */
|
|
338
|
-
size?: 'small' | 'medium' | 'large';
|
|
339
|
-
|
|
340
|
-
/** Controlled value displayed by the Combobox */
|
|
341
|
-
value?: string;
|
|
342
|
-
|
|
343
|
-
/** Callback when the open/closed state of the dropdown changes */
|
|
344
|
-
onOpenChange?(event: OpenEvents, data: OnOpenChangeData): void;
|
|
345
|
-
|
|
346
|
-
/* Callback when an option is selected */
|
|
347
|
-
onOptionSelect?(event: SelectionEvents, optionKey: string): void;
|
|
348
|
-
};
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
### Listbox
|
|
352
|
-
|
|
353
|
-
Listbox shares the same API for selection and option children as Combobox. When used within Combobox, selection should be managed solely through Combobox props, and not through the listbox slot.
|
|
354
|
-
|
|
355
|
-
For the full current set of props, see the [Listbox types file](https://github.com/microsoft/fluentui/blob/master/packages/react-combobox/src/components/Listbox/Listbox.types.ts) and [Selection types file](https://github.com/microsoft/fluentui/blob/master/packages/react-combobox/src/utils/Selection.types.ts).
|
|
356
|
-
|
|
357
|
-
```ts
|
|
358
|
-
// A simplified version of relevant props
|
|
359
|
-
type SimpleListboxProps = {
|
|
360
|
-
/* For an uncontrolled component, sets the initial selection */
|
|
361
|
-
initialSelectedKeys?: string[];
|
|
362
|
-
|
|
363
|
-
/** Sets the selection type to multiselect */
|
|
364
|
-
multiselect?: boolean;
|
|
365
|
-
|
|
366
|
-
/** Controlled array of selected option keys. */
|
|
367
|
-
selectedKeys?: string[];
|
|
368
|
-
|
|
369
|
-
/* Callback when an option is selected */
|
|
370
|
-
onOptionSelect?(event: SelectionEvents, optionKey: string): void;
|
|
371
|
-
};
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
### OptionGroup
|
|
375
|
-
|
|
376
|
-
OptionGroup is functionally a wrapper for options, with a single `label` slot prop.
|
|
377
|
-
|
|
378
|
-
For the full current set of props, see the [OptionGroup types file](https://github.com/microsoft/fluentui/blob/master/packages/react-combobox/src/components/OptionGroup/OptionGroup.types.ts).
|
|
379
|
-
|
|
380
|
-
### Option
|
|
381
|
-
|
|
382
|
-
Options have slots for `check`, `icon`, and `description`.
|
|
383
|
-
|
|
384
|
-
For the full current set of props, see the [Option types file](https://github.com/microsoft/fluentui/blob/master/packages/react-combobox/src/components/Option/Option.types.ts).
|
|
385
|
-
|
|
386
|
-
```ts
|
|
387
|
-
// A simplified version of relevant props
|
|
388
|
-
type SimpleOptionProps = {
|
|
389
|
-
/* Sets an option to the `disabled` state */
|
|
390
|
-
disabled?: boolean;
|
|
391
|
-
|
|
392
|
-
/** The id of the Option */
|
|
393
|
-
id: string;
|
|
394
|
-
|
|
395
|
-
/** Defines a string value for the option, used for the parent Combobox's value */
|
|
396
|
-
value?: string;
|
|
397
|
-
};
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
## Structure
|
|
401
|
-
|
|
402
|
-
### Public
|
|
403
|
-
|
|
404
|
-
```tsx
|
|
405
|
-
<Combobox placeholder="Select an option">
|
|
406
|
-
<OptionGroup label="Group 1">
|
|
407
|
-
<Option key="A">Option A</Option>
|
|
408
|
-
<Option key="B">Option B</Option>
|
|
409
|
-
</OptionGroup>
|
|
410
|
-
<OptionGroup label="Group 2">
|
|
411
|
-
<Option key="C">Option C</Option>
|
|
412
|
-
<Option key="D">Option D</Option>
|
|
413
|
-
</OptionGroup>
|
|
414
|
-
</Combobox>
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
### DOM
|
|
418
|
-
|
|
419
|
-
This shows the DOM structure of the Combobox after being opened:
|
|
420
|
-
|
|
421
|
-
```html
|
|
422
|
-
<div>
|
|
423
|
-
<!-- root slot, combobox wrapper -->
|
|
424
|
-
<button role="combobox" type="button" aria-expanded="true" aria-activedescendant="option1-id">
|
|
425
|
-
<!-- primary slot -->
|
|
426
|
-
Select an option
|
|
427
|
-
</button>
|
|
428
|
-
<span
|
|
429
|
-
><svg><!-- dropdown icon --></svg></span
|
|
430
|
-
>
|
|
431
|
-
</div>
|
|
432
|
-
|
|
433
|
-
<!-- in a portal: -->
|
|
434
|
-
<div role="listbox">
|
|
435
|
-
<!-- listbox root slot -->
|
|
436
|
-
<div role="group" aria-labelledby="group1-label-id">
|
|
437
|
-
<!-- optiongroup root slot -->
|
|
438
|
-
<span id="group1-label-id" role="presentation">Group 1</span
|
|
439
|
-
><!-- optiongroup label slot -->
|
|
440
|
-
<div role="option" aria-selected="false" id="option1-id">
|
|
441
|
-
<!-- option root slot -->
|
|
442
|
-
<span aria-hidden="true"
|
|
443
|
-
><svg><!-- check icon --></svg></span
|
|
444
|
-
><!-- option check slot -->
|
|
445
|
-
Option A
|
|
446
|
-
</div>
|
|
447
|
-
<div role="option" aria-selected="false" id="option2-id">
|
|
448
|
-
<span aria-hidden="true"
|
|
449
|
-
><svg><!-- check icon --></svg></span
|
|
450
|
-
>
|
|
451
|
-
Option B
|
|
452
|
-
</div>
|
|
453
|
-
</div>
|
|
454
|
-
</div>
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
## Migration
|
|
458
|
-
|
|
459
|
-
The following v7/v8 and v0 components can be migrated to the v9 Combobox:
|
|
460
|
-
|
|
461
|
-
- **v8 Dropdown**: Use the v9 Select or v9 Combobox, [depending on the required features](#combobox-vs-select-vs-menu). If using Combobox, use the [select-only variation](#select-only-combobox).
|
|
462
|
-
- **v8 Combobox**: The v8 Combobox should be replaced by the editable variant of the v9 Combobox.
|
|
463
|
-
- **v8 Pickers**: v8 Pickers should be replaced by the multiselect variant of the v9 Combobox. There is a design spec for adding selected tags to the v9 Combobox.
|
|
464
|
-
- **v0 Dropdown**: The v0 Dropdown should be replaced by the v9 Combobox.
|
|
465
|
-
|
|
466
|
-
The primary difference between v7/v8 and v0 components vs. the v9 Combobox is the definition of options as children in v9.
|
|
467
|
-
|
|
468
|
-
For a full migration guide, see [the migration spec](./Spec-migration.md).
|
|
469
|
-
|
|
470
|
-
## Behaviors
|
|
471
|
-
|
|
472
|
-
### Positioning
|
|
473
|
-
|
|
474
|
-
The default position for the listbox popup is `below-start`. The position can be customized through the `positioning` prop, which shares an API with other v9 components like Menu and Tooltip. The full positioning API is defined in the [`@fluentui/react-positioning` package](https://github.com/microsoft/fluentui/blob/master/packages/react-positioning/src/types.ts).
|
|
475
|
-
|
|
476
|
-
### Keyboard interaction
|
|
477
|
-
|
|
478
|
-
The keyboard interaction model follows that of the [ARIA Practices Combobox Pattern](https://w3c.github.io/aria-practices/#combobox), with a couple modifications based on user research:
|
|
479
|
-
|
|
480
|
-
- <kbd>Space</kbd> selects options
|
|
481
|
-
- <kbd>Tab</kbd> selects the currently highlighted/active option when the listbox is open
|
|
482
|
-
|
|
483
|
-
### Dismissing the listbox popup
|
|
484
|
-
|
|
485
|
-
The listbox popup will be dismissed when any of the following occur:
|
|
486
|
-
|
|
487
|
-
- Light dismiss: if a user clicks outside or moves focus away from the combobox, it will dismiss
|
|
488
|
-
- In a single-select combobox, the listbox dismisses when an option is selected
|
|
489
|
-
- Escape is pressed
|
|
490
|
-
- Alt + up arrow is pressed
|
|
491
|
-
|
|
492
|
-
## Accessibility
|
|
493
|
-
|
|
494
|
-
While accessibility is built into the Combobox as much as possible, there will always be bugs due to quirks in platform and screen reader support. The most robustly accessible selection component will always be `@fluentui/react-select`, since it uses the native `<select>` element.
|
|
495
|
-
|
|
496
|
-
Most Combobox-specific accessibility considerations are built in to the rest of the spec, but this section addresses additional concerns that don't fit into any other category, or are worth calling out in more detail.
|
|
497
|
-
|
|
498
|
-
### Using an inline popup
|
|
499
|
-
|
|
500
|
-
The inline vs. portal behavior of the listbox popup has a particularly large impact on Combobox accessibility because keyboard focus does not enter the popup. This, coupled with the lack of support for `aria-owns` in Safari, means that iOS VoiceOver users will not be able to access the options unless they either swipe to the end of the DOM, or use touch exploration to try to find the popup on the screen.
|
|
501
|
-
|
|
502
|
-
If `inline` is set to true, the listbox will follow the trigger in the DOM, and swipe access will work.
|
|
503
|
-
|
|
504
|
-
The other scenario where `inline` is important is if the Combobox is used inside a modal of any sort. VoiceOver will not allow the cursor to leave a modal, so if the listbox is _not_ rendered inline, it will be fully impossible for an iOS VoiceOver user to use the combobox.
|
|
505
|
-
|
|
506
|
-
### Semantic structure
|
|
507
|
-
|
|
508
|
-
The Fluent Combobox uses the [ARIA 1.2 combobox pattern](https://www.w3.org/TR/wai-aria-1.2/#combobox), which differs significantly from ARIA 1.1. The ARIA 1.2 pattern has [better practical support](https://www.24a11y.com/2019/select-your-poison-part-2/), and as of writing, the 1.2 spec is headed towards Candidate Recommendation.
|
|
509
|
-
|
|
510
|
-
### Known issues
|
|
511
|
-
|
|
512
|
-
(TODO: expand this section with more testing once the Combobox implementation is stable)
|
|
513
|
-
|
|
514
|
-
Accessibility support for comboboxes in particular changes frequently, so known issues may quickly go out of date either by being fixed, or be being superceded by new issues. Here are some known accessibility bugs as of early 2022:
|
|
515
|
-
|
|
516
|
-
- NVDA does not read the value of the select-only Combobox
|
|
517
|
-
- VoiceOver on macOS does not consistently expose active options when arrowing through an open combobox
|
|
518
|
-
- `aria-multiselectable` is not announced by multiple screen readers
|
|
519
|
-
- Safari does not respect `aria-owns`, so someone using VoiceOver on iOS will not be able to swipe from the combobox trigger to the options unless `inline` is set to `true`.
|
|
520
|
-
- If the number of options in the listbox changes while it is open, that change is not consistently exposed by screen readers.
|