# Autocomplete

Komponente des SBB Design Systems Lyne.

- Paket: `@sbb-esta/lyne-elements` (Angular: `@sbb-esta/lyne-angular`)
- Aufbau: Hauptelement mit Bestandteilen; Bestandteile nur innerhalb des jeweiligen Elements verwenden
- Kategorien: Form
- Status: Gestaltungsrichtlinien vollständig

## Links

- Seite auf digital.sbb.ch: https://digital.sbb.ch/de/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

## Elemente

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

## Verwandte Komponenten

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

## Übersicht

### Was macht die Komponente?
Die Komponente schlägt den Nutzenden während der Eingabe passende Optionen vor, basierend auf vorhandenen Daten oder früheren Eingaben. Optionen können gruppiert werden und neben der Option zusätzliche Aktions-Buttons zeigen, zum Beispiel zum Bearbeiten oder Entfernen.

### Wann soll die Komponente eingesetzt werden?
* Um die Eingabe zu erleichtern und zu beschleunigen, indem mögliche Eingaben vorgeschlagen werden.
* Um die Genauigkeit und Konsistenz der eingegebenen Daten zu erhöhen.
* Wenn zu einer Option eine Aktion nötig ist, zum Beispiel einen Eintrag aus dem Verlauf zu entfernen.

### Regeln.
* Bei kleinen Datensätzen ist stattdessen ein [Select](https://digital.sbb.ch/de/design-system/lyne/components/select/) zu verwenden.
* Die Liste zeigt nicht zu viele Vorschläge auf einmal (max. 10).
* Nutzende können die Vorschläge ignorieren und eigene Eingaben machen.
* Aktions-Buttons gehören zusammen mit der Option in eine Autocomplete-Row. Pro Option sind ein oder mehrere Buttons möglich, nicht alle Optionen brauchen einen.
* Die Buttons sind nicht per Tab erreichbar, sondern nur mit den Pfeiltasten (rechts/links). Auf ihre Existenz wird mit einer `aria-description` an der Option hingewiesen.
* In Optionen selbst dürfen keine anderen interaktiven Elemente wie Buttons oder Checkboxen stehen.

## Implementation (Web Components, Englisch)

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, Englisch)

Vollständige API-Tabellen (Attribute, Events, Slots, CSS-Eigenschaften): https://digital.sbb.ch/de/design-system/lyne/components/autocomplete/api.md
