Actions
Toolbar
Organize the actions and controls that belong to a screen.
Import
import { NeuToolbarComponent } from '@neural-ui/native/toolbar';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.
Basic
A screen toolbar keeps its title on the left and its actions on the right. Search filters the files; the plus creates a local draft.
View and copy the complete example
import { Component, signal, computed } from '@angular/core';
import { NeuInputComponent } from '@neural-ui/native/input';
import { NeuToolbarComponent } from '@neural-ui/native/toolbar';
import { View, Text, ScrollView } from '@ng-native/components';
import type { NeuToolbarAction } from '@neural-ui/native/toolbar';
@Component({
selector: 'app-example',
imports: [NeuInputComponent, NeuToolbarComponent, View, Text, ScrollView],
template: `
<view class="documents-screen">
<neu-toolbar label="Document actions" [actions]="actions" (activated)="onActivated($event)">
<text class="toolbar-title" [numberOfLines]="1" ellipsizeMode="tail">Documents</text>
</neu-toolbar>
<scroll-view class="documents-scroll" keyboardShouldPersistTaps="handled"><view class="documents-body">
@if (searching()) {
<neu-input label="Search documents" placeholder="Name or file type" [(value)]="query" />
}
<view class="section-heading">
<text class="section-title">Recent files</text>
<text class="file-count">{{ visibleDocuments().length }}</text>
</view>
@for (document of visibleDocuments(); track document.id) {
<view class="document-row">
<view class="file-symbol"><text class="file-type">{{ document.type }}</text></view>
<view class="document-copy">
<text class="document-name" [numberOfLines]="1" ellipsizeMode="tail">{{ document.name }}</text>
<text class="document-meta">{{ document.detail }}</text>
</view>
</view>
} @empty {
<text class="empty-copy">No documents match your search.</text>
}
<text class="status-copy" accessibilityLiveRegion="polite">{{ status() }}</text>
</view></scroll-view>
</view>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
:host { flex: 1; min-height: 0; }
.documents-screen { flex: 1; background-color: var(--neu-surface, #ffffff); }
.documents-scroll { flex: 1; min-height: 0; }
.toolbar-title { flex-shrink: 1; color: var(--neu-text, #172033); font-size: 20px; line-height: 26px; font-weight: 600; }
.documents-body { padding: 20px 16px; gap: 8px; }
.section-heading { flex-direction: row; align-items: center; justify-content: space-between; margin-top: 8px; margin-bottom: 8px; }
.section-title { color: var(--neu-muted, #596477); font-size: 13px; line-height: 18px; font-weight: 500; }
.file-count { color: var(--neu-muted, #596477); font-size: 13px; line-height: 18px; }
.document-row { flex-direction: row; align-items: center; gap: 12px; min-height: 76px; padding: 12px 0; border-bottom-width: 1px; border-color: var(--neu-divider, #e4e7ec); }
.file-symbol { width: 44px; height: 48px; border-radius: 10px; background-color: var(--neu-tonal, #e9edfc); align-items: center; justify-content: center; }
.file-type { color: var(--neu-text, #172033); font-size: 11px; font-weight: 600; }
.document-copy { flex: 1; min-width: 0; gap: 4px; }
.document-name { color: var(--neu-text, #172033); font-size: 15px; line-height: 20px; font-weight: 500; }
.document-meta, .status-copy { color: var(--neu-muted, #596477); font-size: 13px; line-height: 18px; }
.status-copy { margin-top: 8px; }
.empty-copy { color: var(--neu-muted, #596477); font-size: 15px; line-height: 22px; padding: 24px 0; }
`,
})
export class ExampleComponent {
readonly searching = signal(false);
readonly query = signal('');
readonly status = signal('');
readonly documents = signal([
{ id: 'brief', name: 'Project brief', type: 'PDF', detail: 'Today · 240 KB' },
{ id: 'notes', name: 'Meeting notes', type: 'TXT', detail: 'Yesterday · 12 KB' },
{ id: 'guide', name: 'Brand guidelines', type: 'PDF', detail: 'Monday · 1.8 MB' },
]);
readonly visibleDocuments = computed(() => {
const query = this.query().trim().toLocaleLowerCase();
return this.documents().filter(document =>
(document.name + ' ' + document.type).toLocaleLowerCase().includes(query));
});
readonly actions: readonly NeuToolbarAction[] = [
{ id: 'search', label: 'Search files', svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"><circle cx="10.5" cy="10.5" r="6.5"/><path d="m16 16 4 4"/></svg>' },
{ id: 'new', label: 'New document', svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>' },
];
private nextDraft = 1;
onActivated(id: string): void {
if (id === 'search') {
this.searching.update(value => !value);
this.query.set('');
}
if (id === 'new') {
const number = this.nextDraft++;
this.query.set('');
this.documents.update(documents => [
{ id: 'draft-' + number, name: 'Untitled document ' + number, type: 'TXT', detail: 'Draft · Just now' },
...documents,
]);
this.status.set('Draft created on this screen.');
}
}
}Change the settings and try the result.
Device captures shown in English.


Personalization
Projected content
Leading content, aligned beside the actions. Project a concise native heading or another compact control. Each action accepts an optional svg; label is its accessible name and remains visible when svg is omitted. The toolbar’s disabled state does not disable your projected controls.
Use native elements from @ng-native/components and public Neural Native controls. Angular styles belong to the component that declares this content.
API reference
Inputs
| Name | Type | Default | Binding | Description |
|---|---|---|---|---|
| label | string | 'Toolbar' | Input | Accessible name announced for the toolbar. It does not render a visible title; project a text element between the toolbar tags for that. |
| actions | readonly NeuToolbarAction[] | [] | Input | Actions on the current screen: id, label, optional svg and disabled. With svg the action is a compact icon button; without it, label is visible. activated emits its id. |
| disabled | boolean | false | Input | Disables the action buttons declared in actions. Any projected interactive controls retain their own disabled state, which your application manages. |
Models
This component declares no two-way models.
Outputs
| Name | Payload | When it emits |
|---|---|---|
| activated | string | Emits the activated item ID. Your application performs the action. |
Types and data interfaces
Use the imports in your application. The definitions below are provided for reference.
NeuToolbarAction
import type { NeuToolbarAction } from '@neural-ui/native/toolbar';
import type { NeuOption } from '@neural-ui/native';
// Public definition for reference only. Import this type; do not redeclare it.
export interface NeuToolbarAction extends NeuOption {
readonly svg?: string;
}| Field | Type | Requirement | Meaning |
|---|---|---|---|
| svg | string | Optional | Optional SVG for the action icon. label remains its accessible name. Omit svg to show label as visible text. |
| 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. |
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. |