Saltar al contenido principal
@capgo/capacitor-native-navigation UI y Sistema Código abierto

Navegación Nativa plugin Capacitor

Renderiza navbars, tabbars y shells de transición nativos sobre una Capacitor WebView a pantalla completa

Instalar

bun add @capgo/capacitor-native-navigation bunx cap sync
npm, pnpm o yarn
  • npm install @capgo/capacitor-native-navigation
  • pnpm add @capgo/capacitor-native-navigation
  • yarn add @capgo/capacitor-native-navigation

Demo

Demos de Native Navigation

Cromo de navegación nativa, selección de pestañas, iconos SVG y opciones de estilo, renderizados como demos animadas en WebP.

Assets de origen
Demo del shell de navegación nativa animada: navbar nativa, pestañas y contenido WebView
Shell nativa
Flujo de navegación nativa animado: selección de pestaña, transición push y botón back nativo
Flujo de taps
Demo animada de iconos SVG nativos con iconos SVG en línea, tinte nativo, etiquetas y selección de pestañas
Iconos SVG
Demo de opciones de navegación nativa animada con colores dinámicos, etiquetas seleccionadas, insignias y transiciones de zoom
Opciones de estilo

Guía

Cómo usar Native Navigation en Capacitor

Probar en el dispositivo

Descarga la app Capgo y escanea el QR code.

QR de vista previa del plugin Native Navigation code

Uso de @capgo/capacitor-native-navigation

@capgo/capacitor-native-navigation renderiza la navegación superior nativa, la interfaz de pestañas inferiores y las transiciones de rutas sobre un único WebView Capacitor a pantalla completa. Tu framework web sigue siendo responsable de las rutas y el contenido, mientras que la capa nativa gestiona el marco de la app.

Instalar y sincronizar

npm install @capgo/capacitor-native-navigation
npx cap sync

Configura el frame nativo

import { NativeNavigation } from '@capgo/capacitor-native-navigation';

await NativeNavigation.configure({
  contentInsetMode: 'css',
  animationDuration: 360,
  colors: {
    tint: '#0f172a',
    inactiveTint: '#64748b',
  },
});

Renderiza una navbar nativa

await NativeNavigation.setNavbar({
  title: 'Inbox',
  subtitle: 'Native chrome',
  transparent: true,
  backButton: { visible: false },
  rightItems: [
    {
      id: 'compose',
      title: 'Compose',
      icon: {
        svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>',
      },
    },
  ],
});

Añade filas de segmentos multinivel debajo de la navbar

Pasa segments a setNavbar para apilar filas de segmentos nativos bajo la barra; por ejemplo, un selector de scope arriba y pestañas de sección debajo. Las filas se dibujan de arriba hacia abajo y cada una añade 44pt (iOS) o 48dp (Android) a la navbar y a los insets reportados. iOS usa UISegmentedControl y cápsulas de cristal; Android usa botones segmentados de Material y filter chips.

iOS Android
Grabación de iOS: al tocar secciones de Account, cambiar a Organization cambia la segunda fila a ocho chips con scroll, y seleccionar Billing Grabación de Android: fila segmentada Account / Organization sobre chips de sección con scroll, cambiando el scope y seleccionando Billing
const sections = {
  account: ['General', 'Notifications', 'Password', 'Two-factor'],
  organization: ['General', 'Members', 'Plans', 'Usage', 'Credits', 'Billing', 'Security', 'Webhooks'],
};
const selection = { scope: 'account', section: 'general' };

const renderNavbar = () =>
  NativeNavigation.setNavbar({
    title: 'Settings',
    segments: [
      {
        id: 'scope',
        selectedId: selection.scope,
        items: [
          { id: 'account', title: 'Account' },
          { id: 'organization', title: 'Organization' },
        ],
      },
      {
        id: 'section',
        style: 'scroll', // scrolling chips; `auto` uses `segmented` for up to 4 items
        selectedId: selection.section,
        items: sections[selection.scope].map((title) => ({ id: title.toLowerCase(), title })),
      },
    ],
  });

await NativeNavigation.addListener('navbarSegmentSelect', async ({ groupId, id }) => {
  if (groupId === 'scope') {
    selection.scope = id;
    selection.section = 'general'; // the second level depends on the first one
  } else {
    selection.section = id;
  }
  await renderNavbar();
});

await renderNavbar();

La selección se mueve de forma nativa al tocar, pero cada setNavbar llamada aplica selectedId de nuevo. Mantén los ids seleccionados en tu estado y pásalos en cada setNavbar llamada posterior; para rechazar una selección, envía el anterior selectedId. Los items también aceptan icon, accessibilityLabel, y enabled. Pass segments: [] para eliminar las filas. Disponible desde la versión 8.13.0.

Renderiza una tabbar nativa

await NativeNavigation.setTabbar({
  selectedId: 'inbox',
  labelVisibilityMode: 'selected',
  icons: true,
  colors: {
    dynamic: true,
    tint: '#0f172a',
    inactiveTint: '#64748b',
  },
  tabs: [
    {
      id: 'inbox',
      title: 'Inbox',
      icon: {
        svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16v16H4z"/><path d="m4 13 4 4h8l4-4"/></svg>',
      },
    },
    {
      id: 'search',
      title: 'Search',
      icon: {
        svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m20 20-3-3"/></svg>',
      },
    },
  ],
});

Conecta los eventos nativos con tu router

Las barras nativas emiten una intent. Tu router sigue ejecutando el cambio de ruta:

await NativeNavigation.addListener('navbarBack', () => {
  router.back();
});

await NativeNavigation.addListener('navbarItemTap', ({ id }) => {
  if (id === 'compose') router.push('/compose');
});

await NativeNavigation.addListener('tabSelect', ({ id }) => {
  router.push(`/${id}`);
});

Anima los cambios de ruta

Usa una transacción de transición alrededor de tu actualización normal de ruta web:

const transition = await NativeNavigation.beginTransition({
  direction: 'forward',
});

router.push('/message/42');
await router.ready?.();

await NativeNavigation.setNavbar({
  title: 'Message',
  backButton: { visible: true, title: 'Inbox' },
});

await NativeNavigation.finishTransition({
  id: transition.id,
  direction: 'forward',
});

Añade una transición de zoom

Usa los helpers de zoom para rutas que se abren desde una tarjeta, un elemento de cuadrícula o una vista previa de medios.

import { beginZoomTransition, finishZoomTransition } from '@capgo/capacitor-native-navigation';

const card = document.querySelector('[data-message-card]');
if (card) {
  const transition = await beginZoomTransition(card, { cornerRadius: 18 });

  router.push('/message/42');
  await router.ready?.();

  await NativeNavigation.setNavbar({
    title: 'Message',
    backButton: { visible: true, title: 'Inbox' },
  });

  await finishZoomTransition(undefined, {
    id: transition.id,
    cornerRadius: 18,
  });
}

Aplica padding al contenido con insets nativos

Cuando contentInsetMode es css, el plugin escribe variables CSS para las barras nativas:

.page {
  padding-top: var(--cap-native-navigation-top);
  padding-bottom: var(--cap-native-navigation-bottom);
}

Opciones de iconos

Los iconos son descriptores nativos, no nodos de React o Vue. Usa SVG si no quieres incluir assets nativos en el bundle:

const icon = {
  svg: '<svg viewBox="0 0 24 24"><path d="M3 10.5 12 3l9 7.5"/></svg>',
  template: true,
  ios: { sfSymbol: 'house.fill' },
  android: { resource: 'ic_menu_view' },
};

El SVG inline soporta path, line, polyline, polygon, circle, y rect, que cubre conjuntos de iconos comunes como Lucide y Feather.

Combínalo con @capgo/capacitor-transitions

Usa Native Navigation para la navbar nativa, el tabbar, los insets de safe-area y los eventos de intent nativos. Usa @capgo/capacitor-transitions para la pila de páginas del WebView debajo de ese chrome nativo.

npm install @capgo/capacitor-native-navigation @capgo/capacitor-transitions
npx cap sync

Inicializa ambos paquetes una vez:

import { NativeNavigation } from '@capgo/capacitor-native-navigation';
import '@capgo/capacitor-transitions';
import { initTransitions, setupRouterOutlet, setDirection } from '@capgo/capacitor-transitions/react';

initTransitions({ platform: 'auto' });

const outlet = document.querySelector('cap-router-outlet');
if (outlet) {
  setupRouterOutlet(outlet, { platform: 'auto', swipeGesture: 'auto' });
}

await NativeNavigation.configure({
  contentInsetMode: 'css',
});

Mantén el outlet de transición enfocado en las páginas, no en barras web duplicadas:

<cap-router-outlet platform="auto" swipe-gesture="auto">
  <cap-page>
    <cap-content slot="content" fullscreen>
      <main class="page">Inbox content</main>
    </cap-content>
  </cap-page>
</cap-router-outlet>

Controla ambos paquetes desde las mismas acciones del router:

async function openMessage(id: string) {
  setDirection('forward');
  await router.push(`/messages/${id}`);
  await NativeNavigation.setNavbar({
    title: 'Message',
    backButton: { visible: true, title: 'Inbox' },
  });
}

await NativeNavigation.addListener('navbarBack', () => {
  setDirection('back');
  router.back();
});

await NativeNavigation.addListener('tabSelect', ({ id }) => {
  setDirection('root');
  router.push(`/${id}`);
});

Elige una capa de animación por cambio de ruta. Deja @capgo/capacitor-transitions anima las inserciones normales de páginas y usa los helpers de zoom de Native Navigation solo para rutas de elemento compartido o zoom.

Referencia completa

Continúa desde Uso de @capgo/capacitor-native-navigation

Si estás usando Uso de @capgo/capacitor-native-navigation para planificar el comportamiento de los medios nativos y la interfaz, conéctalo con @capgo/capacitor-native-navigation para el detalle de implementación en @capgo/capacitor-native-navigation, Primeros pasos para los detalles de implementación en Primeros pasos, Uso de @capgo/capacitor-live-activities para la capacidad nativa en Uso de @capgo/capacitor-live-activities, @capgo/capacitor-live-activities para el detalle de implementación en @capgo/capacitor-live-activities, y Uso de @capgo/capacitor-video-player para la capacidad nativa en Uso de @capgo/capacitor-video-player.

FAQ

Preguntas frecuentes del plugin Native Navigation

¿Cómo instalo el plugin Native Navigation en una app de Capacitor?

Ejecuta &quot;bun add @capgo/capacitor-native-navigation&quot; (o &quot;npm install @capgo/capacitor-native-navigation&quot;) y luego ejecuta &quot;bunx cap sync&quot; para que los proyectos de iOS y Android incorporen el código nativo code. Impórtalo desde &quot;@capgo/capacitor-native-navigation&quot; en el code de tu app.

¿Funciona @capgo/capacitor-native-navigation con React, Vue y Angular?

Sí. Native Navigation es un paquete de Capacitor, por lo que funciona con cualquier framework web que se ejecute dentro de Capacitor, incluyendo Ionic, React, Vue, Angular, Svelte y JavaScript puro.

¿Qué versión de Capacitor soporta @capgo/capacitor-native-navigation?

Los plugins de Capgo siguen la versión mayor de Capacitor: usa la versión mayor del plugin que coincida con la versión mayor de tu Capacitor (por ejemplo, el plugin v8 con Capacitor 8). La tabla de compatibilidad del README de GitHub lista las versiones mantenidas.

¿Es @capgo/capacitor-native-navigation gratuito y de código abierto?

Sí. El code está publicado en GitHub en https://github.com/Cap-go/capacitor-native-navigation/ y el paquete se puede instalar gratis desde npm. Se aceptan informes de errores y pull requests.

¿Puedo actualizar code que usa Native Navigation sin una revisión de la App Store?

Instalar o actualizar el plugin cambia el code nativo, así que requiere un nuevo build para la tienda. Después, los cambios de JavaScript, HTML y CSS que llamen al plugin se pueden publicar al instante con las live updates de Capgo.

Publica cambios de Native Navigation sin esperar la revisión de la app

Una vez que el plugin esté en tu store build, Capgo live updates envía tus cambios de JavaScript, HTML y CSS a los usuarios en minutos.

Empieza con Capgo