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-libraryUsage
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.
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');<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.
<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
<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
<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.
<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.
<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.
<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 textendsWith— 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.
<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.
<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.
<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>| Event | Detail 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"witharia-expanded,aria-controls, andaria-activedescendant - The dropdown list uses
role="listbox" - Options use
role="option"witharia-selectedstate - 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
- Avoid very long option names to facilitate understanding and perception.
- Don't use the same word or phrase at the beginning of a set of options.
- If the autocomplete is a required field, include the
requiredproperty 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
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
charLimit | char-limit | Character limit to expand on for Autocomplete | number | 1 |
disabled | disabled | Disable flag for Autocomplete | boolean | false |
errTextPlacement | err-text-placement | This 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' |
errorText | error-text | Error text for Autocomplete | string | "default error text" |
expandOn | expand-on | Expand condition for Autocomplete | "charLimit" | "click" | 'click' |
filterCondition | filter-condition | Filter 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 |
helpText | help-text | Helpful Text for Autocomplete | string | undefined |
inputValue | input-value | Value inputed | string | undefined |
label | label | Label for Autocomplete | string | undefined |
loadText | load-text | Text to show when loading is true | string | "Searching..." |
loading | loading | To set a loading state while options are recieved | boolean | false |
noOptionsErrorText | no-options-error-text | No options text for Autocomplete | string | "No Options found" |
options | options | Options for Autocomplete | (string | OptionValue)[] | string | undefined |
placeholder | placeholder | Placeholder Text for Autocomplete | string | undefined |
readonly | readonly | ReadOnly flag for Autocomplete | boolean | false |
required | required | Mark the field as required for form validation. | boolean | false |
showError | show-error | Show error on not selecting from dropdown | boolean | true |
showIcon | show-icon | Show search icon for Autocomplete | boolean | false |
uuid | uuid | The unique id of the input field | string | uuidv4() |
Events
| Event | Description | Type |
|---|---|---|
blurevent | Event emitted when the input loses focus | CustomEvent<AutocompleteBlurEventDetail> |
collapse | Event emitted when the dropdown collapses | CustomEvent<AutocompleteCollapseEventDetail> |
expand | Event emitted when the dropdown expands | CustomEvent<AutocompleteExpandEventDetail> |
focusevent | Event emitted when the input receives focus | CustomEvent<AutocompleteFocusEventDetail> |
highlight | Event emitted for a highlighted selection when a user uses arrow keys for navigating options | CustomEvent<AutocompleteHighlightEventDetail> |
inputchange | Event emitted when input field is changed | CustomEvent<AutocompleteInputEventDetail> |
selectevent | Event emitted when a valid option has been selected | CustomEvent<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:4pxBuilt with StencilJS
