Toggle Group

A set of toggles where one or many can be on.

import { … } from '@inlaylab/ivorie/toggle-group'
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_TOGGLE_GROUP_IMPORTS } from '@inlaylab/ivorie/toggle-group';
import { LucideBold, LucideItalic, LucideUnderline } from '@lucide/angular';

@Component({
  selector: 'demo-toggle-group',
  imports: [IV_TOGGLE_GROUP_IMPORTS, LucideBold, LucideItalic, LucideUnderline],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <iv-toggle-group type="multiple" aria-label="Text format">
      <button ivToggleGroupItem value="bold" aria-label="Bold"><svg lucideBold aria-hidden="true"></svg></button>
      <button ivToggleGroupItem value="italic" aria-label="Italic"><svg lucideItalic aria-hidden="true"></svg></button>
      <button ivToggleGroupItem value="underline" aria-label="Underline"><svg lucideUnderline aria-hidden="true"></svg></button>
    </iv-toggle-group>
  `,
})
export default class ToggleGroupDemo {}

Installation

CLInpm
npx ivorie add toggle-group

Usage

import { IV_TOGGLE_GROUP_IMPORTS } from '@inlaylab/ivorie/toggle-group';
<iv-toggle-group type="single" aria-label="Align" [(value)]="align">
  <button ivToggleGroupItem value="left">Left</button>
  <button ivToggleGroupItem value="right">Right</button>
</iv-toggle-group>

Examples

Single, joined

Value: grid

import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { IV_TOGGLE_GROUP_IMPORTS, ToggleGroupValue } from '@inlaylab/ivorie/toggle-group';

@Component({
  selector: 'demo-toggle-group-single',
  imports: [IV_TOGGLE_GROUP_IMPORTS],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div class="flex flex-col items-center gap-3">
      <iv-toggle-group type="single" variant="outline" [spacing]="0" aria-label="View" [(value)]="view">
        <button ivToggleGroupItem value="list">List</button>
        <button ivToggleGroupItem value="grid">Grid</button>
        <button ivToggleGroupItem value="board">Board</button>
      </iv-toggle-group>
      <p class="text-muted-foreground text-sm">Value: {{ view() ?? 'none' }}</p>
    </div>
  `,
})
export default class ToggleGroupSingleDemo {
  protected readonly view = signal<ToggleGroupValue>('grid');
}

Reactive forms

Value: Mon,Wed

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { IV_TOGGLE_GROUP_IMPORTS, ToggleGroupValue } from '@inlaylab/ivorie/toggle-group';

@Component({
  selector: 'demo-toggle-group-reactive-forms',
  imports: [IV_TOGGLE_GROUP_IMPORTS, ReactiveFormsModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div class="flex flex-col items-center gap-3">
      <iv-toggle-group type="multiple" size="sm" aria-label="Days" [formControl]="days">
        @for (d of week; track d) {
          <button ivToggleGroupItem [value]="d">{{ d }}</button>
        }
      </iv-toggle-group>
      <p class="text-muted-foreground text-sm">Value: {{ days.value }}</p>
    </div>
  `,
})
export default class ToggleGroupReactiveFormsDemo {
  protected readonly week = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
  protected readonly days = new FormControl<ToggleGroupValue>(['Mon', 'Wed']);
}

API

Every part also accepts class.

iv-toggle-group

Works with formControl, formControlName and ngModel.

Name Type Default Description
type 'single' | 'multiple' 'single' One pressed item, or many.
value string | string[] | null null single: the value or null. multiple: the list of values.
disabled boolean false Disables every item.
variant 'default' | 'outline' 'default' Look of every item.
size 'default' | 'sm' | 'lg' 'default' Size of every item.
spacing number 2 Gap in spacing units. 0 joins the items.
orientation 'horizontal' | 'vertical' 'horizontal' Layout and arrow keys.

Outputs:

Name Payload Description
valueChange string | string[] | null The new value.

button[ivToggleGroupItem]

Name Type Default Description
value string required The item's value.
disabled boolean false Disables this item.

Accessibility

  • The group has role="group"; give it an aria-label.
  • single: items are role="radio" with aria-checked. multiple: items use aria-pressed.
  • One tab stop. Arrow keys move focus, Home and End jump to the ends. Space and Enter press.