Escritorio
Armazón de la aplicación: cabecera (banner), navegación lateral (navigation con nombre), contenido (main) y pie (contentinfo), con un enlace para saltar al contenido. La navegación son datos: el consumidor marca la página actual (current, que se pinta como aria-current="page") y responde a navigate con el evento nativo, para usar su router sin que FLT dependa de ninguno. Los grupos son botones de divulgación (aria-expanded), no menús, y se abren solos si contienen la página actual. Aquí el marco mide 64rem, el ancho a partir del cual la navegación va en línea; desplázalo en horizontal si no cabe. Por ser una demo, su main queda dentro del main del escaparate.
<flt-app-shell>
<flt-app-header>
<span fltAppHeaderBrand>FLT Banca</span>
<flt-button fltAppHeaderActions variant="ghost" size="sm">Salir</flt-button>
</flt-app-header>
<flt-side-nav [items]="items()" (navigate)="onNavigate($event)" />
<h1>{{ title() }}</h1>
<flt-app-footer>© 2026 FLT Banca · <a href="/aviso-legal">Aviso legal</a></flt-app-footer>
</flt-app-shell>
// items: [{ id, label, href, current? }, { id, label, children: [{ id, label, href, current? }] }]
onNavigate({ item, event }: FltNavigateEvent) {
event.preventDefault();
this.router.navigateByUrl(item.href);
} <FltAppShell>
<template #header>
<FltAppHeader>
<template #brand>FLT Banca</template>
<template #actions><FltButton variant="ghost" size="sm">Salir</FltButton></template>
</FltAppHeader>
</template>
<template #nav><FltSideNav :items="items" @navigate="onNavigate" /></template>
<h1>{{ title }}</h1>
<template #footer>
<FltAppFooter>© 2026 FLT Banca · <a href="/aviso-legal">Aviso legal</a></FltAppFooter>
</template>
</FltAppShell>
function onNavigate({ item, event }: FltNavigateEvent) {
event.preventDefault();
router.push(item.href);
}