组件 · 输入
ComboboxSelect
A ready-made searchable select driven by an array of options, for one or a few of many values, with groups, remote search and creation.
import { ComboboxSelect } from "@botiverse/raft-ui/wip";ComboboxSelect is a field at the control height (44px on a phone, 32px on a desktop) that people type into to find one or a few values in a long list, on a phone as on a desktop. It is for filtering, searching a server and creating values; a field people only pick from is a Select. It takes an array of options, flat or grouped, and builds the field, the list, the chips and the empty and loading lines from it. It is exported from @botiverse/raft-ui/wip, and its API can change in any release.
When to use
The full choice between pickers is in Choosing a component.
| Situation | Use |
|---|---|
| One of many values, with search | ComboboxSelect |
| A few of many values (people, agents, labels) | ComboboxSelect with multiple |
| Values that come from a server as people type | ComboboxSelect with remote |
| One of up to 10 values, or any value picked without typing | Select |
| A filter over a list, or a layout the options array can't express | Combobox |
Variants
| Variant | Use for |
|---|---|
| Single (default) | One value. The list shows a check mark on the current value |
multiple | A few values. Each chosen value becomes a chip in the field |
| Grouped options | Values that belong together, such as models by provider. Group labels head each group |
remote with onSearch | Results the caller fetches. The component shows them without filtering |
create | Values people can add by typing a new one |
States
- Loading:
loadingshows a loading line in the list. Keep the list open while a choice is being saved, and show it withloading. - Not loaded yet:
fallbackOptiongives a label to a chosen value whose option hasn't arrived, so the field stays readable. - Invalid:
status="error"oraria-invalidgives the field adanger-strongborder. - No match: the list says so in one line. Don't leave an empty popup.
Behavior
- Filter the options as people type, unless
remoteis set. - With
multiple, keep the list open when a value is chosen; clicking outside or Esc closes it. Typing continues after the last chip. - An option is as tall as its content: one line is 36px, and a second line adds only its own height, with the same space above and below the text (Forms).
- A long option wraps to two lines, then truncates; a long chip truncates at the width of the field. Each has its whole text as its
titlewhile it is cut off (Forms). - A chip, the clear button and the toggle sit 6px inside the field's outer edge and 6px apart: 20px on a desktop and 32px on a phone, so the field keeps its height with chips in it. They wear
radius-chip, like every control embedded in a frame; a chip's remove button wearsradius-sticker2px inside the chip, with its focus ring drawn inside it (Shape). - With
maxTagCount, chips beyond the count collapse into a count while the field is not focused. All of them come back on focus. - The list grows to 16rem (256px), its 4px padding above and below included: six 36px rows and part of a seventh, which shows there are more. Then it scrolls.
listMaxHeight(a CSS length, or pixels, measured the same way) moves that cap, andlistMaxHeight="16rem"is the same as leaving it out. Raise it where the field has a tall space of its own below it, such as a tall bottom Drawer; lower it when the list would cover something people need to see while they choose.
On a phone
A phone here is a touch screen narrower than the desktop layout, (width < 48rem) and (pointer: coarse). ComboboxSelect is the same text field there as on a desktop, because typing is what it is for: a tap focuses it and brings up the keyboard, typing filters the list, and create and remote work in the field. There is no bottom sheet. When people only pick a value and never need to type, use a Select instead: it opens without the keyboard.
- The list always opens below the field, between the field and the keyboard, as a native autocomplete does, and never flips. Which side has more room depends on whether the keyboard happens to be up, so a list that chose the roomier side opened downward one time and upward the next on the same field. When fewer than three rows fit below, the field scrolls up to the top of what is visible instead. As the keyboard comes up or goes, the address bar moves, or the filtered list shrinks and grows, only the list's height changes: the field stays where it is.
- The input stays at 16px or more at every
size, so iOS doesn't zoom into it. size="lg"is a 52px field with 40px chips and buttons, 6px inside it;size="sm"is a 28px field with 22px chips and buttons, 3px inside it, as close as a segmented control's items sit to their track.- Inside a bottom Drawer, give the drawer a height that doesn't follow the keyboard (
lvh, notdvh) and room below the field for the list, and raiselistMaxHeightwhen the drawer is tall.
This is for finding a value in a list. Combobox, the free-text field for mentions and tags, will get its own phone pattern: the input pinned at the top of a sheet or a full screen, with the suggestions between it and the keyboard.
Content
- Write the placeholder as what to do: Choose a model.
- Write the empty line as what found nothing: No models match "zz".
Accessibility
ComboboxSelect wraps Base UI Combobox: a text input with role="combobox" that controls a listbox.
- Name the field with a
FieldLabel(Field) whosehtmlFormatches itsid, or witharia-label. - Left Arrow at the start of the input moves focus to the chips, and Backspace or Delete removes the focused chip. Each remove button is named after its value (Remove Bugen).
- On a phone the field is the same text input, named the same way.
- Translate these announcements with
messageswhen the interface is not in English.
API
ComboboxSelect
| Prop | 类型 | 默认值 |
|---|---|---|
| boolean | false | |
| boolean | true | |
| Alias for create, useful when matching Select libraries that call this mode creatable. | boolean | |
| boolean | false | |
| NonNullable<ComboboxSelectSelection<Multiple>> | ||
| keyof Option | "disabled" as keyof Option | |
| ReactNode | "No options found" | |
| Supplies labels for values that have not been loaded yet. | (value: ComboboxSelectValue) => Option | |
| false | ((query: string, option: Option) => boolean) | ||
| boolean | true | |
| Omit<AutocompleteInputProps, "defaultValue" | "value" | "children" | "size"> | ||
| keyof Option | "label" as keyof Option | |
| The tallest the list gets before it scrolls, its 6px padding above and below included: a CSS length, or a number of pixels. On a phone the list also gets shorter to fit the room on its side, and opens above when that side has more room and below is short of this height. | string | number | "16rem" |
| boolean | false | |
| ReactNode | "Loading…" | |
| Collapse chips when the control is unfocused; all remain reachable when focused. | number | |
| Partial<ComboboxSelectMessages> | ||
| NonNullable<Multiple> | ||
| () => void | ||
| Called only when the creation row is selected. Return null to reject creation. | (query: string) => Option | null | |
| (query: string) => void | ||
| (value: ComboboxSelectSelection<Multiple>, options: Multiple extends true ? (Option | undefined)[] : Option | null | undefined, details: BaseCombobox.Root.ChangeEventDetails) => void | ||
| readonly (Option | ComboboxSelectGroup<Option>)[] | ||
| string | "Select an option" | |
| Omit<AutocompletePopupProps, "children"> | ||
| AutocompletePortalProps | ||
| Omit<AutocompletePositionerProps, "children"> | ||
| Display the provided results without local filtering. Requests belong to the caller. | boolean | false |
| (query: string) => ReactNode | defaultRenderCreateLabel | |
| (option: Option) => ReactNode | ||
| Customizes option content while preserving the Base UI option element. | (option: Option, info: { selected: boolean; }) => ReactNode | |
| Customizes chip content while preserving keyboard navigation and removal. | (option: Option) => ReactNode | |
| boolean | true | |
| "sm" | "md" | "lg" | "md" | |
| "warning" | "error" | ||
| NonNullable<ComboboxSelectSelection<Multiple>> | ||
| keyof Option | "value" as keyof Option | |
| Provides a hint to the browser for autofill. | string | |
| Whether the first matching item is highlighted automatically while filtering. | boolean | true |
| The uncontrolled input value when initially rendered. | string | number | readonly string[] | |
| Whether the popup is initially open. | boolean | false |
| Whether the component should ignore user interaction. | boolean | false |
| Identifies the form that owns the internal input. Useful when the combobox is rendered outside the form. | string | |
| The input value of the combobox. Use when controlled. | string | number | readonly string[] | |
| Identifies the field when a form is submitted. | string | |
| Event handler called when the input value changes. | (inputValue: string, eventDetails: BaseCombobox.Root.ChangeEventDetails) => void | |
| Event handler called when the popup is opened or closed. | (open: boolean, eventDetails: BaseCombobox.Root.ChangeEventDetails) => void | |
| Event handler called after any animations complete when the popup is opened or closed. | (open: boolean) => void | |
| Whether the popup is currently open. Use when controlled. | boolean | |
| Whether the user should be unable to choose a different option from the popup. | boolean | false |
| Whether the user must choose a value before submitting a form. | boolean | false |
Also takes the attributes of its element.
相关组件
改动
- 0.12.0 · Breaking Changes
ComboboxSelectalways takes typing on a phone, as on a desktop: tapping the field focuses it and typing filters;createand remote search work in the field. The phone-only pick-only mode and bottom sheet from 0.10.5 are gone, with their propssheetThreshold,sheetTitleandmessages.search/done/close. A pick-only field usesSelect. The list still picks its side once and doesn't flip while the keyboard opens. - 0.12.0 · Added
ComboboxSelecttakeslistMaxHeight(a CSS length or pixels, default16rem, the whole list's height); the side the list opens on follows it. - 0.10.5 · Added
ComboboxSelecttakessheetThreshold(default 10) andsheetTitle, and itsmessagestakesearch,doneandclosefor the phone's bottom sheet. - 0.10.5 · Fixed
ComboboxSelecton a phone (a touch screen under 48rem) no longer focuses a text input and raises the keyboard when people only pick a value. Up tosheetThresholdoptions open as an anchored list that picks its side once and doesn't flip while the keyboard or the address bar moves; more options,createand remote search open a bottom sheet with the search input at its top. Desktop and touch tablets are unchanged. - 0.10.0 · Breaking ChangesField frames (
Input,Textarea,InputGroup,Select,Combobox,ComboboxSelect,Composer, optionCard,SearchTrigger) are drawn at 1px inline-fieldinstead of 1.5px, on the phone too. - 0.10.0 · Changed
Tooltip,ComboboxSelectoptions,StepsandTimelineuse the type scale instead of fixed sizes, so they follow the desktop values.