Input · AutoComplete

AutoComplete

The input box is automatically filled.

When to use

Used to provide input suggestions to the input box and perform automatic completion operations

The difference with the searchable Select component:

  • AutoComplete is essentially an enhanced Input component that provides input suggestions, while Select is a selector
  • When you click to expand, Select will clear all the values in the input box, and AutoComplete will keep the last selected value
  • Select's selected item rendering can be any snippet content, while the renderSelectedItem of AutoComplete may only return a string

Demos

How to import

<script lang="ts">
    import { AutoComplete } from '@fibrae/semi-ui-svelte';
</script>

Basic usage

Monitor user input through onSearch, pass input suggestions through data, and keep the value with bind:value, which updates when the input box changes or an input item is selected. There is no defaultValue: a one-way value={x} only seeds the input, and bind:value={get, set} makes it fully controlled

当前输入:

Code
<script lang="ts">
    import { IconSearch } from '@fibrae/semi-icons-svelte';
    import { AutoComplete } from '@fibrae/semi-ui-svelte';

    let stringData = $state<string[]>([]);
    let value = $state<string | number>('');

    const handleStringSearch = (input: string) => {
        stringData = input ? ['gmail.com', '163.com', 'qq.com'].map((domain) => `${input}@${domain}`) : [];
    };
</script>

<AutoComplete bind:value data={stringData} onSearch={handleStringSearch} placeholder="搜索... " showClear style="width: 200px">
    {#snippet prefix()}
        <IconSearch />
    {/snippet}
</AutoComplete>
<p>当前输入:{value}</p>

Custom option rendering

When you need to customize the rendering of candidates, data can be passed in an array of objects (each Object contains two keys, label and value; value is the value selected by the candidate, and label is the text displayed by the candidate, which falls back to value when missing)
The content of a candidate can be customized through the item snippet, which receives { item, index }: item is the data item as given, so keep only data in the items and write the markup in the snippet

Code
<script lang="ts">
    import { IconSearch } from '@fibrae/semi-icons-svelte';
    import { AutoComplete, Avatar } from '@fibrae/semi-ui-svelte';

    interface ListItem {
        name: string;
        email: string;
        abbr: string;
        color: 'amber' | 'indigo' | 'blue' | 'cyan';
        value?: string;
        label?: string;
    }

    const list: ListItem[] = [
        { name: '夏可漫', email: 'xiakeman@example.com', abbr: 'XK', color: 'amber' },
        { name: '申悦', email: 'shenyue@example.com', abbr: 'SY', color: 'indigo' },
        { name: '曲晨一', email: 'quchenyi@example.com', abbr: 'CY', color: 'blue' },
        { name: '文嘉茂', email: 'wenjiamao@example.com', abbr: 'JM', color: 'cyan' },
    ];

    let data = $state<ListItem[]>([]);

    const handleStringSearch = (value: string) => {
        data = value ? list.map((item) => ({ ...item, value: item.name, label: item.email })) : [];
    };

    const renderSelectedItem = (option: ListItem) => option.email;
</script>

<AutoComplete aria-label="搜索邮箱" {data} onSearch={handleStringSearch} {renderSelectedItem} showClear style="width: 280px">
    {#snippet prefix()}
        <IconSearch />
    {/snippet}
    {#snippet item({ item })}
        <Avatar color={item.color} size="small">{item.abbr}</Avatar>
        <div style="margin-left: 4px">
            <div style="font-size: 14px; margin-left: 4px">{item.name}</div>
            <div style="margin-left: 4px">{item.email}</div>
        </div>
    {/snippet}
</AutoComplete>

Get user input value from onSearch, update data dynamically, update loading

Size

The size of the input box can be set by setting size, optional small, default (default), large





Code
<script lang="ts">
    import { AutoComplete } from '@fibrae/semi-ui-svelte';

    const data = [1, 2, 3, 4];
</script>

<div>
    <AutoComplete {data} placeholder="small" size="small" style="width: 200px" />
    <br />
    <br />
    <AutoComplete {data} placeholder="default" size="default" style="width: 200px" />
    <br />
    <br />
    <AutoComplete {data} placeholder="large" size="large" style="width: 200px" />
</div>

The position of the drop-down menu

The position of the drop-down menu can be set by setting position, and the optional values refer to Tooltip position

Code
<script lang="ts">
    import { AutoComplete } from '@fibrae/semi-ui-svelte';

    let data = $state<string[]>([]);

    const change = (input: string) => {
        data = input ? ['gmail.com', '163.com', 'qq.com'].map((domain) => `${input}@${domain}`) : [];
    };
</script>

<div>
    <AutoComplete {data} onSearch={change} placeholder="选项菜单在上方显示" position="top" style="width: 200px; margin: 10px" />
    <AutoComplete {data} onSearch={change} placeholder="选项菜单在右侧显示" position="rightTop" style="width: 200px; margin: 10px" />
</div>

Disabled

Code
<script lang="ts">
    import { AutoComplete } from '@fibrae/semi-ui-svelte';

    const data = [1, 2, 3, 4];
</script>

<AutoComplete {data} disabled placeholder="禁用下拉菜单" style="width: 200px" />

Validate status

Different verification states can be set to show different styles





Code
<script lang="ts">
    import { AutoComplete } from '@fibrae/semi-ui-svelte';

    let warning = $state('ies');
    let error = $state('ies');
    let normal = $state('ies');
</script>

<AutoComplete aria-label="Warning status" bind:value={warning} validateStatus="warning" />
<br />
<br />
<AutoComplete aria-label="Error status" bind:value={error} validateStatus="error" />
<br />
<br />
<AutoComplete aria-label="Default status" bind:value={normal} />

Custom empty content

Can set up custom display empty content

Code
<script lang="ts">
    import { IllustrationNoContent } from '@fibrae/semi-illustrations-svelte';
    import { AutoComplete, Empty } from '@fibrae/semi-ui-svelte';

    let data = $state<number[]>([]);
    let loading = $state(false);

    const fetchData = (input: string) => {
        loading = true;
        setTimeout(() => {
            data = input ? Array.from({ length: 5 }, () => Math.random()) : [];
            loading = false;
        }, 1000);
    };
</script>

<AutoComplete aria-label="搜索" {data} {loading} onSearch={fetchData}>
    {#snippet emptyContent()}
        <Empty style="padding: 12px; width: 300px">
            {#snippet image()}
                <IllustrationNoContent style="width: 150px; height: 150px" />
            {/snippet}
            {#snippet description()}暂无内容{/snippet}
        </Empty>
    {/snippet}
</AutoComplete>

API reference

Props

PropertyDescriptionTypeDefault
autoAdjustOverflowWhether the dropdown flips automatically when it would be clipped.boolean-
autofocusWhether to focus the input after mount.booleanfalse
clearIconSnippet for the custom clear icon, effective when showClear is true.Snippet-
dataData source of the candidates: an array of strings, numbers or objects. An object item uses value as the picked value and label as its text (value when label is missing); its disabled, class, style and data-* fields go to the matching row, where class takes a string, array or object and style is a string. Use the item snippet for markup.T[][]
defaultActiveFirstOptionWhether the first candidate is highlighted when the panel opens, so that Enter picks it directly.booleanfalse
defaultOpenWhether the dropdown panel is open on mount; AutoComplete has no controlled open state.boolean-
disabledWhether the component is disabled.boolean-
dropdownClassNameClass name of the dropdown list, applied to the role="listbox" element.string-
dropdownMatchSelectWidthWhether the minimum width of the dropdown equals the width of the input.booleantrue
dropdownStyleInline style string of the dropdown list, applied to the role="listbox" element.string-
emptyContentSnippet for the content shown in the dropdown when data is empty.Snippet-
insetLabelSnippet for the inset label of the input; passing it counts as having content. It is not rendered, and does not name the component, when prefix or trigger is used.Snippet-
insetLabelIdThe id of the insetLabel element, which names the combobox and the listbox. When omitted, the component generates one while an insetLabel is rendered.string-
itemSnippet for the content of a candidate row, receiving { item, index }: item is the data item as given and index is its position among the rendered items; without it the row shows the label.TypeSnippet<[AutoCompleteItemSnippetProps<T>]>-
loadingWhether the dropdown shows a loading spinner in place of the candidates and the empty content.booleanfalse
maxHeightMaximum height of the dropdown list; a number is in px.string | number300
motionWhether the dropdown animates when it shows and hides.booleantrue
onBlurCalled once when the focus leaves the input.Type(event: FocusEvent) => void-
onChangeCalled when the input text changes or a candidate is picked.Type(value: string | number) => void-
onClearCalled after the clear button is used.Type() => void-
onDropdownVisibleChangeCalled when the dropdown shows or hides, with its visibility.Type(visible: boolean) => void-
onFocusCalled once when the focus enters the input.Type(event: FocusEvent) => void-
onSearchCalled as the user types, with the typed text.Type(inputValue: string) => void-
onSelectCalled when a candidate is picked, with its value, or with the item without internal fields when onSelectWithObject is set.Type(value: string | number | AutoCompleteDataItem) => void-
onSelectWithObjectA boolean attribute, not a callback: when true, onSelect receives the data item without internal fields instead of its value.booleanfalse
placeholderPlaceholder of the input.string-
positionPosition of the dropdown; the values are those of the Tooltip position. Unset, it is bottomLeft, or bottomRight when the ConfigProvider direction is rtl.Position-
prefixSnippet for the prefix of the input.Snippet-
renderSelectedItemThe text the input shows for a picked item; it must return a string. A string or number item receives { value, label }, an object item the item itself.Type(option: AutoCompleteSelectedItem<T>) => string-
showClearWhether to show the clear button when there is content.booleanfalse
sizeSize of the input.Size-
stopPropagationWhether click, mousedown and focus in/out events on the dropdown stop propagating.boolean | stringtrue
suffixSnippet for the suffix of the input.Snippet-
triggerSnippet that replaces the input. Its parameters are value, inputValue, placeholder, disabled, autofocus, size, validateStatus, showClear, insetLabelId, onChange (updates the input text, calls onSearch and onChange and opens the list), onClear, onFocus, onBlur and controlAttrs (the aria-* attributes given to the component, for the focusable element of the custom trigger). With it, id lands on the root element.TypeSnippet<[AutoCompleteTriggerSnippetProps]>-
validateStatusValidation status; it only affects the style.ValidateStatus"default"
valueCurrent value of the input, supports bind:value. Left out, the component manages it; a one-way value={x} only seeds it, and for a fully controlled input use the function binding bind:value={get, set}. There is no defaultValue.string | number-

Methods

MethodDescriptionType
blurRemoves focus from the input.Type() => void
focusFocuses the input.Type(options?: FocusOptions) => void
getNativeElementReturns the root div that wraps the input or the custom trigger.Type() => HTMLDivElement | undefined

id, name, and aria-describedby, aria-errormessage, aria-invalid, aria-label, aria-labelledby, aria-required land on the input (role="combobox"), so a <label for> finds it. class (a string, array or object), style (a string), data-* and other undeclared attributes and event handlers (for example onclick) land on the root div, whose tabindex is fixed to -1; onkeydown runs after the component has handled the key. The lowercase onfocus, onblur, onchange and onselect are not native passthroughs; use the callbacks onFocus, onBlur, onChange and onSelect. With the trigger snippet there is no input: id lands on the root div, name lands nowhere, and the aria-* attributes reach the focusable element of the custom trigger through the controlAttrs parameter.

Object items of data:

FieldDescriptionType
valueThe value after pickingstring | number
labelThe text of the candidate, falling back to value; use the item snippet for markupstring | number
disabledWhether the candidate is disabledboolean
classClass of the candidate rowstring | object | array
styleStyle of the candidate rowstring

Other fields are kept as they are and show up in item of the item snippet and in the payload of onSelect (when onSelectWithObject is set). Fields starting with data- land on the candidate row. A string or number item reaches renderSelectedItem as { value, label }.

Accessibility

Keyboard and Focus

  • AutoComplete's input box has role="combobox" and is linked to the options panel through aria-expanded, aria-controls, aria-autocomplete="list" and aria-activedescendant
  • The combobox takes its name from, in order: aria-labelledby, aria-label, the rendered insetLabel (the combobox's aria-labelledby points at it, with an id the component generates when insetLabelId is not given; with a prefix the insetLabel is not rendered and does not name it). The listbox uses the same name source. AutoComplete has no default name: with none of these, name the input with aria-label or aria-labelledby; a <label for> names only the input and leaves the listbox unnamed
  • AutoComplete's input box can be focused, and once focused, keyboard users can use Up Arrow or Down Arrow to open the options panel; when data is empty the panel shows emptyContent (nothing when it is not provided), and a loading spinner while loading
  • AutoComplete also supports opening and closing panels via Enter key
  • If the user sets the defaultActiveFirstOption property to true, the first option is highlighted by default when the options panel is opened
  • If the drop-down menu is open:
    • Use Esc to close the menu
    • Use Tab to close the menu; the focus moves on to the next focusable element as usual
    • Use Up Arrow or Down Arrow to toggle options; the highlighted option (the one aria-activedescendant points at) has aria-selected="true"
    • The focused option can be selected with the Enter key and the panel will be collapsed
    • After picking an option with the mouse, the focus stays in the input
  • With showClear and a value, the clear button is the same as Input's: a native button named "Clear input" from the locale; from the input, Tab moves to it, and Enter or Space clears and puts the focus back in the input

Content Guidelines

  • Content needs to be presented clearly so that users can clearly perceive the options available
  • Limit the number of options displayed at one time

Design Token

These are the component's internal Sass variables and cannot be overridden. To customize styles, override the --semi-* CSS variables (see the Design Token page) or write unlayered CSS rules.
Sass variableValueUsage
$transition_duration-autoComplete_option-bgvar(--semi-transition_duration-none)选择器-选项-动画持续时间
$transition_function-autoComplete_option-bgvar(--semi-transition_function-easeIn)选择器-选项-过渡曲线
$transition_delay-autoComplete_option-bgvar(--semi-transition_delay-none)选择器-选项-延迟时间
$spacing-autoComplete_loading_wrapper-paddingTop$spacing-tight加载搜索结果时的顶部内边距
$spacing-autoComplete_loading_wrapper-paddingBottom$spacing-tight加载搜索结果时的底部内边距
$color-autoComplete_option-icon-defaulttransparent自动完成菜单选项图标颜色 - 默认态
$color-autoComplete_option-bg-hovervar(--semi-color-fill-0)自动完成菜单选项背景颜色 - 悬停态
$color-autoComplete_option-bg-activevar(--semi-color-fill-1)自动完成菜单选项背景颜色 - 按下态
$color-autoComplete_option_disabled-textvar(--semi-color-disabled-text)禁用自动完成菜单选项文字颜色
$width-autoComplete_option_tick$width-icon-small自动完成菜单项选中对勾图标大小
$spacing-autoComplete_option_tick-marginRight$spacing-tight自动完成菜单选中对勾右侧外边距
$spacing-autoComplete_option-paddingLeft$spacing-base-tight自动完成菜单项左侧内边距
$spacing-autoComplete_option-paddingRight$spacing-base-tight自动完成菜单项右侧内边距
$spacing-autoComplete_option-paddingTop$spacing-tight自动完成菜单项顶部内边距
$spacing-autoComplete_option-paddingBottom$spacing-tight自动完成菜单项底部内边距
$spacing-autoComplete_option_first-marginTop$spacing-extra-tight自动完成第一个菜单项顶部外边距
$spacing-autoComplete_option_last-marginBottom$spacing-extra-tight自动完成最后一个菜单项顶部外边距
$radius-autoComplete_option0px自动完成待选项圆角
$color-autoComplete_option_main-textvar(--semi-color-text-0)自动完成菜单选项文本颜色