API reference
tngToggle gives a native <button> pressed semantics, while tngToggleGroup coordinates shared selection when multiple toggles belong to one decision surface.
tngToggle
Attach the directive to a native button. The directive keeps keyboard behavior native, reflects aria-pressed, and supports both controlled and uncontrolled usage.
Standalone toggle
<button
tngToggle
[pressed]="showGrid()"
ariaLabel="Grid view"
(pressedChange)="showGrid.set($event)"
>
Grid
</button>
| Input | Type | Default | Details |
|---|---|---|---|
tngToggleValue | string | null | null | Item identity when the toggle participates in a group. |
pressed | boolean | null | '' | 'true' | 'false' | null | Controlled pressed state for standalone usage. |
defaultPressed | boolean | '' | string | false | Initial pressed state when the toggle manages itself. |
disabled | boolean | '' | string | false | Disables interaction and reflects disabled attributes. |
ariaLabel, ariaLabelledby, ariaDescribedBy | string | null | null | Accessible naming and helper-text hooks. |
pressedChange | EventEmitter<boolean> | n/a | Emits the next pressed state after interaction. |
When a grouped toggle has a non-empty tngToggleValue, the group owns its visual pressed state. In that case, use the group outputs instead of standalone pressed control.
tngToggleGroup
Add the group directive to any container when toggles should share a selection model. Single-selection groups emit valueChange; multi-selection groups emit valuesChange.
Single-select group
<div
tngToggleGroup
selectionMode="single"
ariaLabel="View mode"
[value]="viewMode()"
(valueChange)="onViewModeChange($event)"
>
<button tngToggle tngToggleValue="grid">Grid</button>
<button tngToggle tngToggleValue="list">List</button>
<button tngToggle tngToggleValue="split">Split</button>
</div>
| Input | Type | Default | Details |
|---|---|---|---|
selectionMode | 'single' | 'multiple' | 'multiple' | Switches between single-choice and multi-select behavior. |
orientation | 'horizontal' | 'vertical' | 'horizontal' | Orientation hook for layout and accessibility messaging. |
value, defaultValue | string | null | null | Controlled and uncontrolled single-select values. |
values, defaultValues | readonly string[] | [] | Controlled and uncontrolled multiple-select values. |
disabled | boolean | '' | string | false | Disables every child toggle through the shared group state. |
ariaLabel, ariaLabelledby | string | null | null | Accessible name for the group region. |
valueChange, valuesChange | EventEmitter | n/a | Selection outputs for single or multiple mode. |
Reflected attributes
| Selector | Applied on | Purpose |
|---|---|---|
data-slot="toggle" | Toggle button | Stable styling hook for the primitive button. |
data-state="on" | "off" | Toggle button | Pressed state styling and animation hook. |
data-disabled | Toggle button + group | Disabled styling for item and shared surface. |
data-focused, data-focus-visible | Toggle button | Focus and keyboard-focus differentiation. |
data-slot="toggle-group" | Group host | Stable hook for container styling. |
data-selection-mode, data-orientation | Group host | Layout and state styling hooks on the container. |
role="group" | Group host | Communicates grouped semantics to assistive technology. |
Change handling
Standalone toggles emit booleans. Groups emit the selected value or values depending on the selection mode.
State handling
import { signal } from '@angular/core';
type ToggleViewMode = 'grid' | 'list' | 'split';
readonly viewMode = signal<ToggleViewMode>('grid');
function onViewModeChange(value: string | null): void {
if (value === 'grid' || value === 'list' || value === 'split') {
viewMode.set(value);
}
}
function onBoldPressedChange(nextPressed: boolean): void {
boldEnabled.set(nextPressed);
}