# Autocomplete

Component of the SBB design system Lyne.

- Package: `@sbb-esta/lyne-elements` (Angular: `@sbb-esta/lyne-angular`)
- Structure: main element with parts; use parts only within the element they belong to
- Categories: Form
- Status: Design guidelines complete

## Links

- Page on digital.sbb.ch: https://digital.sbb.ch/en/design-system/lyne/components/autocomplete/
- Storybook: https://lyne-elements.app.sbb.ch/?path=/docs/elements-autocomplete--docs
- Angular (`@sbb-esta/lyne-angular`): https://lyne-angular.app.sbb.ch/angular/components/autocomplete/overview (API: https://lyne-angular.app.sbb.ch/angular/components/autocomplete/api)
- Figma: https://www.figma.com/design/mWknI2rC5DJmOgRO61WKai/Lyne-Components?node-id=7491-13
- GitHub: https://github.com/sbb-design-systems/lyne-components/tree/v5.12.0/src/elements/autocomplete

## Elements

- `sbb-autocomplete`: Combined with a native input, it displays a panel with a list of available options.
  - `sbb-autocomplete-row`, only within `sbb-autocomplete`: The component is used as a wrapper for an option and one or more action buttons.
    - `sbb-autocomplete-button`, only within `sbb-autocomplete-row`: It displays an icon-only button that can be used in a `sbb-autocomplete-row`.

## Related components

- Similar: [Select](https://digital.sbb.ch/en/design-system/lyne/components/select/index.md)

## Overview

### What does the component do?
The component suggests matching options to users while they type, based on existing data or previous input. Options can be grouped and can show additional action buttons next to the option, for example to edit or remove it.

### When should the component be used?
* To make input easier and faster by suggesting possible inputs.
* To increase the accuracy and consistency of the entered data.
* When an option needs an action, for example removing an entry from the history.

### Rules.
* For small data sets, use a [select](https://digital.sbb.ch/en/design-system/lyne/components/select/) instead.
* The list does not show too many suggestions at once (max. 10).
* Users can ignore the suggestions and enter their own input.
* Action buttons belong together with their option in an autocomplete row. One or more buttons per option are possible, and not every option needs one.
* The buttons cannot be reached with the Tab key, only with the arrow keys (right/left). Their existence is announced with an `aria-description` on the option.
* Options themselves must not contain other interactive elements such as buttons or checkboxes.

## Implementation (web components)

The `<sbb-autocomplete>` is a component that can be used to display a panel of suggested options connected to a text input.
Use it when you need a basic autocomplete: a panel with a list of selectable and possibly grouped options.

It's possible to set the element to which the component's panel will be attached using the `origin` prop,
and the input which will work as a trigger using the `trigger` prop.
Both accept an id or an element reference.

```html
<!-- Origin element -->
<div id="autocomplete-origin">Another origin</div>

<!-- Trigger element -->
<input id="autocomplete-txt" placeholder="Another trigger element" />

<sbb-autocomplete origin="autocomplete-origin" trigger="autocomplete-txt">
  <sbb-option value="Option A">Option A</sbb-option>
  <sbb-option value="Option B">Option B</sbb-option>
  <sbb-option value="Option C">Option C</sbb-option>
</sbb-autocomplete>
```

### In `<sbb-form-field>`

If the component is used within a [sbb-form-field](https://lyne-elements.app.sbb.ch/?path=/docs/elements-form-field--docs),
it will automatically connect to the native `<input>` as trigger and will display the option panel above or below the `<sbb-form-field>`.

```html
<!-- Origin element -->
<sbb-form-field>
  <label>Label</label>
  <!-- Trigger element -->
  <input placeholder="Trigger element" />

  <sbb-autocomplete>
    <sbb-option icon-name="clock-small" value="Option 1"> Option 1 </sbb-option>
    <sbb-option icon-name="clock-small" value="Option 2"> Option 2 </sbb-option>
    <sbb-option icon-name="clock-small" value="Option 3"> Option 3 </sbb-option>
  </sbb-autocomplete>
</sbb-form-field>
```

### Style

#### Option highlight

By default, the autocomplete will highlight the label of the `<sbb-option>` in the panel, if it matches the typed text.
See the [sbb-option](https://lyne-elements.app.sbb.ch/?path=/docs/elements-option--docs) for more details.

#### Option grouping

The displayed `<sbb-option>` can be collected into groups using `<sbb-optgroup>` element:

```html
<!-- Origin element -->
<sbb-form-field>
  <label>Label</label>
  <!-- Trigger element -->
  <input placeholder="Trigger element" />

  <sbb-autocomplete>
    <sbb-optgroup label="Group 1">
      <sbb-option icon-name="clock-small" value="Option 1"> Option 1 </sbb-option>
      ...
    </sbb-optgroup>
    <sbb-optgroup label="Group 2"> ... </sbb-optgroup>
  </sbb-autocomplete>
</sbb-form-field>
```

#### Size

The component has a `size` property with two sizes available. When slotted in a `<sbb-form-field>` element, it adapts to the `<sbb-form-field>` element `size`.

```html
<sbb-form-field size="s">
  <label>Label</label>
  <input placeholder="Trigger element" />
  <sbb-autocomplete> ... </sbb-autocomplete>
</sbb-form-field>
```

#### Ellipsis

It's possible to truncate the label (apply ellipsis) of slotted `<sbb-option>` elements with the `sbb-options-nowrap` CSS class.
To select which elements should be affected, the consumer can set the class on either the `html` tag, the `<sbb-autocomplete>`, or the single `<sbb-option>`.

### Actions

An `<sbb-option>` can be paired with one or more action buttons by wrapping it, together with one or more `<sbb-autocomplete-button>`, in an `<sbb-autocomplete-row>`:

```html
<sbb-autocomplete>
  <sbb-autocomplete-row>
    <sbb-option value="Option 1">Option 1</sbb-option>
    <sbb-autocomplete-button icon-name="pen-small"></sbb-autocomplete-button>
  </sbb-autocomplete-row>
  <sbb-option value="Option 2">Option 2</sbb-option>
</sbb-autocomplete>
```

Options without an associated action can be used as usual, without wrapping them in an `<sbb-autocomplete-row>`.

#### Accessibility

If needed, add an `aria-description`/ `aria-described-by` to the `<sbb-option>` to announce the existence of the action buttons.
This will be read by screen readers when the option is focused.

> There is a known issue with NVDA screen reader about keyboard navigation into actions.

### Events

The `<sbb-option>` emits the `optionSelected` event when selected via user interaction.

### Keyboard interaction

The options panel opens on `focus`, `click` or `input` events on the trigger element, or on `ArrowDown` keypress;
it can be closed on backdrop click, or using the `Escape` or `Tab` keys.

| Keyboard               | Action                                                                                              |
| ---------------------- | --------------------------------------------------------------------------------------------------- |
| <kbd>Down Arrow</kbd>  | Navigate to the next option. Open the panel, if closed.                                             |
| <kbd>Up Arrow</kbd>    | Navigate to the previous option.                                                                    |
| <kbd>Right Arrow</kbd> | If the active option has one or more action buttons, navigate to the next one. No-op otherwise.     |
| <kbd>Left Arrow</kbd>  | If the active option has one or more action buttons, navigate to the previous one. No-op otherwise. |
| <kbd>Enter</kbd>       | Select the active option, or activate the focused action button.                                    |
| <kbd>Escape</kbd>      | Close the autocomplete panel.                                                                       |

#### `autoSelectActiveOption`

With `autoSelectActiveOption` enabled, navigating between options also selects them, without having to press the `Enter`.
The `input` and `change` events emission are postponed to when the panel is closed or on blur.

#### `autoSelectActiveOptionOnBlur`

With `autoSelectActiveOptionOnBlur` enabled, the active option is automatically selected when the input field loses focus.
To prevent accidental selections, this mechanism will not trigger if the input is cleared.

This can be used in combination with `autoActiveFirstOption` to speed up form completion in copy-paste scenarios.
Be aware that this can lead to unexpected behavior. Carefully test your use case.

#### `requireSelection`

Use the `requireSelection` to clear the input if the user does not explicitly select an option, via mouse click or keyboard selection.

### Complex Values

This component supports any types of values, including complex objects.
The type can be specified using the generic type parameter `T` of `SbbAutocomplete<T>` and `SbbOption<T>`.

```ts
const values = [
  { value: 'value 1', name: 'Option 1' },
  { value: 'value 2', name: 'Option 2' },
];
```

```html
<sbb-form-field>
  <input />
  <sbb-autocomplete .displayWith="${(value) => value.name}">
    <sbb-option .value="${values[0]}">Option 1</sbb-option>
    <sbb-option .value="${values[1]}">Option 2</sbb-option>
  </sbb-autocomplete>
</sbb-form-field>
```

#### `displayWith` function

When using complex values, the selection should most likely still be represented as text.
To achieve this, you can use the `displayWith` property which accepts a function.
This function receives the selected value and should return a string.

Please note that the parameter is the assigned value of the selected option which does not necessarily
align with the type information.

### Accessibility

The `<sbb-autocomplete>` implements the [ARIA combobox interaction pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/).

The text input trigger specifies `role="combobox"` while the content of the pop-up applies `role="listbox"`.
Because of this `listbox` pattern, you should not put other interactive controls, such as buttons or checkboxes, inside an autocomplete option.
Nesting interactive controls like this interferes with many assistive technologies.

The component preserves focus on the input trigger,
using `aria-activedescendant` to support navigation though the autocomplete options.

The `<sbb-autocomplete-button>` has `role="button"`. Since focus is always kept on the input trigger,
buttons can't be reached via <kbd>Tab</kbd>, but only with the <kbd>Left</kbd>/<kbd>Right Arrow</kbd> keys.

## API (web components)

Full API tables (attributes, events, slots, CSS properties): https://digital.sbb.ch/en/design-system/lyne/components/autocomplete/api.md
