Anchor Design System

Autocomplete

Autocomplete allows users to search through a list of options and select a value. It supports keyboard navigation, custom filtering, and rich options with labels and descriptions.

Installation

npm i @tryg/react-ui-library

Usage

The AnchorAutocomplete component allows users to search through a list of options and select a value. It supports keyboard navigation, custom filtering, and rich options with labels and descriptions.

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany']}
  placeholder="Start typing to search..."
/>

Rich Options

Options can be passed as an array of OptionValue objects with value, label, and optional description properties.

<AnchorAutocomplete
  label="Select Country"
  options={[
    { value: 'us', label: 'United States' },
    { value: 'uk', label: 'United Kingdom' },
    { value: 'ca', label: 'Canada' },
  ]}
  placeholder="Search by country name..."
/>

Options with Descriptions

Options can include a description field that provides additional context in the dropdown.

<AnchorAutocomplete
  label="Select Region"
  options={[
    { value: 'na', label: 'North America', description: 'United States, Canada, Mexico' },
    { value: 'eu', label: 'Europe', description: 'Western and Eastern European countries' },
    { value: 'asia', label: 'Asia', description: 'East Asian and Southeast Asian countries' },
  ]}
  placeholder="Search regions..."
/>

Disabled

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada']}
  placeholder="Cannot interact with this field"
  disabled
/>

Read Only

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada']}
  placeholder="This field is read-only"
  readonly
/>

Required

If you pass the required prop, the field will be required for form validation.

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada']}
  required
/>

Help Text

You can add helpful text by passing the helpText prop.

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada']}
  placeholder="Search countries..."
  helpText="Enter a country name to see suggestions"
/>

Error Message

When showError is true (default), typing a value not selected from the dropdown will display an error message on blur. Customize it with errorText.

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada']}
  errorText="Please select a valid country"
/>

Filter Options

Filter Condition

Control how the default filter matches options using the filterCondition prop. The default is contains.

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany']}
  filterCondition="startsWith"
  helpText="Only shows options that start with your input"
/>

Available filter conditions:

  • contains — Shows options that contain the input text anywhere (default)
  • startsWith — Shows options that start with the input text
  • endsWith — Shows options that end with the input text

Custom Filter Function

For full control over filtering, pass a custom filter function via the filterFn prop.

const customFilter: (options: OptionValue[], input: string, condition?: string) => OptionValue[] =
  (options, input) => {
    const trimmed = input?.toLowerCase().trim();
    if (!trimmed) return options;
    return options.filter(opt =>
      (opt.label || opt.value).toLowerCase().startsWith(trimmed)
    );
  };

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada']}
  filterFn={customFilter}
/>

Expand Behavior

Expand on Click

The dropdown expands when the user clicks the input (default behavior).

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada']}
  expandOn="click"
  helpText="Dropdown expands when you click the input"
/>

Expand on Character Limit

The dropdown expands only after the user types a minimum number of characters.

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada']}
  expandOn="charLimit"
  charLimit={3}
  helpText="Dropdown expands after typing 3 characters"
/>

Backend Filtering

When filtering on your backend (e.g., querying an API for each keystroke), listen to the inputchange event and update the options prop with the server response.

import { useEffect, useRef, useState, useCallback } from 'react';
import { AnchorAutocomplete } from '@tryg/react-ui-library';

function SearchAutocomplete() {
  const autocompleteRef = useRef<HTMLAnchorAutocompleteElement>(null);
  const [options, setOptions] = useState([]);
  const [loading, setLoading] = useState(false);
  const abortControllerRef = useRef<AbortController | null>(null);

  const handleInputChange = useCallback(async (e: CustomEvent) => {
    const searchTerm = e.detail.value;

    // Abort previous in-flight request
    if (abortControllerRef.current) abortControllerRef.current.abort();
    abortControllerRef.current = new AbortController();

    setLoading(true);

    try {
      const response = await fetch(`/api/countries?q=${encodeURIComponent(searchTerm)}`, {
        signal: abortControllerRef.current.signal
      });
      const data = await response.json();

      setLoading(false);
      setOptions(data.map(c => ({ value: c.id, label: c.name })));
    } catch (err) {
      if (err.name !== 'AbortError') {
        setLoading(false);
      }
    }
  }, []);

  useEffect(() => {
    const el = autocompleteRef.current;
    if (!el) return;
    el.addEventListener('inputchange', handleInputChange);
    return () => el.removeEventListener('inputchange', handleInputChange);
  }, [handleInputChange]);

  return (
    <AnchorAutocomplete
      ref={autocompleteRef}
      label="Search Countries"
      options={options}
      loading={loading}
      loadText="Searching countries..."
      placeholder="Search..."
    />
  );
}

Loading State

Set loading to display a loading indicator while options are being fetched asynchronously.

<AnchorAutocomplete
  label="Search Countries"
  options={[]}
  loading
  loadText="Searching countries..."
/>

Search Icon

Show a search icon in the input using the showIcon prop. The icon is visible when the dropdown is collapsed and no option is selected.

<AnchorAutocomplete
  label="Search Countries"
  options={['United States', 'United Kingdom', 'Canada']}
  showIcon
  helpText="Search icon hides when dropdown is open or option is selected"
/>

Events

The Autocomplete component emits several custom events that can be listened to for reactive behavior.

import { useEffect, useRef, useCallback } from 'react';
import { AnchorAutocomplete } from '@tryg/react-ui-library';

function AutocompleteWithEvents() {
  const ref = useRef<HTMLAnchorAutocompleteElement>(null);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;

    const handlers = {
      selectevent: (e: CustomEvent) => console.log('Selected:', e.detail),
      inputchange: (e: CustomEvent) => console.log('Input changed:', e.detail),
      expand: (e: CustomEvent) => console.log('Dropdown expanded:', e.detail),
      collapse: (e: CustomEvent) => console.log('Dropdown collapsed:', e.detail),
      highlight: (e: CustomEvent) => console.log('Option highlighted:', e.detail),
      focusevent: (e: CustomEvent) => console.log('Input focused:', e.detail),
      blurevent: (e: CustomEvent) => console.log('Input blurred:', e.detail),
    };

    Object.entries(handlers).forEach(([event, handler]) =>
      el.addEventListener(event, handler)
    );

    return () => {
      Object.entries(handlers).forEach(([event, handler]) =>
        el.removeEventListener(event, handler)
      );
    };
  }, []);

  return (
    <AnchorAutocomplete
      ref={ref}
      label="Search Countries"
      options={['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany']}
      placeholder="Interact to see events in console"
    />
  );
}
EventDetail Type
selectevent{ value: string, label: string }
inputchange{ value: string }
expand{ expanded: true, searchTerm: string }
collapse{ expanded: false, selected: boolean }
highlight{ index: number, value: string, label: string }
focusevent{ value: string }
blurevent{ value: string, selected: boolean, error: boolean }

Accessibility

The Autocomplete component implements the ARIA combobox pattern:

  • The input uses role="combobox" with aria-expanded, aria-controls, and aria-activedescendant
  • The dropdown list uses role="listbox"
  • Options use role="option" with aria-selected state
  • Full keyboard navigation is supported:
    • Arrow Down — Open dropdown / move focus to next option
    • Arrow Up — Move focus to previous option
    • Enter / Space — Select the currently focused option
    • Escape — Close the dropdown

Accessibility Considerations

  1. Avoid very long option names to facilitate understanding and perception.
  2. Don't use the same word or phrase at the beginning of a set of options.
  3. If the autocomplete is a required field, include the required prop and indicate that it is a required field.

Guidelines

Do use

  • Autocomplete in full pages, forms, modals, and side panels
  • Autocomplete to select values from a large dataset

Don't use

  • Use a select or radio group instead when there are only a limited number of options to choose from

API

anchor-typeahead

WORK IN PROGRESS: This component is new

How to use the typeahead component

Basic typeahead

<anchor-typeahead options='["foo","bar","foobar"]' language="NO" texts='{"noResult":"The search yeilded no results"}'></anchor-typeahead>

Properties

PropertyAttributeDescriptionTypeDefault
charLimitchar-limitCharacter limit to expand on for Autocompletenumber1
disableddisabledDisable flag for Autocompletebooleanfalse
errTextPlacementerr-text-placementThis prop decides if the messages should render between the label of an input and the input field, or below the input field."below" | "inside"'inside'
errorTexterror-textError text for Autocompletestring"default error text"
expandOnexpand-onExpand condition for Autocomplete"charLimit" | "click"'click'
filterConditionfilter-conditionFilter condition to be used with default filter function for Autocomplete"contains" | "endsWith" | "startsWith"'contains'
filterFn--Custom Filter Function for Autocomplete(options: OptionValue[], input: string, condition?: string) => OptionValue[]filterOptions
helpTexthelp-textHelpful Text for Autocompletestringundefined
inputValueinput-valueValue inputedstringundefined
labellabelLabel for Autocompletestringundefined
loadTextload-textText to show when loading is truestring"Searching..."
loadingloadingTo set a loading state while options are recievedbooleanfalse
noOptionsErrorTextno-options-error-textNo options text for Autocompletestring"No Options found"
optionsoptionsOptions for Autocomplete(string | OptionValue)[] | stringundefined
placeholderplaceholderPlaceholder Text for Autocompletestringundefined
readonlyreadonlyReadOnly flag for Autocompletebooleanfalse
requiredrequiredMark the field as required for form validation.booleanfalse
showErrorshow-errorShow error on not selecting from dropdownbooleantrue
showIconshow-iconShow search icon for Autocompletebooleanfalse
uuiduuidThe unique id of the input fieldstringuuidv4()

Events

EventDescriptionType
blureventEvent emitted when the input loses focusCustomEvent<AutocompleteBlurEventDetail>
collapseEvent emitted when the dropdown collapsesCustomEvent<AutocompleteCollapseEventDetail>
expandEvent emitted when the dropdown expandsCustomEvent<AutocompleteExpandEventDetail>
focuseventEvent emitted when the input receives focusCustomEvent<AutocompleteFocusEventDetail>
highlightEvent emitted for a highlighted selection when a user uses arrow keys for navigating optionsCustomEvent<AutocompleteHighlightEventDetail>
inputchangeEvent emitted when input field is changedCustomEvent<AutocompleteInputEventDetail>
selecteventEvent emitted when a valid option has been selectedCustomEvent<AutocompleteSelectEventDetail>

Dependencies

Depends on

Graph

graph TD;
  anchor-autocomplete --> anchor-input
  anchor-autocomplete --> anchor-option
  anchor-input --> anchor-form-field
  anchor-input --> anchor-icon
  anchor-input --> anchor-tooltip
  anchor-form-field --> anchor-icon
  anchor-option --> anchor-icon
  style anchor-autocomplete fill:#f9f,stroke:#333,stroke-width:4px

Built with StencilJS

On this page