On this page
Import
import { Combobox } from '@envsemble/envui';
Usage
Combobox takes its options as items, each with a value and a label, and optionally a description and start content, such as an Avatar; a ComboboxGroup puts items under a heading. An entry with an items array is a group, so an option has no field of that name.
- Control it with
value,nullfor none, andonValueChange, which receives the value and its item, or leave it uncontrolled withdefaultValue. label,descriptionanderrorwork as on TextField.clearableadds a clear button while there is a value, and Esc on the closed field clears it too. Beside chips, it shows with a mouse only while the field is under the pointer or has focus; on a touch screen it always shows.
import { useState } from 'react';
import { Avatar, Combobox, type ComboboxItem } from '@envsemble/envui';
const people: ComboboxItem[] = [
'Alex Morgan',
'Sam Lee',
'Priya Shah',
'Jordan Ellis',
'Taylor Kim',
'Riley Chen',
].map((name) => {
const handle = name.toLowerCase().replace(' ', '.');
return {
value: handle,
label: name,
description: `${handle}@example.com`,
start: <Avatar name={name} />,
};
});
export default function ChooseOwner() {
const [owner, setOwner] = useState<string | null>('alex.morgan');
return (
<div style={{ inlineSize: 'min(100%, 24rem)' }}>
<Combobox
label="Owner"
placeholder="Type a name"
description="The person who answers questions about the plan."
items={people}
value={owner}
onValueChange={setOwner}
clearable
/>
</div>
);
}Several options
With multiple, value is an array of values, each shown as a chip with a remove button, and the list stays open as people choose.
<Combobox
multiple
label="Reviewers"
placeholder="Add people"
items={people}
value={reviewers}
onValueChange={setReviewers}
/>
Search on a server
By default the list shows the options whose label or description contains the typed text, ignoring case and accents, in locale; filter takes a function of your own.
- With
filter={null}it showsitemsas given: search fromonInputValueChange, which receives the typed text. - Set
loadingwhile the search runs, which showsloadingLabelinstead ofemptyLabel. onOpenChangecan load the options as the list opens; its second argument,ComboboxOpenChangeDetails, says why it opens or closes.
<Combobox
label="Contact"
items={results}
filter={null}
onInputValueChange={setQuery}
loading={searching}
loadingLabel="Searching…"
emptyLabel={query ? 'No contacts found' : 'Type a name to search'}
value={contact}
onValueChange={setContact}
/>
In a form
name submits the value, or one entry for each chip, and a form reset restores defaultValue.
readOnlylets people focus the field and browse the list without changing the value.- Validation and its
errorbelong to the application, such as an error set on submit whennew FormData(form).getAll('topics')is empty.
<Combobox
multiple
name="topics"
label="Topics"
items={topics}
defaultValue={['accessibility']}
required
error={error}
/>
Sizes
sizeissm,mdorlg; without it, the field takes its container's control height.- With
visibleLabel={false}, aplaceholderand anaria-labelname it.
<Combobox
size="sm"
visibleLabel={false}
aria-label="Document"
placeholder="Document"
items={documents}
/>
Composition
The field is env-field with env-combobox: the control, env-combobox-control, holds the chips, env-combobox-chip, with their labels, env-combobox-chip-label, and remove buttons, env-combobox-chip-remove, IconButtons with a cross; then the input, env-combobox-input, the clear button, env-combobox-clear, and the trigger, env-combobox-trigger. The list is the shared popup, env-combobox-popup, and its options are its rows, env-combobox-item, with the check, env-combobox-item-indicator. className and style reach the field's root, and ref the input.
Customize
Its popup is frosted, as every popup is: --env-popup-opacity, --env-popup-blur and --env-popup-shadow, set on a theme, change it, as Popover describes.
Accessibility
You provide
- A
label, oraria-labelon a field without one. - The options, and with
filter={null}the search behind them. - Validation and its
errormessage. clearLabel,removeLabel,loadingLabelandemptyLabelin the application's language.
envUI provides
- The combobox pattern: a
comboboxfield with alistboxof options and the highlighted one as its active descendant. - The label, description and error tied to the field, and
aria-invalid. - Remove buttons named after their option, such as Remove Alex Morgan.
- A status that announces loading and no matches.
Props
Combobox
A text field that filters a list of options as people type, for choosing one option or several. Chosen options show as removable chips; keyboard, focus and announcements follow the WAI-ARIA combobox pattern.
| Prop | Type | Description |
|---|---|---|
ref | Ref< | The text input, so that a form library can register it and focus it. |
className | string | The field's class, on its root element, beside env-field and env-combobox. |
style | CSSProperties | Styles of the field's root element. |
itemsrequired | readonly Item[readonly ComboboxGroup< | The options, or groups of options under headings, in display order. |
filter | ComboboxFilter<null | Which options match the typed text: by default those whose label or description contains it, ignoring case and accents. null shows the items as given, for searching on the server. |
onInputValueChange | ( | Receives the typed text, and an empty string once it is cleared, such as to search a server. |
loadingDefault false | boolean | The options are loading: the popup shows loadingLabel instead of emptyLabel. |
loadingLabelDefault 'Loading…', or EnvUIProvider's messages.combobox.loading | ReactNode | Shown in the popup while loading. |
emptyLabelDefault 'No matches', or EnvUIProvider's messages.combobox.empty | ReactNode | Shown in the popup when no option matches. |
clearableDefault false | boolean | A clear button removes the value while there is one; Esc on the closed field clears it too. |
clearLabelDefault 'Clear', or EnvUIProvider's messages.combobox.clear | string | Accessible name of the clear button. |
removeLabelDefault Remove followed by the label, or EnvUIProvider's messages.combobox.remove | ( | Accessible name of a chip's remove button, from the chip's label. |
open | boolean | Whether the list is open; with `onOpenChange` it controls the popup. |
defaultOpenDefault false | boolean | Whether an uncontrolled list starts open; closed by default. |
onOpenChange | ( | Called as the popup opens and closes, and why, such as to load the options as it opens. |
locale | string | The locale of the default filter's matching: EnvUIProvider's, else the browser's. |
label | ReactNode | The field's visible name, such as Project name; it also names the control for assistive technology. |
description | ReactNode | Lasting guidance under the field, such as a format or a limit, linked to the control as its description. |
error | ReactNode | A message under the field that says how to correct the value. While it is set, the control is invalid (aria-invalid) and the message joins its description, after the description. |
size | 'sm''md''lg' | The control height, sm, md or lg; without it, the container's, and else md. sm is for a field with its label hidden. |
visibleLabelDefault true | boolean | The label shows in the field, where it rests while the field is empty and floats into the outline while the field is in use or has a value. false hides it, for a field whose purpose is clear without it, such as a search in a toolbar: the label still names the field for assistive technology, and a placeholder gives the visible guidance. |
multiple | boolean | Several options can be chosen; they show as chips in the field. |
value | stringnullreadonly string[ | The chosen option's value, or null for none. |
defaultValue | stringnullreadonly string[ | The value an uncontrolled field starts with, and that a form reset restores; none by default. |
onValueChange | (( | Receives the chosen value and its option, or null twice once the field is cleared. |
Also accepts the native props of <input>, such as ref, className and aria-* attributes.
Part names
Each part's class and state attributes are public and versioned, for an application's CSS to style.
env-combobox- The combobox field.
env-combobox-chip- A chosen value as a chip, in a multiple combobox.
env-combobox-chip-label- A chip's text.
env-combobox-chip-remove- The button that removes a chip.
env-combobox-clear- The button that clears the value.
env-combobox-control- The well that holds the chips, the input and the buttons.
env-combobox-empty- The message when no option matches.
env-combobox-end- The buttons at the end of the well.
env-combobox-group- A group of options.
env-combobox-group-label- A group's label.
env-combobox-input- The text input.
env-combobox-item- One option.
env-combobox-item-indicator- The check of a chosen option.
env-combobox-label- The label.
env-combobox-list- The list of options.
env-combobox-popup- The popup with the options.
env-combobox-start- The icon at the start of the well, or of an option in the popup.
env-combobox-status- The announcement of the number of options.
env-combobox-trigger- The button that opens the list.
env-combobox-value-icon- The chosen option's icon in the well.
data-action-count1·2on env-combobox-controldata-disabled- Any value, or present on env-combobox-item
data-popup-open- Any value, or present on env-combobox-trigger
data-selected- Any value, or present on env-combobox-item
Color properties
Each sets a color of one instance, through style or CSS; its hover, focus and press follow it. They are public and versioned.
--env-combobox-chip-container- The fill of a chosen option’s chip.
--env-combobox-chip-content- The chip's label and remove button.
Strings
EnvUIProvider's messages overrides each, and a component's own label prop wins over it.
messages.combobox.remove({ label }) => stringA chip's remove button, such as Remove Alex Morgan.messages.combobox.loading"Loading…"Shown in the popup while options load.messages.combobox.empty"No matches"Shown in the popup when no option matches.messages.combobox.clear"Clear"The clear button's name.
Changelog
- 1.0.0
showLabelisvisibleLabel, named after the label thatvisibleLabel={false}hides.hintisdescriptionandvariant="outlined"isvariant="outline".classNameandstylestyle the field's root rather than the input, which takesref. Read-only chips no longer carryaria-readonly, which the input reports. The popup is the shared popup and the options its rows, and a chip's remove button is an IconButton with a cross:env-combobox-wellisenv-combobox-control,env-combobox-optionenv-combobox-itemandenv-combobox-checkenv-combobox-item-indicator, and the icons at the start,env-combobox-leadingandenv-combobox-value-leading, areenv-combobox-startandenv-combobox-value-icon, as other components name their start slots. The loading, empty, clear and remove labels come from EnvUIProvider'smessages. An option'sleadingcontent isstart, as on List.Item.- 1.0.0-prerelease.6
The chevron turns over
--env-motion-duration-mediumwith--env-motion-ease-enteras the list opens, and back in--env-motion-duration-fastwith--env-motion-ease-exit, done when the list is.The list opens over
--env-motion-duration-medium, fading in and growing from 98 % with--env-motion-ease-enter, rather than growing from 96 % over the slow duration, so it shows from its first frames rather than late.The chevron turns half a circle as the list opens and closes, rather than flipping over.
Beside chips, the clear button shows with a mouse only while the field is under the pointer or has focus, and each chip's cross is a little smaller, so the field's end holds one cross at rest; the clear button and the chevron stand a step apart.
While its list is open, the field keeps its focused frame, the accent edge and label, also when focus is in the popup, as when it opens under the pointer.
An avatar in the field and in the options takes an avatar's small size, large enough for its initials, rather than a disc of its color alone; where initials don't fit, in a small field at the compact scale and in a chip, an avatar of initials is left out, while an icon, a photo or a figure stays. A read-only field keeps its chevron, muted, as a read-only Select does.
A multiple field stays one row tall while its chips fit there; the input moves to a row of its own only once its text no longer fits.
The
floatingvariant and thevariantprop are gone: the field is outlined, and takessize="lg"in a long form on a page. The field takes a text area's rounded corners rather than round ends. A small one with a visible label takes the medium height, so its floated label and its value each have room, and says so in the console while developing:smis for a field with its label hidden.- 1.0.0-prerelease.5
The popup is frosted: the popup's color lets a little of what is behind through, blurred, with a soft shadow and no outline edge but a faint hairline in dark, and is solid with its edge at high contrast and with reduced transparency. Options are the md control height in body text, chosen ones take the selection's fill as well as their check mark, and groups part by space. Group labels sit a little ahead of the rows, and options lie one under the next with no space between them. A chosen option's check mark ends its row, after the label.