Navegación
Nav
Permite seleccionar secciones desde una barra de navegación compacta.
Angular NativeiOS / Android0.1.0-beta.1
Importación
component.ts
import { NeuNavComponent } from '@neural-ui/native/nav';Ejemplos
Importa ExampleComponent en su padre y coloca <app-example /> dentro del neu-theme raíz de tu aplicación. El preview aporta el marco y las zonas seguras; utiliza la estructura raíz de Instalación en tu app.
Básico
Explora el resumen, el progreso de los proyectos y las preferencias de la cuenta. La barra inferior permanece en su sitio; las pantallas y las rutas pertenecen a tu aplicación.
Ver y copiar el ejemplo completo
basic.component.ts
import { Component, signal } from '@angular/core';
import { NeuButtonComponent } from '@neural-ui/native/button';
import { NeuSwitchComponent } from '@neural-ui/native/switch';
import { NeuCardComponent } from '@neural-ui/native/card';
import { NeuBadgeComponent } from '@neural-ui/native/badge';
import { NeuAvatarComponent } from '@neural-ui/native/avatar';
import { NeuNavComponent } from '@neural-ui/native/nav';
import { NeuProgressBarComponent } from '@neural-ui/native/progress-bar';
import { View, Text, ScrollView } from '@ng-native/components';
import type { NeuNavItem } from '@neural-ui/native/nav';
@Component({
selector: 'app-example',
imports: [NeuButtonComponent, NeuSwitchComponent, NeuCardComponent, NeuBadgeComponent, NeuAvatarComponent, NeuNavComponent, NeuProgressBarComponent, View, Text, ScrollView],
template: `
<view class="workspace-screen">
@switch (destination()) {
@case ('home') {
<scroll-view class="workspace-scroll" keyboardShouldPersistTaps="handled"><view class="workspace-body">
<view class="screen-heading">
<view class="heading-copy">
<text class="eyebrow">NEURAL STUDIO</text>
<text class="screen-title" accessibilityRole="header">Hola, Alex</text>
<text class="muted">Hoy creamos algo especial.</text>
</view>
<neu-avatar label="Alex Morgan" size="md" />
</view>
<view class="summary-row">
<view class="summary-tile"><text class="summary-number">03</text><text class="summary-label">Proyectos</text></view>
<view class="summary-tile"><text class="summary-number">12</text><text class="summary-label">Tareas esta semana</text></view>
</view>
<text class="section-title">Tu prioridad de hoy</text>
<neu-card title="Lanzamiento móvil" description="Próximo hito · Viernes" variant="outlined">
<neu-badge label="En curso" tone="brand" />
<text class="body-copy">Una bienvenida más sencilla para cada persona.</text>
<neu-progress-bar label="Listo para el lanzamiento" [value]="72" />
<neu-button label="Ver proyectos" size="sm" variant="text" (pressed)="destination.set('projects')" />
</neu-card>
<text class="section-title">Lo próximo</text>
<view class="agenda-row">
<view class="agenda-time"><text class="time-value">10:30</text><text class="small-copy">HOY</text></view>
<view class="agenda-copy"><text class="row-title">Revisión de diseño</text><text class="muted">Con el equipo de producto</text></view>
<neu-avatar label="Ada Lovelace" size="sm" tone="neutral" />
</view>
</view></scroll-view>
}
@case ('projects') {
<scroll-view class="workspace-scroll" keyboardShouldPersistTaps="handled"><view class="workspace-body">
<view class="heading-copy">
<text class="eyebrow">TU ESPACIO</text>
<text class="screen-title" accessibilityRole="header">Proyectos</text>
<text class="muted">Un poco de progreso, cada día.</text>
</view>
@for (project of projects; track project.id) {
<neu-card [title]="project.title" [description]="project.team" variant="outlined">
<neu-badge [label]="project.status" [tone]="project.tone" />
<neu-progress-bar label="Progreso" [value]="project.progress" [tone]="project.tone" />
</neu-card>
}
</view></scroll-view>
}
@case ('account') {
<scroll-view class="workspace-scroll" keyboardShouldPersistTaps="handled"><view class="workspace-body">
<view class="heading-copy">
<text class="eyebrow">A TU MEDIDA</text>
<text class="screen-title" accessibilityRole="header">Cuenta</text>
</view>
<view class="profile-panel">
<neu-avatar label="Alex Morgan" size="lg" />
<view class="profile-copy"><text class="profile-name">Alex Morgan</text><text class="muted">Diseñadora de producto</text></view>
<neu-badge label="Miembro del estudio" tone="brand" />
</view>
<text class="section-title">Espacio de trabajo</text>
<view class="settings-panel">
<view class="settings-row"><text class="muted">Equipo</text><text class="setting-value">Neural Studio</text></view>
<view class="settings-row"><text class="muted">Rol</text><text class="setting-value">Diseñador</text></view>
</view>
<text class="section-title">Preferencias</text>
<view class="settings-panel">
<neu-switch label="Avisos por correo" hint="Novedades de tus proyectos" labelPosition="left" [(checked)]="updates" />
<text class="small-copy" accessibilityLiveRegion="polite">{{ updates() ? 'Avisos activados' : 'Avisos pausados' }}</text>
</view>
<neu-button label="Volver al resumen" size="sm" variant="outline" (pressed)="destination.set('home')" />
</view></scroll-view>
}
}
<neu-nav label="Navegación principal" [items]="destinations" [(value)]="destination" />
</view>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
:host { flex: 1; flex-shrink: 1; min-height: 0; }
.workspace-screen { flex: 1; flex-shrink: 1; min-height: 0; background-color: var(--neu-canvas, #f4f5f7); }
.workspace-scroll { flex: 1; flex-shrink: 1; height: 0px; min-height: 0; }
.workspace-body { padding: 24px 20px; gap: 18px; }
.screen-heading { flex-direction: row; align-items: center; gap: 12px; }
.heading-copy { flex: 1; min-width: 0; gap: 5px; }
.eyebrow { font-size: 11px; line-height: 16px; font-weight: 600; letter-spacing: 1.2px; color: var(--neu-muted, #596477); }
.screen-title { font-size: 26px; line-height: 33px; font-weight: 700; color: var(--neu-text, #172033); }
.muted { font-size: 14px; line-height: 20px; color: var(--neu-muted, #596477); }
.summary-row { flex-direction: row; gap: 12px; }
.summary-tile { flex: 1; min-width: 0; padding: 16px; gap: 4px; border-radius: 16px; background-color: var(--neu-surface, #ffffff); }
.summary-number { font-size: 28px; line-height: 34px; font-weight: 700; color: var(--neu-accent, #006ee6); }
.summary-label { font-size: 13px; line-height: 18px; color: var(--neu-muted, #596477); }
.section-title { font-size: 15px; line-height: 21px; font-weight: 600; color: var(--neu-text, #172033); }
.body-copy { font-size: 15px; line-height: 22px; color: var(--neu-text, #172033); }
.agenda-row { flex-direction: row; align-items: center; padding: 16px; gap: 12px; border-radius: 16px; background-color: var(--neu-surface, #ffffff); }
.agenda-time { gap: 3px; }
.time-value { font-size: 15px; line-height: 20px; font-weight: 600; color: var(--neu-accent, #006ee6); }
.agenda-copy { flex: 1; min-width: 0; gap: 3px; }
.row-title { font-size: 15px; line-height: 21px; font-weight: 600; color: var(--neu-text, #172033); }
.small-copy { font-size: 12px; line-height: 18px; color: var(--neu-muted, #596477); }
.profile-panel { align-items: center; gap: 12px; padding: 24px 16px; border-radius: 18px; background-color: var(--neu-surface, #ffffff); }
.profile-copy { align-items: center; gap: 4px; }
.profile-name { font-size: 21px; line-height: 28px; font-weight: 600; color: var(--neu-text, #172033); }
.settings-panel { padding: 16px; gap: 16px; border-radius: 16px; background-color: var(--neu-surface, #ffffff); }
.settings-row { flex-direction: row; align-items: center; justify-content: space-between; gap: 12px; }
.setting-value { flex-shrink: 1; font-size: 14px; line-height: 20px; font-weight: 500; color: var(--neu-text, #172033); }
neu-nav { flex-shrink: 0; }
`,
})
export class ExampleComponent {
readonly destination = signal('home');
readonly updates = signal(true);
readonly destinations: readonly NeuNavItem[] = [
{ id: 'home', label: 'Inicio', svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m3 10 9-7 9 7v11H3Z"/><path d="M9 21v-8h6v8"/></svg>' },
{ id: 'projects', label: 'Proyectos', svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v10H3Z"/></svg>' },
{ id: 'account', label: 'Cuenta', svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"><circle cx="12" cy="8" r="4"/><path d="M4 21v-2a8 8 0 0 1 16 0v2"/></svg>' },
];
readonly projects = [
{ id: 'mobile', title: 'Lanzamiento móvil', team: 'Equipo de producto', status: 'En curso', tone: 'brand', progress: 72 },
{ id: 'website', title: 'Renovación de la web', team: 'Equipo de plataforma', status: 'En revisión', tone: 'warning', progress: 90 },
{ id: 'research', title: 'Investigación con clientes', team: 'Equipo de clientes', status: 'Completado', tone: 'success', progress: 100 },
] as const;
}Playground interactivo
Ajusta la configuración y prueba el resultado.
Capturas del dispositivo en inglés.


Referencia API
Inputs
| Nombre | Tipo | Predeterminado | Enlace | Descripción |
|---|---|---|---|---|
| label | string | 'Navigation' | Input | Nombre legible del control, acción o grupo. |
| items | readonly NeuNavItem[] | [] | Input | Datos ordenados del componente. Utiliza el contrato siguiente e identificadores estables y únicos. |
| disabled | boolean | false | Input | Desactiva la interacción del usuario. La aplicación puede seguir proporcionando valores. |
Models
| Nombre | Tipo | Predeterminado | Enlace | Descripción |
|---|---|---|---|---|
| value | string | '' | Model · bidireccional | Valor editado o ID(s) seleccionado(s), según el tipo declarado. Enlaza una signal escribible mediante [(value)]. |
Outputs
| Nombre | Payload | Cuándo se emite |
|---|---|---|
| valueChange | string | Emite el valor actualizado de value. [(value)] enlaza este output junto con su input model. |
| navigate | string | Comunica un destino de navegación solicitado; las rutas pertenecen a la aplicación. |
Estado de los models
Enlaza la signal con [(nombreModel)] sin llamarla. Utiliza nombreModel() para leer su valor.
model-fields.ts
import { signal } from '@angular/core';
// Fields inside your component class
readonly value = signal<string>('');Tipos e interfaces de datos
Utiliza los imports en tu aplicación. Las definiciones siguientes se muestran como referencia.
NeuNavItem
NeuNavItem.ts
import type { NeuNavItem } from '@neural-ui/native/nav';
import type { NeuOption } from '@neural-ui/native';
// Public definition for reference only. Import this type; do not redeclare it.
export interface NeuNavItem extends NeuOption {
readonly svg?: string;
}| Campo | Tipo | Requisito | Significado |
|---|---|---|---|
| svg | string | Opcional | SVG opcional del icono del elemento. Nav lo muestra encima de la etiqueta del destino; SpeedDial lo sitúa dentro del círculo y utiliza la inicial de la etiqueta si se omite. |
| id | string | Obligatorio | Identificador estable y único para seguimiento y selección. |
| label | string | Obligatorio | Nombre legible del elemento. |
| description | string | Opcional | Texto de apoyo opcional; su presentación depende del control. |
| disabled | boolean | Opcional | Impide activar o seleccionar este elemento. |
NeuOption
NeuOption.ts
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;
}| Campo | Tipo | Requisito | Significado |
|---|---|---|---|
| id | string | Obligatorio | Identificador estable y único para seguimiento y selección. |
| label | string | Obligatorio | Nombre legible del elemento. |
| description | string | Opcional | Texto de apoyo opcional; su presentación depende del control. |
| disabled | boolean | Opcional | Impide activar o seleccionar este elemento. |