# Toggle Group

A set of two-state buttons that can be toggled on or off with either single or multiple selection.

Use Toggle Group for formatting toolbars, persistent filters, view-mode switches, or any compact control cluster where each item represents a pressed state instead of an immediate action.

## Import

```ts
import { ToggleGroupComponent, ToggleGroupItemDirective } from '@edsis/component/toggle-group';
```

## Composition

The Angular structure keeps the same root-plus-items shape as shadcn and Radix while translating the API to strongly typed Angular bindings.

```text
ToggleGroup
├── button[ToggleGroupItem]
└── button[ToggleGroupItem]
```

## Basic usage

Use `[(value)]` for single-select groups and `[(values)]` for multi-select groups.

```ts
readonly alignment = signal<string | null>('center');
readonly styles = signal<string[]>(['bold']);
```

```html
<ToggleGroup type="single" [(value)]="alignment" variant="outline" aria-label="Text alignment">
  <button ToggleGroupItem value="left" aria-label="Left aligned">Left</button>
  <button ToggleGroupItem value="center" aria-label="Center aligned">Center</button>
  <button ToggleGroupItem value="right" aria-label="Right aligned">Right</button>
</ToggleGroup>
```

```html
<ToggleGroup type="multiple" [(values)]="styles" variant="outline" aria-label="Text styles">
  <button ToggleGroupItem value="bold" aria-label="Bold">Bold</button>
  <button ToggleGroupItem value="italic" aria-label="Italic">Italic</button>
  <button ToggleGroupItem value="underline" aria-label="Underline">Underline</button>
</ToggleGroup>
```

## Common patterns

### Outline

Use `variant="outline"` when the group should read like a bordered toolbar or filter control.

```html
<ToggleGroup type="single" [(value)]="filter" variant="outline" aria-label="Message filters">
  <button ToggleGroupItem value="all">All</button>
  <button ToggleGroupItem value="missed">Missed</button>
</ToggleGroup>
```

### Size

Set `size` on the root so every child item scales together.

```html
<ToggleGroup
  type="single"
  [(value)]="alignment"
  variant="outline"
  size="lg"
  aria-label="Large alignment"
>
  <button ToggleGroupItem value="left">Left</button>
  <button ToggleGroupItem value="center">Center</button>
  <button ToggleGroupItem value="right">Right</button>
</ToggleGroup>
```

### Spacing

Spacing defaults to `2`, matching the current shadcn docs. Use `spacing="0"` for connected items or larger values for looser toolbars.

```html
<ToggleGroup
  type="single"
  [(value)]="alignment"
  variant="outline"
  spacing="0"
  aria-label="Connected alignment"
>
  <button ToggleGroupItem value="left">Left</button>
  <button ToggleGroupItem value="center">Center</button>
  <button ToggleGroupItem value="right">Right</button>
</ToggleGroup>
```

### Vertical orientation

Use `orientation="vertical"` to stack items while keeping the same roving-focus keyboard behavior.

```html
<ToggleGroup
  type="multiple"
  [(values)]="styles"
  orientation="vertical"
  spacing="1"
  aria-label="Text styles"
>
  <button ToggleGroupItem value="bold" aria-label="Toggle bold">Bold</button>
  <button ToggleGroupItem value="italic" aria-label="Toggle italic">Italic</button>
  <button ToggleGroupItem value="underline" aria-label="Toggle underline">Underline</button>
</ToggleGroup>
```

### Disabled group

Disable the root when the whole cluster is unavailable.

```html
<ToggleGroup
  type="multiple"
  [(values)]="styles"
  variant="outline"
  [disabled]="true"
  aria-label="Unavailable text styles"
>
  <button ToggleGroupItem value="bold">Bold</button>
  <button ToggleGroupItem value="italic">Italic</button>
  <button ToggleGroupItem value="underline">Underline</button>
</ToggleGroup>
```

### Custom controlled state

The selected value can drive any Angular signal, such as font weight, filters, or an editor mode.

```ts
readonly fontWeight = signal<string | null>('normal');
```

```html
<ToggleGroup
  type="single"
  [(value)]="fontWeight"
  variant="outline"
  size="lg"
  aria-label="Font weight"
>
  <button ToggleGroupItem value="light" class="min-w-24">Light</button>
  <button ToggleGroupItem value="normal" class="min-w-24">Normal</button>
  <button ToggleGroupItem value="medium" class="min-w-24">Medium</button>
  <button ToggleGroupItem value="bold" class="min-w-24">Bold</button>
</ToggleGroup>
```

### RTL

Direction comes from the surrounding layout. Horizontal arrow navigation respects the active text direction automatically.

```html
<div dir="rtl" lang="ar" class="text-right">
  <ToggleGroup type="single" [(value)]="view" variant="outline" aria-label="طريقة العرض">
    <button ToggleGroupItem value="list">قائمة</button>
    <button ToggleGroupItem value="grid">شبكة</button>
    <button ToggleGroupItem value="cards">بطاقات</button>
  </ToggleGroup>
</div>
```

## API reference

### `ToggleGroupComponent`

| Input or model | Type                         | Default        |
| -------------- | ---------------------------- | -------------- |
| `type`         | `'single' \| 'multiple'`     | required       |
| `value`        | `string \| null`             | `null`         |
| `values`       | `string[]`                   | `[]`           |
| `orientation`  | `'horizontal' \| 'vertical'` | `'horizontal'` |
| `variant`      | `'default' \| 'outline'`     | `'default'`    |
| `size`         | `'sm' \| 'default' \| 'lg'`  | `'default'`    |
| `spacing`      | `0 \| 1 \| 2 \| 3 \| 4`      | `2`            |
| `loop`         | `boolean`                    | `true`         |
| `disabled`     | `boolean`                    | `false`        |
| `dir`          | `'ltr' \| 'rtl' \| null`     | `null`         |
| `class`        | `string`                     | `''`           |

### `ToggleGroupItemDirective`

| Input      | Type      | Default |
| ---------- | --------- | ------- |
| `value`    | `string`  | —       |
| `disabled` | `boolean` | `false` |
| `class`    | `string`  | `''`    |

Host: `button[ToggleGroupItem]`.

The item host exposes `aria-pressed`, `data-state="on|off"`, `data-variant`, `data-size`, `data-orientation`, and `data-disabled` for styling and testing hooks.

## Styling and theming

- Toggle Group items intentionally share the same `variant` and `size` contract as the standalone Toggle primitive, so grouped toolbars and standalone toggles stay visually aligned.
- Use `spacing` for inter-item layout. When `spacing="0"`, the root collapses adjacent radius and borders so outline items read as a connected control.
- Use `class` on the root or an item for width, alignment, or card-like custom presentations.

## Accessibility

- `ToggleGroup` renders `role="group"`; provide `aria-label` or `aria-labelledby` when the cluster needs an accessible name.
- `button[ToggleGroupItem]` keeps native button semantics and exposes `aria-pressed` for the two-state pattern.
- Add an `aria-label` to icon-only items.
- Disabled items stay visible and are skipped by the group keyboard navigation.

## Keyboard interactions

- Tab moves focus to the pressed item or the first enabled item in the group.
- Enter and Space activate or deactivate the current item through the native button click.
- Arrow keys move focus through the group.
- `Home` and `End` jump to the first or last enabled item.
- Horizontal arrow movement respects RTL direction.

## Angular notes

- Use `[(value)]` in single mode and `[(values)]` in multiple mode instead of overloading one input with two types.
- The item host selector is `button[ToggleGroupItem]`; consumers do not add `Toggle` separately.
- The root owns roving focus, so consumer templates do not need extra CDK focus utilities.

## Source parity

This Angular implementation follows the current shadcn Toggle Group docs for outline styling, size scaling, spacing, vertical orientation, disabled groups, custom controlled state, RTL behavior, and the Radix roving-focus keyboard contract.

The intentional Angular deviation is the binding split between `value` and `values`, which keeps signal types explicit for single and multiple modes.
