# Tag

Component of the SBB design system Lyne.

- Package: `@sbb-esta/lyne-elements` (Angular: `@sbb-esta/lyne-angular`)
- Structure: one element with optional grouping
- Categories: Container
- Status: Design guidelines complete

## Links

- Page on digital.sbb.ch: https://digital.sbb.ch/en/design-system/lyne/components/tag/
- Storybook: https://lyne-elements.app.sbb.ch/?path=/docs/elements-tag--docs
- Angular (`@sbb-esta/lyne-angular`): https://lyne-angular.app.sbb.ch/angular/components/tag/overview (API: https://lyne-angular.app.sbb.ch/angular/components/tag/api)
- GitHub: https://github.com/sbb-design-systems/lyne-components

## Elements

- `sbb-tag`, several can be combined with `sbb-tag-group`: It displays a selectable element which can be used as a filter.

## Related components

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

## Overview

### What does the component do?
A tag is a small labelling element that is used for categorisation and as a filter.

### When should the component be used?
* To filter and categorise content according to certain criteria.
* To allow users to search content according to defined properties.
* To make the user interface clearer.

### Rules.
* Tags should be short and clearly labelled.
* Use a logical and intuitive order of tags to maximise usability.
* Avoid too many tags at once to ensure clarity.

## Implementation (web components)

Tags categorize large amounts of information and filter content through user selection.

The `<sbb-tag-group>` is a container for one or more `<sbb-tag>` components.
Each `<sbb-tag>` must have a `value` property.

```html
<sbb-tag-group>
  <sbb-tag value="all">All</sbb-tag>
  <sbb-tag value="phones" amount="23">Phones</sbb-tag>
  <sbb-tag value="computer" amount="3">Computer</sbb-tag>
  <sbb-tag value="laptop" amount="99">Laptop</sbb-tag>
</sbb-tag-group>
```

### Style

The `size` property on `<sbb-tag-group>` (values: `s`, `m`) is applied to all contained `<sbb-tag>` elements.

```html
<sbb-tag-group size="m">
  <sbb-tag value="all">All</sbb-tag>
  <sbb-tag value="phones">Phones</sbb-tag>
  <sbb-tag value="computer">Computer</sbb-tag>
</sbb-tag-group>

<sbb-tag-group size="s">
  <sbb-tag value="all">All</sbb-tag>
  <sbb-tag value="phones">Phones</sbb-tag>
  <sbb-tag value="computer">Computer</sbb-tag>
</sbb-tag-group>
```

### Interactions

#### Exclusive selection vs. multiple selection

By default, `<sbb-tag-group>` behaves like a radio button group: only one tag can be selected at a time.
The `value` of the `<sbb-tag-group>` reflects the `value` of the selected `<sbb-tag>`.

Set the `multiple` property to allow multiple selections (checkbox behavior).
In this mode, the `value` is an array containing all selected tag values.

```html
<sbb-tag-group multiple>
  <sbb-tag value="all">All</sbb-tag>
  <sbb-tag value="phones" checked>Phones</sbb-tag>
  <sbb-tag value="computer" checked>Computer</sbb-tag>
  <sbb-tag value="laptop">Laptop</sbb-tag>
</sbb-tag-group>
```

**Note:** Changing the `multiple` property at runtime is not supported. Set this property during initialization.

#### Advanced usage: multiple and exclusive mixed

```ts
const uncheckAllTag = () => {
  document.getElementById('all').removeAttribute('checked');
};

const uncheckTags = () => {
  Array.from(document.querySelectorAll('sbb-tag'))
    .filter((e) => e.getAttribute('id') !== 'all' && !e.getAttribute('disabled'))
    .forEach((e) => e.removeAttribute('checked'));
};
```

```html
<sbb-tag-group aria-label="Select your desired device to filter it" multiple>
  <sbb-tag id="all" onchange="uncheckTags()" value="All" checked> All </sbb-tag>
  <sbb-tag value="phones" onchange="uncheckAllTag()">Phones</sbb-tag>
  <sbb-tag value="computer" onchange="uncheckAllTag()">Computer</sbb-tag>
  <sbb-tag value="laptop" onchange="uncheckAllTag()">Laptop</sbb-tag>
</sbb-tag-group>
```

### States

Tags support `checked` and `disabled` states. Set `disabled` on the `<sbb-tag-group>` to disable all contained tags.

### Slots

It is possible to provide a label via an unnamed slot; the component can optionally display a `<sbb-icon>`
at the component start using the `iconName` property or via custom content using the `icon` slot.

It's also possible to display a numeric amount at the component's end using the `amount` property or slot.

```html
<sbb-tag value="All" icon-name="pie-small" amount="123"> All </sbb-tag>

<sbb-tag value="None">
  <sbb-icon slot="icon" name="pie-small"></sbb-icon>
  None
  <span slot="amount">123</span>
</sbb-tag>
```

### Complex Values

The `<sbb-tag>` element supports any types of values, including complex objects.
The type can be specified using the generic type parameter `T` of `SbbTag<T>`.

```html
<sbb-tag .value=${{value: 'value', name: 'name'}} name="name">Option</sbb-tag>
```

### Events

Consumers can listen to the native `change` and `input` events on the `<sbb-tag>`.
The current state can be read from `event.target.checked`, while the value from `event.target.value`.
It's recommended to check the parent's `<sbb-tag-group>` for the value.

### Accessibility

#### Exclusive mode (default)

In exclusive (non-multiple) mode, `<sbb-tag-group>` behaves like a radio group (`role="radiogroup"`).
Each `<sbb-tag>` acts as a radio button and the state is reflected via `aria-checked`.

Keyboard navigation follows the roving tabindex pattern:

- Only the currently selected tag (or the first tag if none is selected) receives `tabindex="0"`;
  all other tags receive `tabindex="-1"`.
- **Arrow keys** (Left/Right/Up/Down) move focus and selection to the adjacent tag, wrapping around
  at the ends. Disabled tags are skipped automatically.
- **Tab** moves focus into and out of the group without changing the selection.

```html
<sbb-tag-group accessibility-label="Select your desired device to filter it">
  <sbb-tag value="all" checked>All</sbb-tag>
  <sbb-tag value="phones">Phones</sbb-tag>
  <sbb-tag value="computer">Computer</sbb-tag>
  <sbb-tag value="laptop">Laptop</sbb-tag>
</sbb-tag-group>
```

#### Multiple mode

In multiple mode, each `<sbb-tag>` behaves like a toggle button. The state is reflected via `aria-pressed`.

The `<sbb-tag-group>` applies `role="group"` (when no `accessibilityLabel` is set) to convey
the association between the individual tags. Each group should be given a label via `accessibilityLabel`
that communicates the collective meaning of all tags.

The `accessibilityLabel` property on `<sbb-tag-group>` is forwarded as `aria-label` to the
inner list element. When provided, the implicit `role="group"` is omitted in favor of the
labeled list.

```html
<sbb-tag-group multiple accessibility-label="Select your desired font styles to filter it">
  <sbb-tag value="bold" checked>Bold</sbb-tag>
  <sbb-tag value="italic">Italic</sbb-tag>
  <sbb-tag value="underline">Underline</sbb-tag>
</sbb-tag-group>
```

## API (web components)

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