AutoComplete
Suggest as they type.
About
Suggest-as-you-type text field. The typed substring renders in bold in every match. By default it filters options itself; a host that fetches sets externalFilter and answers suiSearch. With multiple each pick becomes a removable chip before the query. Form-associated: posts the typed text, or one entry per value.
Usage
Basic
The field is a combobox with aria-autocomplete="list" that points at the active suggestion through aria-activedescendant. The panel opens only once there is text to suggest against, on typing or ArrowDown.
Matches and no matches
The typed substring renders in bold. When nothing matches, emptyFilterMessage takes the panel and says No matches. A panel opened over no suggestions at all shows emptyMessage, which says Nothing here yet: an empty list and a search that found nothing are two states, and one sentence cannot be right about both.
Dropdown button
dropdown draws a chevron button after the text that opens the panel with every option, no typing needed, and fires suiSearch with the reason dropdown so a host that fetches can answer with the full list. clearable draws a Clear button beside it; both are real buttons, so Tab reaches them.
Opening on focus
A field that already holds text opens nothing when it takes focus, so tabbing through a form never drops a list over the next field; typing, ArrowDown or the dropdown button open it. open-on-focus, on the second field, opens it on focus too, for a field people pick from again.
Object and grouped options
An option object is { label, value, disabled }: the field shows and posts the label, and suiSelect reports the value, so a host can keep the id. A group is { label, items } and draws an eyebrow header over the rows that match.
Several values
multiple turns each pick into a chip, and value becomes the list of picked values: the chip shows the name, the form posts the address. A pick empties the query and keeps the list open; a checked row picked again leaves, as Backspace in an empty query does. allow-custom on Cc takes a typed address; max caps it at five.
As a property
variant="quiet" draws the text as it is in the surrounding font, with no shell at rest: the fill and the Clear and Show options buttons come on hover, and the shell while the field has focus or the panel is open, since a focused text field is being typed into. The label is not drawn but still names the field.
Force selection
forceSelection lets only a suggestion stand: when the text commits, a label match (ignoring case) is picked as that suggestion and anything else is wiped. The wipe is an edit the element made, so suiInput reports the empty text and suiChange commits it. Type a name that is not on the list and leave the field.
Loading and sizes
While loading is set a spinner sits at the end of the field and the panel shows the loading row instead of rows. size is the same sm, md, lg vocabulary and the same 28, 34, 42 heights as the rest of the control family.
States
An error replaces the help line, paints the danger border and sets aria-invalid; invalid is the border alone, for a value the host checks on save. A disabled field posts nothing and never holds the form.
Remote suggestions
Set external-filter when the host answers suiSearch with the server's own result for that query, because filtering a fuzzy remote answer again on the client would drop rows the server returned. Try typing dentist.
A long list
From virtualScrollThreshold suggestions, 200 by default, the panel draws only the rows near the view and stands the rest in a blank the height of the list. The Show options button browses all five thousand; the arrows and the position a screen reader reads still count over every one.
Read-only
readonly forwards to the native input, opens nothing, keeps the dropdown and clear controls off, and the text still posts.
Empty list
emptyMessage is the row for a suggestion list with nothing in it, as when a fetch has not answered yet; emptyFilterMessage is the row for typed text that matches nothing, which the Matches and no matches example shows.
In a form
The typed text posts under the host name through ElementInternals. An emptied field posts an empty string rather than dropping the key.
Events
suiInput fires on every change of the text, a keystroke or a pick that writes the label, suiSelect when a suggestion is picked, and suiChange when the text commits. suiOpen fires after the element opens the panel, and the cancelable suiClose fires before it closes with a reason of pick, escape, outside or cancel.
Keyboard
| Key | Action |
|---|---|
| ArrowDown ArrowUp | Opens the panel when there is text to suggest against, or with dropdown set, opens every option from an empty field. Once open, moves the active suggestion, skipping disabled ones and wrapping at either end. |
| Enter | Picks the active suggestion. With none active, commits the typed text and closes the panel; with forceSelection set, the text must match a suggestion or it is wiped. In a multiple field it adds the active suggestion, or removes it when it is already picked, and keeps the panel open; with none active, text that spells a suggestion is picked, and other text is added only under allowCustom. |
| Backspace | In a multiple field with an empty query, removes the last chip. |
| Escape | Closes the panel and leaves the text as typed. |
| Tab | Closes the panel, then reaches the Clear and Show options buttons when they are drawn, before moving on. Shift+Tab from a multiple field reaches the remove button on each chip. |
API
<sui-auto-complete>
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
allowCustom | allow-custom | boolean | false | Multiple field only: typed text that matches no suggestion can be added as a value of its own, with Enter or by leaving the field. Off by default, so every value comes from the suggestions and a stray Enter adds nothing. Text that equals a suggestion's label, ignoring case, is always picked as that suggestion; text left over that nothing took is cleared when the field loses focus. |
clearable | clearable | boolean | false | X button after the text that empties the field and commits the empty value. On a multiple field it removes every chip and the query. |
disabled | disabled | boolean | false | Disables the field. A disabled field posts nothing and never holds the form. |
dropdown | dropdown | boolean | false | Chevron button after the text that opens the panel with every option, no typing needed. It fires suiSearch with the reason dropdown, so a host that fetches can answer with the full list. |
emptyFilterMessage | empty-filter-message | stringstring | undefined | Row shown when the filter matched nothing. An empty list and a search that found nothing are different states and one sentence cannot be right about both: "Nothing here yet." is wrong over a list of two hundred the reader has just narrowed to none. | |
emptyMessage | empty-message | stringstring | undefined | Row shown when the suggestion list is empty. | |
error | error | stringstring | undefined | Error message under the field; paints the danger border and sets aria-invalid. | |
externalFilter | external-filter | boolean | false | The host filters: the panel shows options as given, with no match test of its own. Set it when the host answers suiSearch with the server's own answer for that query: a remote result is often a fuzzy or semantic match, and filtering it again on the client would drop rows the server returned. Off by default, so the field filters options by the typed text. |
forceSelection | force-selection | boolean | false | Single field only: only a suggestion may stand. When the text commits (Enter with no row active, or leaving the field), text that equals a suggestion's label, ignoring case, is picked as that suggestion; anything else is wiped and an empty value commits. The wipe is an edit the element made, so suiInput reports the empty text before suiChange commits it. A multiple field takes only suggestions unless allowCustom is set. |
help | help | stringstring | undefined | Help text under the field. Replaced by error when set. | |
invalid | invalid | boolean | false | Danger border without a message, for a value the host checks against its own list on save. |
label | label | stringstring | undefined | Label above the field. Without one the field takes the host's aria-label or aria-labelledby as its name; a visible label wins over both. | |
loading | loading | boolean | false | Shows the suggestions are still on their way: a spinner sits at the end of the field and the panel shows the loading row instead of rows. Set it while fetching, clear it when options land. |
loadingMessage | loading-message | stringstring | undefined | Text of the loading row. | |
max | max | numbernumber | undefined | Multiple field only: the most values it takes. At the limit the suggestions not yet picked are disabled and a screen reader hears that the limit is reached. A fractional value is floored; anything below 1, or none, means no limit. | |
multiple | multiple | boolean | false | Picks several values instead of one. value is then an array of option values, each drawn as a removable chip before the query box. A pick adds its value, empties the query and leaves the panel open for the next one; a picked suggestion carries a check, and picking it again removes it. Backspace in an empty query removes the last chip. |
name | name | stringstring | undefined | Form control name; a multiple field posts one entry per value under it. Reflected: the form entry is built from the content attribute. | |
open | open | boolean | false | Opens the suggestion panel. Mutable and the single source of truth: while it is true the panel is rendered and aria-expanded is 'true'. The element opens itself only when there is text to suggest against, or from the dropdown button, announces that with suiOpen, and asks with the cancelable suiClose before it closes itself on pick, outside click, Escape, Tab, an emptied field and a form reset. A multiple field stays open on a pick and on an emptied query, and with an empty query it lists every suggestion. |
openOnFocus | open-on-focus | boolean | false | Opens the suggestions when the field takes focus while it holds text. Off by default: tabbing through a form shows only the field, so a list never covers the next one, and the suggestions open on typing, ArrowDown or the dropdown button. Set it for a field whose job is to be picked from again, a recent search say. A multiple field, whose query is empty when focus arrives, opens with every suggestion. |
options | property only | SuiAutoCompleteEntry[] | [] | Suggestion pool: strings, { label, value, disabled } objects, or { label, items } groups whose items are either. A single field shows and posts the label and suiSelect reports the value; a multiple field holds and posts the value and draws the label on its chip. Property, not attribute. |
placeholder | placeholder | stringstring | undefined | Text shown while the field is empty. A multiple field shows it only while it holds no chip. | |
readOnly | readonly | boolean | false | Display only: the text and chips can be read and copied but not edited, the panel never opens, and the field still posts its value. Neither a read-only nor a disabled field holds the form on valueMissing. |
required | required | boolean | false | Marks the field required for form validation: a single field needs text, a multiple field at least one value. |
size | size | "lg" | "md" | "sm" | 'md' | Field height: sm 28, md 34 (default), lg 42, from the --control-* tokens. A multiple field grows past it when its chips wrap. In the quiet variant it is the height of the box that paints on hover and while the field is in use; the text keeps the surrounding font. |
tone | tone | "inverse" | undefined | Ink for the quiet variant on the brand chrome. inverse takes the inverse inks, the inverse hover wash and the inverse focus colour, as sui-button's tone of the same name does, so the value reads on a tone="brand" toolbar. Opening the field shows its shell in the card's own inks. The default variant ignores it. | |
value | value | SuiAutoCompleteValueSuiKey[] | string | '' | The field's value. A single field holds its text, typed or picked: a pick writes the option's label here. A multiple field holds the picked option values, in the order they were added and each as its option gives it (a number stays a number), as an array property; anything that is not an array reads as no values. Mutable; written before suiInput or suiChange fires. |
variant | variant | "default" | "quiet" | 'default' | default draws the field shell. quiet draws the text, or the chips, as they are in the surrounding font, with no border or fill at rest, for a record's properties column: the fill comes on hover, the Clear and Show options buttons show on hover, and the shell while the field has focus or the panel is open, since a focused text field is one being typed into. The label is not drawn but still names the field, so the host prints the property name. Typing, the keyboard, events, validation and the form post are the same in both. Anything else falls back to default. |
virtualScrollThreshold | virtual-scroll-threshold | number | 200 | Suggestion count at which the panel starts mounting only the rows near the viewport instead of all of them, so a list of exactly this many is windowed. The keyboard, the ids and the counts a screen reader reads still cover every suggestion. Set it to 0 to keep every row in the DOM whatever the list costs, or to 1 to window a short list under test. |
Events
| Event | Detail | React | Vue | Description |
|---|---|---|---|---|
suiBlur | void | onSuiBlur | @sui-blur | Fires when the input loses focus; no detail. Does not bubble, like the native blur. |
suiChange | SuiAutoCompleteValueSuiKey[] | string | onSuiChange | @sui-change | Fires when the value commits; detail is the new value. Single field: the text, when it commits (pick, Enter, or leaving the field with a changed value). Multiple field: the full array of values, on every value added or removed. |
suiClose | SuiCloseReason"cancel" | "close-button" | "escape" | "outside" | "pick" | "scrim" | "trigger" | onSuiClose | @sui-close | Fires before the element closes the panel itself; detail is 'pick' | 'escape' | 'outside' | 'trigger' | 'cancel' ('pick' covers both picking a suggestion and committing the typed text with Enter, 'trigger' the dropdown button on an open panel, 'cancel' a form reset, a clear or an emptied field, 'outside' an outside pointer and Tab). Cancelable: preventDefault() keeps it open. Does not bubble: a preventDefault() in a dialog's own suiClose listener cannot veto this one. |
suiFocus | void | onSuiFocus | @sui-focus | Fires when the input takes focus; no detail. Every text field carries the same pair, so a host arms a hint or a launcher the same way on each without listening for the native focusin. Does not bubble, like the native focus. |
suiInput | string | onSuiInput | @sui-input | Fires when the text changes; detail is the text. On a multiple field the text is the query, and the values travel on suiChange. The element's own edits count as well as keystrokes: a pick that writes or empties the text, Clear, and a forceSelection wipe. |
suiOpen | void | onSuiOpen | @sui-open | Fires after the element opens the panel itself (typing, ArrowDown, the dropdown button, or focus under openOnFocus). Does not bubble, so a dialog around the field never takes it for its own. |
suiSearch | SuiAutoCompleteSearchDetail | onSuiSearch | @sui-search | Fires when the field asks for suggestions; detail is { query, reason }. reason is input on each keystroke, with the typed text (a multiple field's query), and dropdown when the Show options button, or ArrowDown on an empty field, asks for every option, with the text in the field. A host that fetches answers it by setting options, usually with externalFilter set so the answer shows as given. The element's own edits (a pick, Clear) do not ask. |
suiSelect | SuiKeynumber | string | onSuiSelect | @sui-select | Fires when a suggestion is picked (click, Enter, or a label match when the text commits); detail is the option's value: the string itself, or value of an object option, as given. A multiple field fires it for each value added from the suggestions, not for one removed or added as typed. |
Methods
| Method | Signature | Description |
|---|---|---|
setFocus() | setFocus() => Promise<void> | Moves keyboard focus into the field, as el.focus() does. |
Types
SuiAutoCompleteEntry typeOne entry of options: a string, an option object, or a group. | |||
|---|---|---|---|
| No members. |
SuiAutoCompleteGroup interfaceA group: its header label and the suggestions under it. Groups never nest. | |||
|---|---|---|---|
label | string | ||
items | SuiAutoCompleteOptionInput[] | ||
SuiAutoCompleteOption interfaceA suggestion with an identity of its own: label is what the field shows, value is what suiSelect reports and a multiple field holds, as given: a number stays a number. | |||
|---|---|---|---|
label | string | ||
value | SuiKey | ||
disabled? | boolean | ||
SuiAutoCompleteOptionInput type | |||
|---|---|---|---|
| No members. |
SuiAutoCompleteSearchDetail interfaceWhat suiSearch carries: the text to answer and why the field asks. | |||
|---|---|---|---|
query | string | The typed text (a multiple field's query), or the text in the field when the dropdown asks. | |
reason | SuiAutoCompleteSearchReason | ||
SuiAutoCompleteSearchReason typeWhy the field asks for suggestions: input for typed text, dropdown for the Show options button, which asks for every option. | |||
|---|---|---|---|
| No members. |
SuiAutoCompleteValue typeThe field's value: its text in a single field, the picked values in a multiple one. | |||
|---|---|---|---|
| No members. |
SuiCloseReason typeWhy a dismissible surface is closing. Detail of the cancelable suiClose. A consumer expresses "a stray backdrop click must not close this" by calling preventDefault() on the reason it does not accept, which is why none of these needs a prop of its own. | |||
|---|---|---|---|
| No members. |
SuiKey typeA record's or an item's key wherever the library identifies one: a row, a tree node, a list item, a selected value. Numbers stay numbers, so a numeric id round-trips through selection, the events and a framework binding without turning into a string. | |||
|---|---|---|---|
| No members. |
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.
Color23
Typography1
Spacing and size5
Radius2
Elevation2
Motion3
Every name above is listed with its value and its role in Foundations.