Skip to content

Commit 05da13b

Browse files
authored
Select spec (#20564)
1 parent a8158d3 commit 05da13b

1 file changed

Lines changed: 243 additions & 0 deletions

File tree

packages/react-select/Spec.md

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
# @fluentui/react-select Spec
2+
3+
## Background
4+
5+
The Select component allows users to select one value from a predefined set of values. It does so by providing a styled wrapper around the HTML `<select>` element. This means it inherits the dropdown UI and keyboard functionality from the platform.
6+
7+
Select is a more lightweight, accessible, and less feature-rich alternative to Combobox. It has better mobile support, and better cross-platform screen reader support. Unlike Combobox, it does not provide filtering, multiple selection, or virtualization. Select is recommended over Combobox when the following are true:
8+
9+
- The control is a basic single-select that matches the functionality of a `<select>`
10+
- Native-feeling cross platform UX (particularly on mobile) is a primary concern
11+
- Performance, accessibility, and bundle size are primary concerns
12+
13+
Combobox is recommended if any of the following are needed:
14+
15+
- Filtering or freeform text input
16+
- Virtualization
17+
- Control over styling the dropdown and options
18+
- Multiple selection
19+
20+
## Prior Art
21+
22+
The [Open UI research on Select](https://open-ui.org/components/select.research) combines both the ideas of the proposed Fluent Combobox and Select. There is also an [Open UI draft describing the select element](https://open-ui.org/components/select).
23+
24+
### Comparison of v8 and v0
25+
26+
`@fluentui/react` has three different controls that are different flavors of select/combobox:
27+
28+
- [Combobox](https://developer.microsoft.com/en-us/fluentui#/controls/web/combobox): an editable combobox with a textfield and dropdown listbox
29+
- [Dropdown](https://developer.microsoft.com/en-us/fluentui#/controls/web/dropdown): a non-editable combobox with dropdown listbox
30+
- [Pickers](https://developer.microsoft.com/en-us/fluentui#/controls/web/pickers): an editable combobox with greater customization, particularly in displaying selected items
31+
32+
`@fluentui/react-northstar` has one combobox control:
33+
34+
- [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
35+
36+
### Functional variations across v8 and v0 components
37+
38+
The main functional variants in existing components are as follows:
39+
40+
- Editable vs. non-editable: editable comboboxes have a textbox and allow the user to type, which optionally filters the listbox
41+
- Within editable comboboxes: freeform text input and filtering on input are optional
42+
- Within editable comboboxes: When a typed value does not match an option, it can be cleared or preserved on blur
43+
- Single vs. multiselect
44+
- Within multiselect: selected options may be presented as text within the combobox value, pills, or a custom render.
45+
46+
### Dropdown options variations across v8 and v0 Components
47+
48+
- Options may have an icon, image, text + description, or entirely custom render
49+
- Options may be grouped with a group header and divider
50+
- There may be a "load more results" action
51+
- Within multiselect: There may be a "Select all" option
52+
53+
## Sample Code
54+
55+
Default/standard Select:
56+
57+
```tsx
58+
<label htmlFor="selectID">Choose a color</label>
59+
<Select id="selectID">
60+
<option>Red</option>
61+
<option>Green</option>
62+
<option>Blue</option>
63+
</Select>
64+
```
65+
66+
Select with grouped options:
67+
68+
```tsx
69+
<label htmlFor="selectID">Choose an animal</label>
70+
<Select id="selectID">
71+
<optgroup label="Land">
72+
<option>Cat</option>
73+
<option>Dog</option>
74+
<option>Horse</option>
75+
</optgroup>
76+
<optgroup label="Water">
77+
<option>Dolphin</option>
78+
<option>Seal</option>
79+
<option>Shark</option>
80+
</optgroup>
81+
</Select>
82+
```
83+
84+
Inline Select with appearance and size set:
85+
86+
```tsx
87+
<label htmlFor="selectID">Choose a color</label>
88+
<Select id="selectID" appearance="filledDarker" size="small" inline>
89+
<option>Red</option>
90+
<option>Green</option>
91+
<option>Blue</option>
92+
</Select>
93+
```
94+
95+
Disabled Select with second option selected:
96+
97+
```tsx
98+
<label htmlFor="selectID">Choose a color</label>
99+
<Select id="selectID" disabled>
100+
<option>Red</option>
101+
<option selected>Green</option>
102+
<option>Blue</option>
103+
</Select>
104+
```
105+
106+
## Variants
107+
108+
### Layout
109+
110+
- Block (default)
111+
- Inline
112+
113+
### Size
114+
115+
- Small
116+
- Medium (default)
117+
- Large
118+
119+
### Appearance
120+
121+
- Filled darker
122+
- Filled lighter
123+
- Outline (default)
124+
- Transparent
125+
126+
### Unsupported Select variants
127+
128+
#### Multiple Selection
129+
130+
The Select component does not support multi-select, and does not support the native `multiselect` attribute. Multiple selection is instead provided through the Combobox component. This is because the native `<select multiple>` has poor accessibility and general UX, and we do not recommend using it. Additionally, because the options are not styleable, there is little benefit to using a wrapped `<Select multiple>` over using the native element directly.
131+
132+
#### Size attribute
133+
134+
For similar reasons to `multiple`, the native `size` attribute is not supported out of the box. It also has very limited styling support, and therefore also has little benefit over the native `<select size="N">`. The Listbox (TODO: confirm name) component is an alternative to using the `size` attribute on a `<select>`.
135+
136+
## API
137+
138+
From [Select.types.tsx](https://github.com/microsoft/fluentui/blob/master/packages/react-select/src/components/Select/Select.types.ts)
139+
140+
### Slots
141+
142+
In this component, `select` is the primary slot. Since `select` is primary, `root` is a separate explicit slot to customize the wrapper.
143+
144+
```ts
145+
export type SelectSlots = {
146+
/** Root of the component, renders as a `<span>`. */
147+
root: IntrinsicShorthandProps<'span'>;
148+
/** The actual `<select>` element */
149+
select: IntrinsicShorthandProps<'select'>;
150+
/** the icon, typically a down arrow */
151+
icon: IntrinsicShorthandProps<'span'>;
152+
};
153+
```
154+
155+
### Children
156+
157+
Children of the `Select` component are rendered as children of the internal `<select>` element. The only children that are supported in practice are the `<optgroup>` and `<option>` elements.
158+
159+
## Structure
160+
161+
- _**Public**_
162+
163+
```tsx
164+
<label htmlFor="selectID">Choose a color</label>
165+
<Select id="selectID" className="my-select-class">
166+
<option>Red</option>
167+
<option>Green</option>
168+
<option>Blue</option>
169+
</Select>
170+
```
171+
172+
- _**DOM**_
173+
174+
```html
175+
<label for="selectID">Choose a color</label>
176+
<span class="my-select-class">
177+
<select id="selectID">
178+
<option>Red</option>
179+
<option>Green</option>
180+
<option>Blue</option>
181+
</select>
182+
<svg><!-- icon --></svg>
183+
</span>
184+
```
185+
186+
## Migration
187+
188+
The Select component is a new approach that was not present in `@fluentui/react` v8, or `@fluentui/react-northstar`. It can be considered if the currently used control is the `@fluentui/react` Dropdown component, or the `@fluentui/react-northstar` Dropdown without `search`.
189+
190+
### Props
191+
192+
| v8 Dropdown | v0 Dropdown | Proposal |
193+
| -------------------- | ------------------------- | --------------------------------- |
194+
| options | items | children |
195+
| defaultSelectedKey | defaultValue | child with `selected` |
196+
| selectedKey | value | imperative ref.value |
197+
| id | n/a | id |
198+
| disabled | disabled | disabled |
199+
| required | n/a | required |
200+
| multiSelect | multiple | use Combobox |
201+
| placeholder | placeholder | child with `value=""` |
202+
| ariaLabel | n/a | aria-label |
203+
| n/a | aria-\* | aria-\* |
204+
| errorMessage | error | invalid, message handled in Field |
205+
| label, onRenderLabel | n/a | Handled in Field |
206+
| componentRef | n/a | ref |
207+
| n/a | popperRef, popper props | n/a |
208+
| calloutProps | list | n/a |
209+
| panelProps | n/a | n/a |
210+
| openOnKeyboardFocus | n/a | n/a |
211+
| n/a | a11ySelectedItemsMessage | n/a |
212+
| n/a | align | n/a |
213+
| n/a | autosize | n/a |
214+
| n/a | checkable | n/a |
215+
| n/a | clearable | n/a |
216+
| n/a | defaultHighlightedIndex | n/a |
217+
| n/a | defaultOpen | n/a |
218+
| n/a | fluid | default style |
219+
| n/a | headerMessage | optgroup child with `name` |
220+
| n/a | highlightFirstItemOnOpen | n/a |
221+
| n/a | highlightedIndex | n/a |
222+
| n/a | inline | inline |
223+
| n/a | inverted | n/a |
224+
| n/a | loading | n/a |
225+
| n/a | noResultsMessage | use children |
226+
| n/a | offset | n/a |
227+
| n/a | open | n/a |
228+
| n/a | position | n/a |
229+
| n/a | positionFixed | n/a |
230+
| n/a | search | use Combobox |
231+
| styles | styles | style |
232+
| onRenderCaretDown | toggleIndicator | use icon slot |
233+
| n/a | triggerButton | n/a |
234+
| onRenderContainer | n/a | n/a |
235+
| onRenderItem | renderItem | use children |
236+
| onRenderList | list slot | n/a |
237+
| onRenderOption | renderItem, headerMessage | use children |
238+
| onRenderPlaceholder | n/a | n/a |
239+
| onRenderTitle | n/a | n/a |
240+
241+
## Behaviors and Accessibility
242+
243+
This component makes use of the native `<select>` element, and inherits the native semantics and keyboard interactivity.

0 commit comments

Comments
 (0)