Skip to main content

SearchInput

Provides an input field for searching content within a site to find specific items.

Submit feedback
github

Migration Information

For teams migrating from the V1 to V2 component, please refer to the migration guide for changes to the component.
Component Guide
import { SearchInput } from '@uhg-abyss/web/ui/SearchInput';
    () => {
    const MockData = utils.useSearchInputMock();
    const handleSearch = (data) => {
    console.log('Searched', data);
    };
    return (
    <SearchInput
    placeholder="Placeholder text"
    label="Search Sandbox"
    onSearch={handleSearch}
    options={MockData}
    />
    );
    };

    Usage

    SearchInput is designed specifically for site-wide search functionality, and is no longer considered a typical form input component. The recommended usage context is for a search input field that is used to search for items within a site and display results.

    For usages that require users to fill out a form with search functionality, it is recommended you use SelectInput with the isSearchable prop.

    Note:

    • SearchInput does not support the following V1 SearchInput props: validators, errorMessage, isDisabled, isRequired, model and subText.
    • SearchInput is no longer compatible with FormProvider and useForm.

    Variants

    The default variant for SearchInput is a basic search input field that, on search, provides the search term to the onSearch callback.

    Note: Most code examples below use the type-ahead variant because of its increased functionality. Any props that are NOT compatible with the default variant are designated below by the following badge:

    Utilize the isTypeAhead prop to enable type-ahead search functionality along with a drop-down menu of options that are filtered based on the search term. Same as with the default variant, the onSearch callback is triggered on search.

    State management

    Uncontrolled / onSearch

    When you only need to capture the searched value, simply use the onSearch prop.

    Note: Whether using controlled or uncontrolled, onSearch is always triggered on search.

    Controlled / onInputChange

    When you need to store the current state of the input, use the onInputChange prop. This callback will be triggered on every input change, including on the type-ahead variant when navigating with arrow keys or clicking an option from the drop-down menu.

    As a second argument, the callback will receive an inputChangeType parameter that designates the type of change that occurred. This can be useful when calling an API to fetch results based on the search term and you need to differentiate between types of user interaction.

    The inputChangeType parameter can have the following values. These values are available as constants via import { SearchInputChangeTypes } from '@uhg-abyss/web/ui/SearchInput';:

    TypeDescription
    InputChangeUser manually typed in the input field
    InputClearUser cleared the input using the clear button
    ArrowNavigationUser navigated with arrow keys
    ItemClickUser clicked on an item in the dropdown

    Note: SearchInput no longer captures a drop-down menu selection separately from changes to the search input field. Therefore, to simplify operations, the onChange prop has been removed in favor of solely utilizing onInputChange.

    Display properties

    Label

    The label prop is required. The hideLabel prop can be set to true to hide the label visually, but still allow it to be accessible to screen readers.

    Helper

    Use the helper prop to display a help icon next to the label. Simply passing a string value will render the default helper, a Tooltip containing that string. The helper can be customized by passing in a node. It is recommended to use either a Tooltip or a Popover. See When should I use a Tooltip vs. a Popover? for more information on best practices regarding the two.

    Placeholder

    Use the placeholder prop to set the placeholder text.

    Width

    Use the width prop to set the width of the select list.

    Search button variant

    Use the searchButtonVariant prop to set the style variant of the search button icon when using the default search variant. Options are filled (default) and outlined.

    Interactivity

    onSearch

    Use the onSearch prop to capture the searched value. The callback will receive the selected search term string as the first argument, and if applicable when using type-ahead, as a second argument, the entire object of the selected option.

    A search occurs with the following actions:

    • Pressing "Enter" when focused on the input field.
    • Selecting an option from the drop-down menu.
    • Clicking or pressing "Enter" on the default variant's search button.

    Clearable

    Use the isClearable prop to allow for clearing the search input. If true, a clear button will appear in the input. The optional onClear callback prop can be used to trigger additional actions when the clear button is clicked.

    Open on focus

    By default, the menu will automatically open when the input receives keyboard focus. To change this behavior, set the openOnFocus prop to false.

    Note: By default, the menu will automatically open when clicked.

    Enable outside scroll

    Set the enableOutsideScroll prop to true to enable scrolling outside the search input component while the option list is open. Default is set to false.

    Search filtering

    Fuse.js

    SearchInput uses the Fuse.js library to fuzzy filter results. What is fuzzy searching?... Generally speaking, fuzzy searching (more formally known as approximate string matching) is the technique of finding strings that are approximately equal to a given pattern (rather than exactly).

    Fuse keys

    The keys prop allows you to specify the values from the specific keys within your options object to search against. This feature accommodates nested paths, prioritizes certain fields with weighted search, and can handle searches within arrays of objects. The default search keys are ['label', 'value'].

    For example, if the options contained objects with the following structure:

    {
    value: "react",
    label: "React",
    tags: ['jsx', 'virtual dom', 'facebook']
    }

    and you wanted to allow users to search on the label and tag values, you would provide the following, as in the example below:

    searchConfig={{ keys: ['label', 'tags'] }}

    Custom Fuse configurations

    The Fuse configuration can be customized by following the Fuse documentation and passing the configurations into the searchConfig prop.

    For example, if you wanted to adjust the threshold to 0, thus requiring an exact match, you would pass in the following object. The default threshold is 0.1.

    Common config props:

    • keys: Array of keys to search against
    • threshold: Threshold for fuzzy search
    • maxResults: Maximum number of results to return
    • debounce: Debounce time in milliseconds
    const customFuseConfig = {
    threshold: 0, // exact match
    };

    Highlighted search results

    By default, highlightMatches is true and matching text in search results is highlighted with bold font weight and a yellow background color.

    The highlightMatches prop accepts either a boolean or an object:

    // Boolean usage
    highlightMatches: boolean
    // Object usage
    highlightMatches: {
    fuzzyHighlighting?: boolean;
    colorHighlighting?: boolean;
    }
    • fuzzyHighlighting: Uses Fuse.js match indices for precise character-level highlighting
    • colorHighlighting: Set to false to remove yellow background but keep bold font weight

    To completely disable highlighting, set highlightMatches to false.

    API filtering with debounce

    To override the Fuse filtering and make asynchronous calls to an API to set the list of dropdown options, use a combination of the onInputChange and options props.

    While searching, onInputChange will supply the current search value and whether the input field was updated due to a selection. After retrieving the option items from the API, pass them into the options prop.

    To incorporate debouncing into the search, use the useDebounce hook.

    import { useDebounce } from '@uhg-abyss/web/hooks/useDebounce';

    Note: Unlike SelectInput, the usage of onInputChange within SearchInput does not assume filtering will be handled externally, so you'll have to set searchConfig to false to prevent internal Fuse filtering.

    This example shows all of these concepts together. The apiFilter function is called on every keystroke, but the API call is debounced to only occur after 300ms of inactivity. Search "united" to see the API call in action.

    Options

    Use the options prop to supply the drop-down menu options that will be available for selection. options is an array of objects, where each object has a base that includes the following properties:

    • value: unique identifier for the option
    • label: content the option will display within the menu list
    [
    { value: 'id1', label: 'Option 1' },
    { value: 'id2', label: 'Option 2' },
    { value: 'id3', label: 'Option 3' },
    ...
    ]

    Sections can also be specified. See Section headers for more details.

    ValueKey / labelKey

    If your data structure uses different property names than value and label, you can map them using the valueKey and labelKey props without restructuring your data.

    • valueKey: Specifies which property to use as the option's value (defaults to "value")
    • labelKey: Specifies which property to use as the option's display text (defaults to "label")

    This is particularly useful when working with API responses or existing data structures that can't be easily transformed.

    Option list height

    Use the maxListHeight prop to set the maximum height the option list can be before it becomes scrollable. The default value is 185px.

    Section headers

    To group list items under section headers, pass objects into the options array that have the section and items properties. section specifies the name of the section, which will be bolded and unselectable, while items contains the options within that section (with the same value/label format as normal), which will appear indented.

    To retain section headers after searching with isSearchable, set retainSectionHeader within searchConfig to true.

    [
    { value: 'id1', label: 'Option 1' },
    { value: 'id2', label: 'Option 2' },
    {
    section: 'Section Header',
    items: [
    { value: 'id3', label: 'Sub-section Option 1' },
    { value: 'id4', label: 'Sub-section Option 2' },
    ...
    ],
    },
    ...
    ]

    Custom render

    Use the customRender prop to customize the render of each option item. If section headers are used, they will also be handled by this function. customRender provides the item object as the first parameter and the item's state as the second.

    Virtualization

    Use the virtual prop to add virtualization and improve performance when working with larger data sets. Virtualization leverages the useVirtualization hook, which utilizes the TanStack Virtual library. Setting virtual to true will utilize the default configuration. virtual also accepts an object to configure the virtualizer. To see all available values that may be provided to the virtual prop, please refer to the TanStack Virtual documentation.

    To maximize performance, virtualization for the SearchInput component is configured by default to use fixed sizing based on an option item element height of 38px. If your item height remains fixed but is different from the default, utilize the estimateSize function. If the item height is unknown prior to rendering, enable dynamic sizing by setting dynamicSizing to true.

    The default settings used in SearchInput are as follows:

    • estimateSize: Sets item height when using fixed sizing. When using dynamic sizing, to help with scroll performance, set this to the largest possible height of the item elements (default value is 38).
    • dynamicSizing: When true, each option item element is dynamically measured on render. Scrolling performance may not be as smooth when using this prop (default value is false).
    • overscan: The number of element items to render above and below the visible area (default value is 5).

    Additional Examples

    Note: The following examples demonstrate common search interface patterns that would typically integrate with API endpoints to fetch real-time data. These examples use static mock data to showcase the component's flexibility in creating various layouts and interactions, rather than replicating full backend functionality.

    SearchInput (Default) Props

    NameTypeDefaultRequiredDescription
    className
    string
    --
    CSS class name to apply to each element within the component
    css
    Abyss.CSSProperties | Partial<Record<`abyss-${T}`, Abyss.CSSProperties>>
    --
    Object containing CSS styling to apply; uses the classes listed in the "Integration" tab of the component's documentation

    See CSS Prop Styling for more information
    data-testid
    string
    --
    Suffix used to create a unique ID used for automated testing

    See Component Testing for more information
    disableDefaultProviderProps
    boolean
    false
    -
    If set to true, the component will not use the DefaultPropsProvider values.

    If you aren’t using the DefaultPropsProvider, this prop can be ignored.
    helper
    React.ReactNode
    --
    Helper element next to label
    hideLabel
    boolean
    false
    -
    If true, the label will be visually hidden
    isClearable
    boolean
    --
    If true, the input will display a clear button
    isTypeAhead
    boolean
    false
    -
    Enables typeahead functionality.
    label
    string
    -
    The label for the input
    onBlur
    React.FocusEventHandler<HTMLInputElement>
    --
    Callback function executed when the input is blurred
    onClear
    () => void
    --
    Callback function executed when the input is cleared
    onFocus
    React.FocusEventHandler<HTMLInputElement>
    --
    Callback function executed when the input is focused
    onInputChange
    (inputValue: string) => void
    --
    Callback fired every time the input value changes
    onKeyDown
    (event: React.KeyboardEvent<HTMLElement>) => void
    --
    Callback fired every time a key is pressed within search input
    onPaste
    (event: React.ClipboardEvent<HTMLElement>) => void
    --
    Callback fired every time a paste event occurs within search input
    onSearch
    (inputValue: string) => void
    --
    Callback fired when user performs a search
    placeholder
    string
    --
    Placeholder text for the input
    searchButtonVariant
    "filled" | "outlined"
    'filled'
    -
    Variant of the search icon button
    value
    string
    --
    Selected option value
    width
    string | number
    '100%'
    -
    Width of the input.

    SearchInput (Type-Ahead) Props

    NameTypeDefaultRequiredDescription
    className
    string
    --
    CSS class name to apply to each element within the component
    css
    Abyss.CSSProperties | Partial<Record<`abyss-${T}`, Abyss.CSSProperties>>
    --
    Object containing CSS styling to apply; uses the classes listed in the "Integration" tab of the component's documentation

    See CSS Prop Styling for more information
    customLoader
    React.ReactElement<any, string | React.JSXElementConstructor<any>>
    --
    Custom loader node display when isLoading is true
    customRender
    (item: SearchInputTypeAheadMenuOption | SearchInputTypeAheadMenuSection, itemState: Omit<...>) => React.ReactElem...
    --
    A custom render function for rendering each option
    data-testid
    string
    --
    Suffix used to create a unique ID used for automated testing

    See Component Testing for more information
    disableDefaultProviderProps
    boolean
    false
    -
    If set to true, the component will not use the DefaultPropsProvider values.

    If you aren’t using the DefaultPropsProvider, this prop can be ignored.
    enableOutsideScroll
    boolean
    false
    -
    Enable outside scroll when the select input is open.
    helper
    React.ReactNode
    --
    Helper element next to label
    hideLabel
    boolean
    false
    -
    If true, the label will be visually hidden
    highlightMatches
    boolean | { fuzzyHighlighting?: boolean | undefined; colorHighlighting?: boolean | undefined; }
    true
    -
    Determines if the search matches should be highlighted.
    Can be a boolean or an object with advanced highlighting options.
    isClearable
    boolean
    --
    If true, the input will display a clear button
    isLoading
    boolean
    false
    -
    Whether the input is loading.
    isTypeAhead
    boolean
    false
    -
    Enables typeahead functionality.
    label
    string
    -
    The label for the input
    labelKey
    string
    'label'
    -
    Key for the label in the options.
    maxListHeight
    string | number
    '200px'
    -
    Maximum height for the list.
    onBlur
    React.FocusEventHandler<HTMLInputElement>
    --
    Callback function executed when the input is blurred
    onClear
    () => void
    --
    Callback function executed when the input is cleared
    onFocus
    React.FocusEventHandler<HTMLInputElement>
    --
    Callback function executed when the input is focused
    onInputChange
    (inputValue: string, changeType: SearchInputChangeType) => void
    --
    Callback fired every time the input value changes

    See the SearchInputChangeTypes for more information.
    onKeyDown
    (event: React.KeyboardEvent<HTMLElement>) => void
    --
    Callback fired every time a key is pressed within search input
    onOpenChange
    (isOpen: boolean) => void
    --
    Callback fired when the dropdown menu opens or closes
    onPaste
    (event: React.ClipboardEvent<HTMLElement>) => void
    --
    Callback fired every time a paste event occurs within search input
    onSearch
    (inputValue: string, selectedOption: Record<string, any>) => void
    --
    Callback fired when user performs a search
    openOnFocus
    boolean
    true
    -
    Whether the menu should open when the input receives focus.
    options
    (SearchInputTypeAheadMenuOption | SearchInputTypeAheadMenuSection)[]
    --
    Options for the select input.
    placeholder
    string
    --
    Placeholder text for the input
    searchConfig
    false | SearchConfig
    --
    Configuration for the search.
    When set to false, disables internal filtering.
    value
    string
    --
    Selected option value
    valueKey
    string
    'value'
    -
    Key for the value in the options.
    virtual
    boolean | VirtualConfig
    --
    Adds virtualization to option item drop-down list.
    Can be a boolean or object with additional virtual scrolling configurations.
    width
    string | number
    '100%'
    -
    Width of the input.

    SearchInput Classes

    Class NameDescription
    .abyss-search-input-rootSearchInput root element
    .abyss-search-input-wrapperWrapper for all non-portal/menu elements
    .abyss-search-input-labelSearchInput label
    .abyss-search-input-container-wrapperWrapper for selection container interior elements
    .abyss-search-inputSearchInput input field
    .abyss-search-input-type-ahead-search-icon-containerContainer for the typeahead search icon
    .abyss-search-input-type-ahead-search-iconTypeahead search icon
    .abyss-search-input-default-focus-wrapperWrapper to handle focus for default variant
    .abyss-search-input-clear-buttonButton to clear selection
    .abyss-search-input-default-search-icon-containerContainer for the default search icon
    .abyss-search-input-default-search-iconIcon for the default search icon
    .abyss-search-input-portal-containerPortal container for typeahead menu
    .abyss-search-input-dismissable-layerDismissable layer for typeahead menu
    .abyss-search-input-menu-containerContainer for the typeahead menu
    .abyss-search-input-menu-loading-containerContainer for the loading spinner in the typeahead menu
    .abyss-search-input-menu-top-containerContainer for the custom top slot content in the typeahead menu
    .abyss-search-input-menu-bottom-containerContainer for the custom bottom slot content in the typeahead menu
    .abyss-search-input-menu-loading-spinnerLoading spinner in typeahead menu
    .abyss-search-input-menu-virtual-wrapperWrapper for virtualized menu items
    .abyss-search-input-menu-option-list-containerContainer for all options in typeahead menu
    .abyss-search-input-menu-section-listList of section options in typeahead menu
    .abyss-search-input-menu-option-headingSection heading in typeahead menu
    .abyss-search-input-menu-optionIndividual selectable option in typeahead menu
    .abyss-search-input-menu-option-search-iconSearch icon in typeahead menu option
    .abyss-search-input-menu-option-labelTypeahead menu option label content
    .abyss-search-input-menu-option-heading-labelTypeahead menu option heading label content

    A combobox is a widget made up of the combination of two distinct elements: 1) a single-line textbox, and 2) an associated pop-up element for helping users set the value of the textbox. The popup may be a listbox, grid, tree, or dialog. Many implementations also include a third optional element -- a graphical button adjacent to the textbox, indicating the availability of the popup. Activating the button displays the popup if suggestions are available.

    Adheres to the Combobox WAI-ARIA design pattern. Example: Editable Combobox With Both List and Inline Autocomplete

    Include meaningful accessible labels, even when not displayed

    All SearchInput fields must include a meaningful label, even if hidden (using hideLabel). This should start with the word "Search", especially if there is any visible text that suggests that (such as placeholder="Search..."). If this is not possible or part of the design, use the I18nProvider to prepend "Search " to the aria-label (as shown in the second example below).

    Typeahead Variant Keyboard Interactions

    Textbox Keyboard Interactions

    KeyDescription
    Down ArrowIf the listbox is displayed: Moves focus to the second suggested value. Note that the first value is automatically selected. If the listbox is not displayed: opens the listbox and moves focus to the first value
    Up ArrowIf the listbox is displayed, moves focus to the last suggested value. If the listbox is not displayed, opens the listbox and moves focus to the last value
    Alt + Down ArrowOpens the listbox without moving focus or changing selection
    EnterIf the listbox is displayed and the first option is automatically selected: Sets the textbox value to the content of the selected option. Closes the listbox
    EscClears the textbox. If the listbox is displayed, closes it

    Listbox Keyboard Interactions

    KeyDescription
    EnterSets the textbox value to the content of the focused option in the listbox. Closes the listbox. Sets focus on the textbox
    EscCloses the listbox. Sets focus on the textbox. Clears the textbox
    Down ArrowMoves focus to the next option. If focus is on the last option, moves focus to the first option
    Up ArrowMoves focus to the previous option. If focus is on the first option, moves focus to the last option
    Right ArrowMoves focus to the textbox and moves the editing cursor one character to the right
    Left ArrowMoves focus to the textbox and moves the editing cursor one character to the left
    HomeMoves focus to the textbox and places the editing cursor at the beginning of the field
    EndMoves focus to the textbox and places the editing cursor at the end of the field

    Component Tokens

    Note: Click on the token row to copy the token to your clipboard.

    SearchInput Tokens

    Token NameValue
    search-input.color.border.menu
    #CBCCCD
    search-input.color.surface.menu
    #FFFFFF
    search-input.color.surface.menu-item.rest
    #FFFFFF
    search-input.color.surface.menu-item.hover
    #F3F3F3
    search-input.color.surface.menu-item.active
    #E5E5E6
    search-input.color.surface.search-button.filled.rest
    #002677
    search-input.color.surface.search-button.filled.hover
    #004BA0
    search-input.color.surface.search-button.filled.active
    #00184D
    search-input.color.surface.search-button.outlined.rest
    #FFFFFF
    search-input.color.surface.search-button.outlined.hover
    #F3F3F3
    search-input.color.surface.search-button.outlined.active
    #E5E5E6
    search-input.color.icon.search.filled
    #FFFFFF
    search-input.color.icon.search.outlined
    #323334
    search-input.color.icon.search.content
    #323334
    search-input.color.icon.search.menu-item
    #002677
    search-input.color.text.menu-item
    #002677
    search-input.border-radius.all.menu
    4px
    search-input.border-width.all.menu
    1px
    search-input.sizing.icon.menu-item
    20px
    search-input.spacing.gap.horizontal.menu-item
    8px
    search-input.spacing.padding.horizontal.menu.loading
    16px
    search-input.spacing.padding.horizontal.menu-item
    16px
    search-input.spacing.padding.vertical.menu-item
    8px
    search-input.spacing.padding.top.menu.loading
    16px
    search-input.spacing.padding.bottom.menu.loading
    24px
    search-input.elevation.menu
    0px 2px 4px -2px rgba(0,0,0,0.16)
    Table of Contents