Anchor Design System

Autocomplete4.0

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.

WORK IN PROGRESS: This component has not gone through final testing and a11y validation. It may see breaking changes in the near future based on the feedback from testing.

Installation

npm i @tryg/vue-ui-library

Usage

The Autocomplete 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.

Install the component library as a Vue plugin. This globally registers all Anchor components.

main.js
import { createApp } from 'vue';
import { ComponentLibrary } from '@tryg/vue-ui-library';
import App from './App.vue';

const app = createApp(App);
app.use(ComponentLibrary);
app.mount('#app');
YourComponent.vue
<script setup>
import { ref } from 'vue';
const options = ref(['United States', 'United Kingdom', 'Canada']);
</script>
<template>
  <anchor-autocomplete :options="options" label="Search Countries" placeholder="Start typing to search..."></anchor-autocomplete>
</template>

Import only the components you need for optimal bundle size.

YourComponent.vue
<script setup>
import { ref } from 'vue';
import { AnchorAutocomplete } from '@tryg/vue-ui-library';
const options = ref(['United States', 'United Kingdom', 'Canada']);
</script>
<template>
  <anchor-autocomplete :options="options" label="Search Countries" placeholder="Start typing to search..."></anchor-autocomplete>
</template>

Rich Options

Options can be passed as an array of OptionValue objects with value, label, and optional description properties. Options display labels but submit values on selection.

Options with Descriptions

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

Disabled

YourComponent.vue
<script setup>
import { ref } from 'vue';
const options = ref(['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany']);
</script>
<template>
  <anchor-autocomplete :options="options" label="Search Countries" disabled></anchor-autocomplete>
</template>

Read Only

YourComponent.vue
<script setup>
import { ref } from 'vue';
const options = ref(['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany']);
</script>
<template>
  <anchor-autocomplete :options="options" label="Search Countries" readonly></anchor-autocomplete>
</template>

Required

If you pass the required property to the component, the field will be required for form validation.

YourComponent.vue
<script setup>
import { ref } from 'vue';
const options = ref(['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany']);
</script>
<template>
  <anchor-autocomplete :options="options" label="Search Countries" required></anchor-autocomplete>
</template>

Help Text

You can add helpful text to the component by passing the help-text property.

YourComponent.vue
<script setup>
import { ref } from 'vue';
const options = ref(['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany']);
</script>
<template>
  <anchor-autocomplete :options="options" label="Search Countries" help-text="Enter a country name to see suggestions"></anchor-autocomplete>
</template>

Error Message

When show-error is true (default), typing a value that is not selected from the dropdown will display an error message on blur. Customize the message with error-text.

YourComponent.vue
<script setup>
import { ref } from 'vue';
const options = ref(['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany']);
</script>
<template>
  <anchor-autocomplete :options="options" label="Search Countries" error-text="Please select a valid country"></anchor-autocomplete>
</template>

Filter Options

Filter Condition

Control how the default filter matches options using the filter-condition property. The default is contains.

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 custom-filter property.

YourComponent.vue
<script setup>
import { ref } from 'vue';
const options = ref(['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany']);

const customFilter = (opts, input, condition) => {
  const trimmed = input?.toLowerCase().trim();
  if (!trimmed) return opts;
  return opts.filter(opt =>
    (opt.label || opt.value).toLowerCase().startsWith(trimmed)
  );
};
</script>
<template>
  <anchor-autocomplete :options="options" :custom-filter="customFilter" label="Search Countries"></anchor-autocomplete>
</template>

Expand Behavior

Expand on Click

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

Expand on Character Limit

The dropdown expands only after the user types a minimum number of 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 with the server response. Combine with loading to show a loading indicator while fetching.

YourComponent.vue
<script setup>
import { ref } from 'vue';

const options = ref([]);
const loading = ref(false);
const autocomplete = ref(null);
let abortController = null;

async function handleInputChange(e) {
  const searchTerm = e.detail.value;

  // Abort previous in-flight request to avoid stale results
  if (abortController) abortController.abort();
  abortController = new AbortController();

  // Show loading indicator
  loading.value = true;

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

    // Feed server-filtered results back into options
    loading.value = false;
    options.value = data.map(c => ({ value: c.id, label: c.name }));
  } catch (err) {
    if (err.name !== 'AbortError') {
      loading.value = false;
    }
  }
}
</script>
<template>
  <anchor-autocomplete
    ref="autocomplete"
    :options="options"
    :loading="loading"
    label="Search Countries"
    placeholder="Search..."
    load-text="Searching countries..."
    @inputchange="handleInputChange"
  ></anchor-autocomplete>
</template>

The inputchange event fires on every keystroke. The component's internal watcher picks up the new options automatically — no manual filter function is needed since the backend has already done the filtering.

Loading State

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

Search Icon

Show a search icon in the input using the show-icon property. The icon is visible when the dropdown is collapsed and no option is selected.

Events

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

YourComponent.vue
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';

const options = ref(['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany']);
const autocomplete = ref(null);

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

onMounted(() => {
  const el = autocomplete.value.$el;
  Object.entries(handlers).forEach(([event, handler]) =>
    el.addEventListener(event, handler)
  );
});

onUnmounted(() => {
  const el = autocomplete.value.$el;
  Object.entries(handlers).forEach(([event, handler]) =>
    el.removeEventListener(event, handler)
  );
});
</script>
<template>
  <anchor-autocomplete
    ref="autocomplete"
    :options="options"
    label="Search Countries"
    placeholder="Interact to see events in console"
  ></anchor-autocomplete>
</template>
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 property 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