fluentui icon indicating copy to clipboard operation
fluentui copied to clipboard

react-combobox: add `allowFreeform` and update default input behavior

Open smhigley opened this issue 3 years ago • 5 comments

After chatting with design, we landed on the following behaviors for Combobox with typability:

  • All Comboboxes allow free user input while the combobox is focused
  • Combobox with allowFreeform={true} allows any user input to remain in the combobox input as the value when blurred. Unlike v8, this does not automatically add a new entry to the options list.
  • Comboboxes without allowFreeform will revert to the last selected value or no value when blurred
  • The current plan is to not support allowFreeform with multiselect, pending discussion (not included in this PR, and does not apply to pill select/pickers)

This is pretty different from Combobox in v8, which prevented user input without allowFreeform, at which point it also added options to the listbox. The rationale for changing it is that:

  1. Dropdown already covers the use case for a selection widget without typing input, and we want to be able to clearly define when to use each of our components and avoid blurred lines and overlap.
  2. Adding options to the combobox automatically with allowFreeform seemed weird to both Yvonne and myself, and it's very possible for authors to re-add that behavior if they want it.

Code-specific changes in this PR:

  • activeOption changes based on typing, and first tries to match options after the current active option
  • onOptionClick was moved to the option component, which allowed me to extend functions like setOpen and selectOption returned by the useComboboxBaseState hook from within useCombobox (this is why the context values changed)
  • I added a clearSelection function to useSelection, which is used when typing clears the current selection (e.g. fully erasing the input value). This will can be used by the "clear selection" button currently being prototyped in design, if we end up adding it.

smhigley avatar Jul 06 '22 20:07 smhigley

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-combobox
Combobox (including child components)
71.457 kB
23.361 kB
72.723 kB
23.746 kB
1.266 kB
385 B
react-combobox
Dropdown (including child components)
70.585 kB
23.22 kB
70.792 kB
23.233 kB
207 B
13 B
Unchanged fixtures
Package & Exports Size (minified/GZIP)
react-components
react-components: Accordion, Button, FluentProvider, Image, Menu, Popover
189.024 kB
51.924 kB
react-components
react-components: FluentProvider & webLightTheme
32.876 kB
10.773 kB
🤖 This report was generated against f17b8604209a099d354c212077832516dcfbbae2

fabricteam avatar Jul 06 '22 20:07 fabricteam

Perf Analysis (@fluentui/react-components)

No significant results to display.

All results

Scenario Render type Master Ticks PR Ticks Iterations Status
Avatar mount 1112 1149 5000
Button mount 840 844 5000
FluentProvider mount 1435 1399 5000
FluentProviderWithTheme mount 560 555 10
FluentProviderWithTheme virtual-rerender 591 564 10
FluentProviderWithTheme virtual-rerender-with-unmount 560 563 10
MakeStyles mount 1723 1693 50000
SpinButton mount 2176 2271 5000

fabricteam avatar Jul 06 '22 20:07 fabricteam

Asset size changes

Size Auditor did not detect a change in bundle size for any component!

Baseline commit: f17b8604209a099d354c212077832516dcfbbae2 (build)

size-auditor[bot] avatar Jul 06 '22 20:07 size-auditor[bot]

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit ccd4dbf0aab87920d375a1809e8ace4d0432b5e1:

Sandbox Source
@fluentui/react 8 starter Configuration
@fluentui/react-components 9 starter Configuration

codesandbox-ci[bot] avatar Jul 06 '22 20:07 codesandbox-ci[bot]

Hey Sarah, this looks great! Really happy with this direction for allowFreeform. Here is some design feedback/questions!

1. Selection by typing only works once

Here's what happens for me: I type "Cat" + EnterKey and it selects Cat and closes the popup. I clear the selection and type "Hamster" + EnterKey. Instead of selecting Hamster, it just opens the popup without selecting Hamster. If I blur away, the selection is cleared. When allowFreeform is on, the selection is a custom option even though there's an option that matches the typed value.

I played around with this a lot, and sometimes it works, sometimes it doesn't. No idea what causes the issue haha...

2. I can't use Space in the input area

Since SpaceKey is used as a selection key, I'm not able to type an actual space into the input area. Looks like v8 Combobox solves this by only having EnterKey as the selection key? Is that an ok solution?

3. Chevron should be clickable to trigger popup

Less about the typing interactions, but the user should be able to click the chevron to invoke the popup menu. If they don't invoke the popup via the chevron, the popup should only appear once the user starts typing in the input area or once they use Up/Down ArrowKeys.

Here's the Figma reference for this: https://www.figma.com/file/pI5m9e9hsNkl1odWzxCxNd/Dropdown?node-id=3205%3A28033

4. When allowFreeform is on, how do we account for custom options that match the first few characters of an existing option?

Currently, if I type "Ham" and tab away, it automatically selects Hamster. I'm wondering if we should only select an existing option on EnterKey, so that if a user wants to input "Ham" they can do so without it being overridden when they tab away. Right now, it seems like the only way it keeps "Ham" is if I blur by clicking away.

When allowFreeform is off, it makes sense to override input value with the closest matching option. But not sure if it's weird to have different interactions based on if this prop is on/off.

yvonne-chien-ms avatar Jul 07 '22 22:07 yvonne-chien-ms