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 (renderSelectedItem) can return any JSX element, while AutoComplete's renderSelectedItem only returns a string

Demos

How to import

import { AutoComplete } from '@fibrous/semi-ui-solid';

Basic usage

Monitor user input through onSearch, pass input suggestions through data, and keep it controlled with value and onChange, which fires when the input box changes or an input item is selected

Code
import { createSignal } from 'solid-js';
import { IconSearch } from '@fibrous/semi-icons-solid';
import { AutoComplete } from '@fibrous/semi-ui-solid';

const domains = ['gmail.com', '163.com', 'qq.com'];

export default function AutoCompleteDemo() {
    const [stringData, setStringData] = createSignal<string[]>([]);
    const [value, setValue] = createSignal<string | number>('');

    const handleStringSearch = (input: string) => {
        setStringData(input ? domains.map((domain) => `${input}@${domain}`) : []);
    };

    const handleChange = (next: string | number) => {
        console.log('onChange', next);
        setValue(next);
    };

    return <AutoComplete data={stringData()} value={value()} showClear prefix={<IconSearch />} placeholder="搜索... " onSearch={handleStringSearch} onChange={handleChange} style={{ width: '200px' }} />;
}

Custom option rendering

When you need to customize the rendering of candidates, data can be passed in an array of objects (each Object must contain label and value keys; value is the value picked by the candidate, and label is the text the candidate displays). Render each candidate through renderItem, which returns JSX.

Code
import { createSignal } from 'solid-js';
import { IconSearch } from '@fibrous/semi-icons-solid';
import { AutoComplete, Avatar } from '@fibrous/semi-ui-solid';

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' },
];

export default function AutoCompleteDemo() {
    const [data, setData] = createSignal<ListItem[]>([]);

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

    const renderOption = (item: ListItem) => (
        <>
            <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>
        </>
    );

    return <AutoComplete aria-label="搜索邮箱" data={data()} showClear prefix={<IconSearch />} onSearch={handleStringSearch} renderItem={renderOption} renderSelectedItem={(option) => option.email} style={{ width: '280px' }} />;
}

Get the user input value from onSearch and update data dynamically

Size

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





Code
import { AutoComplete } from '@fibrous/semi-ui-solid';

const data = [1, 2, 3, 4];

export default function AutoCompleteDemo() {
    return (
        <div>
            <AutoComplete data={data} size="small" placeholder="small" style={{ width: '200px' }} />
            <br />
            <br />
            <AutoComplete data={data} size="default" placeholder="default" style={{ width: '200px' }} />
            <br />
            <br />
            <AutoComplete data={data} size="large" placeholder="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
import { createSignal } from 'solid-js';
import { AutoComplete } from '@fibrous/semi-ui-solid';

const domains = ['gmail.com', '163.com', 'qq.com'];

export default function AutoCompleteDemo() {
    const [data, setData] = createSignal<string[]>([]);

    const change = (input: string) => {
        setData(input ? domains.map((domain) => `${input}@${domain}`) : []);
    };

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

Disabled

Code
import { AutoComplete } from '@fibrous/semi-ui-solid';

const data = [1, 2, 3, 4];

export default function AutoCompleteDemo() {
    return <AutoComplete data={data} placeholder="禁用下拉菜单" disabled style={{ width: '200px' }} />;
}

Validate status

Different verification states can be set to show different styles





Code
import { AutoComplete } from '@fibrous/semi-ui-solid';

export default function AutoCompleteDemo() {
    return (
        <>
            <AutoComplete aria-label="Warning status" defaultValue="ies" validateStatus="warning" />
            <br />
            <br />
            <AutoComplete aria-label="Error status" defaultValue="ies" validateStatus="error" />
            <br />
            <br />
            <AutoComplete aria-label="Default status" defaultValue="ies" />
        </>
    );
}

Custom empty content

Can set up custom display empty content

Code
import { createSignal } from 'solid-js';
import { IllustrationNoContent } from '@fibrous/semi-illustrations-solid';
import { AutoComplete, Empty } from '@fibrous/semi-ui-solid';

export default function AutoCompleteDemo() {
    const [data, setData] = createSignal<number[]>([]);
    const [loading, setLoading] = createSignal(false);

    const fetchData = (input: string) => {
        setLoading(true);
        setTimeout(() => {
            setData(input ? Array.from({ length: 5 }, () => Math.random()) : []);
            setLoading(false);
        }, 1000);
    };

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

API reference

Props

PropertyDescriptionTypeDefault
autoAdjustOverflowWhether the dropdown flips automatically when it would be clipped.boolean-
autofocusWhether the input is focused after mount.booleanfalse
clearIconCustom clear icon, effective when showClear is true.JSX.Element-
dataData source of the candidates: an array of strings, numbers or objects. An object item's value is the picked value and its label is the row text (provide it; markup goes through renderItem). Other fields are kept as they are and reach the renderItem argument. Pass a new array to update the list.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.boolean-
defaultValueInitial value of the input when uncontrolled, read on mount only.string | number-
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 of the dropdown list, with kebab-case keys for an object, applied to the role="listbox" element.JSX.CSSProperties | string-
emptyContentContent shown in the dropdown when data is empty. While loading, the spinner is shown instead.JSX.Elementnull
idThe id of the input, for <label for>; with triggerRender it lands on the root element.string-
insetLabelInset label of the input, rendered in the prefix position. It is not rendered, and does not name the component, when prefix or triggerRender is set.JSX.Element-
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-
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
onBlurCallback when the focus leaves the input area, with the FocusEvent. Moving the focus inside the area, for example to the clear button, does not fire it.Type(e: FocusEvent) => void-
onChangeCallback when the input text changes or a candidate is picked, with the current value.Type(value: string | number) => void-
onChangeWithObjectHas no effect; the component does not read it.boolean-
onClearCallback after the clear button empties the input.Type() => void-
onDropdownVisibleChangeCallback when the dropdown shows or hides, with its visibility.Type(visible: boolean) => void-
onFocusCallback when the focus enters the input area, with the FocusEvent. Moving the focus inside the area, for example to the clear button, does not fire it.Type(e: FocusEvent) => void-
onSearchCallback as the user types, with the typed text.Type(inputValue: string) => void-
onSelectCallback when a candidate is picked, with its value, or with the item without internal fields when onSelectWithObject is set.Type(value: string | number | BaseDataItem) => void-
onSelectWithObjectBoolean prop. 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-
prefixPrefix content of the input. When it is set, insetLabel is not rendered.JSX.Element-
refThe root div that wraps the input or the output of triggerRender. Its focus() and blur() act on the input.TypeRef<HTMLDivElement>-
renderItemRenders a candidate row. The argument is the data item itself, and the return value is JSX. Without it the row shows label.Type(option: T) => JSX.Element-
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: T extends string | number ? BaseDataItem : T) => string-
showClearWhether to show the clear button when there is content.booleanfalse
sizeSize of the input: small, default or large.Size"default"
stopPropagationWhether click, mousedown and focus in/out events on the dropdown stop propagating.TooltipProps['stopPropagation']true
suffixSuffix content of the input.JSX.Element-
triggerRenderCustom trigger, which replaces the input. Its parameters include value (the array of selected items), inputValue, placeholder, disabled, autofocus, size, validateStatus, showClear, prefix, suffix, clearIcon, the aria-label, aria-labelledby, aria-describedby, aria-errormessage, aria-invalid and aria-required attributes (other aria-* attributes do not reach the custom trigger), onChange (updates the input text, calls onSearch and onChange and opens the list), onClear, onFocus, onBlur and componentProps. With it, id lands on the root element.Type(props: AutoCompleteTriggerRenderProps<T>) => JSX.Element-
validateStatusValidation status: default, error or warning. It only affects the style.ValidateStatus"default"
valueCurrent value. Passing it makes the component controlled; undefined leaves it uncontrolled.string | number-

class, style, ref, data-* and other undeclared attributes and events (for example onClick) land on the root div, whose tabindex is fixed to -1. id, name and aria-* land on the input (role="combobox"), so a <label for> finds it. With triggerRender there is no input: id lands on the root div, name lands nowhere, and aria-label, aria-labelledby, aria-describedby, aria-errormessage, aria-invalid and aria-required reach the focusable element of the custom trigger through its parameters; other aria-* attributes do not reach the trigger.

Object items of data:

FieldDescriptionType
valueThe value after pickingstring | number
labelThe row text; must be provided, markup goes through renderItemstring | number
disabledWhether the candidate is disabledboolean
classClass of the candidate rowstring
styleStyle of the candidate rowJSX.CSSProperties | string

Other fields are kept as they are and show up in the renderItem argument; with onSelectWithObject set, the object that onSelect receives keeps them too. 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)自动完成菜单选项文本颜色