Actions
Toggle Button Group
Make the selected option visible in a group of toggles.
Import
import { NeuToggleButtonGroupComponent } from '@neural-ui/native/toggle-button-group';Examples
Import ExampleComponent into its parent and place <app-example /> inside your application’s root neu-theme. The preview supplies the device frame and safe areas; use the root setup from Installation in your app.
Single selection
Choose a calendar view. The filled segment marks the current choice; tap it again to clear it.
View and copy the complete example
import { Component, signal } from '@angular/core';
import { NeuToggleButtonGroupComponent } from '@neural-ui/native/toggle-button-group';
import { View, Text, ScrollView } from '@ng-native/components';
import type { NeuOption } from '@neural-ui/native';
@Component({
selector: 'app-example',
imports: [NeuToggleButtonGroupComponent, View, Text, ScrollView],
template: `
<scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
<view class="toggle-example">
<text class="usage-heading">Calendar view</text>
<neu-toggle-button-group label="Calendar view" [options]="periods" [(value)]="period" />
<view class="toggle-preview">
<text class="usage-heading">{{ period()[0] === 'day' ? 'Daily overview' : period()[0] === 'week' ? 'Weekly overview' : period()[0] === 'month' ? 'Monthly overview' : 'Choose a view' }}</text>
<text class="usage-caption">{{ period().length ? 'Your schedule follows the selected view.' : 'Tap a segment to choose how to view your schedule.' }}</text>
</view>
</view>
</view></scroll-view>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
.usage-scroll { flex: 1; }
.usage-stack { gap: 20px; padding-bottom: 20px; }
.usage-section { gap: 12px; }
.usage-heading { color: var(--neu-text, #172033); font-size: 16px; font-weight: 600; }
.usage-caption { color: var(--neu-muted, #64748b); font-size: 14px; }
.usage-row { flex-direction: row; flex-wrap: wrap; gap: 12px; align-items: center; }
.usage-actions { flex-direction: row; flex-wrap: wrap; gap: 8px; align-items: center; }
.toggle-example { gap: 16px; } .toggle-preview { gap: 10px; padding: 16px; border-radius: 12px; background-color: var(--neu-surface, #ffffff); border-width: 1px; border-color: var(--neu-border, #a5afbf); } .toggle-summary { color: var(--neu-text, #172033); font-size: 14px; }
`,
})
export class ExampleComponent {
readonly periods: readonly NeuOption[] = [{ id: 'day', label: 'Day' }, { id: 'week', label: 'Week' }, { id: 'month', label: 'Month' }];
readonly period = signal<readonly string[]>(['week']);
}Multiple selection
Enable several update channels. Each highlighted segment stays selected independently.
View and copy the complete example
import { Component, signal } from '@angular/core';
import { NeuToggleButtonGroupComponent } from '@neural-ui/native/toggle-button-group';
import { View, Text, ScrollView } from '@ng-native/components';
import type { NeuOption } from '@neural-ui/native';
@Component({
selector: 'app-example',
imports: [NeuToggleButtonGroupComponent, View, Text, ScrollView],
template: `
<scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
<view class="toggle-example">
<text class="usage-heading">Update channels</text>
<neu-toggle-button-group label="Update channels" [options]="channels" [multiple]="true" [(value)]="selected" />
<view class="toggle-preview">
<text class="usage-heading">Delivery preferences</text>
<text class="usage-caption">{{ selected().length ? 'Updates will use the highlighted channels.' : 'Updates are paused. Choose one or more channels.' }}</text>
@if (selected().includes('email')) { <text class="toggle-summary">Email updates enabled</text> }
@if (selected().includes('push')) { <text class="toggle-summary">Push notifications enabled</text> }
@if (selected().includes('sms')) { <text class="toggle-summary">SMS updates enabled</text> }
</view>
</view>
</view></scroll-view>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
.usage-scroll { flex: 1; }
.usage-stack { gap: 20px; padding-bottom: 20px; }
.usage-section { gap: 12px; }
.usage-heading { color: var(--neu-text, #172033); font-size: 16px; font-weight: 600; }
.usage-caption { color: var(--neu-muted, #64748b); font-size: 14px; }
.usage-row { flex-direction: row; flex-wrap: wrap; gap: 12px; align-items: center; }
.usage-actions { flex-direction: row; flex-wrap: wrap; gap: 8px; align-items: center; }
.toggle-example { gap: 16px; } .toggle-preview { gap: 10px; padding: 16px; border-radius: 12px; background-color: var(--neu-surface, #ffffff); border-width: 1px; border-color: var(--neu-border, #a5afbf); } .toggle-summary { color: var(--neu-text, #172033); font-size: 14px; }
`,
})
export class ExampleComponent {
readonly channels: readonly NeuOption[] = [{ id: 'email', label: 'Email' }, { id: 'push', label: 'Push' }, { id: 'sms', label: 'SMS' }];
readonly selected = signal<readonly string[]>(['email', 'push']);
}Interactive playground
Change the settings and try the result.
Device captures shown in English.


API reference
Inputs
| Name | Type | Default | Binding | Description |
|---|---|---|---|---|
| label | string | Required | Input | Human-readable name for the control, action or group. |
| options | readonly NeuOption[] | [] | Input | Available choices. Selected values refer to option IDs, not their displayed labels. |
| multiple | boolean | false | Input | Allows multiple choices or files where supported; check the declared model type. |
| disabled | boolean | false | Input | Disables user interaction. Values can still be supplied by the application. |
| tone | NeuTone | 'brand' | Input | Semantic color: neutral, brand, success, info, warning or danger. The accent value remains a compatible alias for brand. Colors use NeuTheme tokens; explain statuses with words as well as color. |
Models
| Name | Type | Default | Binding | Description |
|---|---|---|---|---|
| value | readonly string[] | [] | Model · two-way | Current edited value or selected ID(s), using the declared type. Bind a writable signal with [(value)]. |
Outputs
| Name | Payload | When it emits |
|---|---|---|
| valueChange | readonly string[] | Emits the updated value value. [(value)] binds this output together with its model input. |
| touch | void | Reports user interaction to the surrounding form or application. |
Model state
Bind the signal with [(modelName)] without calling it. Use modelName() to read its value.
import { signal } from '@angular/core';
// Fields inside your component class
readonly value = signal<readonly string[]>([]);Types and data interfaces
Use the imports in your application. The definitions below are provided for reference.
NeuOption
import type { NeuOption } from '@neural-ui/native';
// Public definition for reference only. Import this type; do not redeclare it.
export interface NeuOption {
readonly id: string;
readonly label: string;
readonly description?: string;
readonly disabled?: boolean;
}| Field | Type | Requirement | Meaning |
|---|---|---|---|
| id | string | Required | Stable, unique identifier used for tracking and selection. |
| label | string | Required | Human-readable item name. |
| description | string | Optional | Optional supporting text; rendering depends on the control. |
| disabled | boolean | Optional | Prevents activating or selecting this item. |
NeuTone
import type { NeuTone } from '@neural-ui/native/foundation';
// Public definition for reference only. Import this type; do not redeclare it.
export type NeuTone = 'neutral' | 'brand' | 'accent' | 'success' | 'info' | 'warning' | 'danger';