Component · Top App Bar

Top App Bar

El chrome superior de toda pantalla en MiCapi. 56dp de alto, edge-to-edge sobre el status bar del sistema. Cambia su contenido según el contexto: marca en home, título + back en pantallas interiores, título + close en flujos modales. Material 3 AppBar como referencia, ajustado al sistema cromático del DS.

Material 3 AppBar 56dp height edge-to-edge sobre status bar elevation on-scroll
Anatomy

Estructura

Tres slots horizontales: leading (48dp), title (expandido, alineado a la izquierda) y trailing (1–3 acciones de 48dp). Status bar del sistema vive arriba.

9:41
Detalle Bitcoin
contenido scrolleable
1

Status bar del sistema

Hora · señal · WiFi · batería. Vive sobre el app bar, no es parte del componente. Edge-to-edge — el fondo del app bar se extiende debajo del status bar.

2

Leading · 48dp

Back arrow (Android arrow-left, no iOS chevron-left) · close · menú · o vacío en home. Touch target 48dp con InkResponse circular.

3

Title · alineado a la izquierda

Convención Material 3 — el título no se centra. Body-large / title-medium, peso 600. En home, este slot lo ocupa el wordmark "MiCapi".

4

Trailing · 1–3 acciones

Cada ícono ocupa 48dp × 48dp para garantizar touch target. Más de 2 acciones → menú overflow (more-vertical). En MiCapi rara vez más de 2.

5

Altura 56dp · padding 4dp

Material 3 standard. Padding horizontal 4dp — los íconos ya incluyen su propio padding interno para llegar al touch target.

6

Fondo · superficie sólida

--surface en light · --surface-dark en dark. No translúcido, no blur — el contenido detrás no se debe leer. Border-bottom 1dp aparece al scrollear.

Variants

Cuatro variantes

Misma estructura, distinto contenido. La variante depende de dónde en la jerarquía vive la pantalla y de qué tipo de salida ofrece (atrás vs. cerrar).

aHome · con marca
9:41
Sin back — es la raíz. Title slot lo ocupa el wordmark. Trailing: campana de notificaciones con badge dot si hay no leídas.
USO · pestaña Inicio del bottom nav
bInterior · título + back
9:41
Bitcoin
La más frecuente. Leading arrow-left (no chevron-left iOS). Title = nombre de la pantalla. Trailing contextual.
USO · detalle de activo · historial · todas las pantallas interiores con back
cInterior · título + close
9:41
Verificar identidad
Leading es close (x), no back. Indica que el usuario está en un flujo modal — KYC, registrar wallet, agregar cuenta — que puede abandonar, no navegar atrás.
USO · KYC · agregar wallet · agregar cuenta bancaria · flujos que se cierran enteros
dCompacta · solo back
9:41
Sin título — el contenido tiene su propio hero heading grande debajo (ej. monto de la transacción). Evita duplicar título.
USO · detalle de transacción · pantallas con hero amount propio
Trailing actions

Acciones por pantalla

Tabla de referencia. Máximo 2 acciones visibles — más, se agrupan en menú overflow.

Pantalla
Descripción
Trailing
Home · Inicio
Acceso a notificaciones del usuario (saldo recibido, KYC completado, alertas de SAGRILAFT).
Mercado
Búsqueda futura. En MVP con 3 activos no hay búsqueda — trailing vacío.
— ninguna —
Historial
Filtros (por activo, tipo, fecha) + descargar comprobantes en PDF/CSV.
Detalle de activo
Favorito (futuro: lista de favoritos). Compartir si se decide en roadmap.
Detalle de transacción
Copiar referencia interna al portapapeles (haptic lightImpact).
Perfil
El perfil es vista raíz. Sin acciones contextuales — todo vive en filas internas.
— ninguna —
Regla. Máximo 2 íconos en trailing. Si una pantalla necesita más, agrupar en more-vertical que abre un menú. En el MVP de MiCapi es improbable — la app es sobria, las acciones contextuales son pocas.
Scroll behavior

Dos comportamientos al scroll

Default pinned — el app bar siempre visible, gana elevación sutil al scrollear. La variante scroll-off es solo para pantallas de lista larga (historial) donde el espacio vertical importa.

DEFAULT

Pinned · permanente

Permanece visible al scrollear. Al desplazarse el contenido bajo el bar, aparece border-bottom 1dp + shadow sutil elev.2 para separar visualmente.

01 · top
Bitcoin
Bar plano · sin border
02 · scrolling
Bitcoin
SCROLL
Bar visible · border bottom aparece
SCROLL-OFF

Colapsable · al scrollear hacia abajo

El bar se oculta cuando el usuario scrollea hacia abajo, reaparece al scrollear hacia arriba. Solo para listas largas (Historial) donde cada dp vertical cuenta. Usa SliverAppBar(floating: true, snap: true).

01 · top
Historial
Bar visible
02 · scroll ↓
SCROLL
Bar oculto · slide up out
03 · scroll ↑
Historial
SCROLL
Reaparece con snap
System status bar

Integración edge-to-edge

El fondo del app bar se extiende hasta el borde superior real, detrás del status bar del sistema. Los íconos y title del app bar viven en una zona más baja, dentro de la safe area.

9:41
SISTEMA
Bitcoin
APP BAR · 56DP

Regla de capas

El app bar y el status bar comparten la misma superficie cromática, pero el status bar es del sistema operativo, no del componente. La continuidad visual es deliberada.

  • Status bar (sistema) — hora, batería, señal. Texto e íconos los pinta Android.
  • App bar (MiCapi) — leading, title, actions. 56dp debajo del status bar.
  • El fondo del app bar se pinta detrás del status bar — sin escalón visual.

Flutter — SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge) en main(). SystemUiOverlayStyle define iconos del status bar oscuros en light mode, claros en dark mode.

Interactive states

Estados del back button

El leading icon es el control más tappeado del app bar. Estados explícitos.

DEFAULT

Reposo

Ícono color fg. Touch target 48dp.

PRESSED

Tap / ripple

Ripple circular Material (InkResponse). Sin haptic — navegación atrás no requiere feedback táctil.

DISABLED

N/A

No existe estado disabled. Si no hay atrás (pantalla raíz), el ícono no se renderiza — slot vacío.

Dark mode

Claro y oscuro

Misma estructura. Cambian fondo, color de texto/íconos, color del wordmark (primary-300 en lugar de primary-700 para contraste).

LightDEFAULT
Home
9:41
Interior
9:41
Historial
DarkDARK MODE
Home
9:41
Interior
9:41
Historial
In context

Home + Interior

Dos pantallas reales: dashboard de Inicio (home variant + bottom nav) y detalle de BTC (interior variant, sin bottom nav).

HOME · variante a
9:41
Valor estimado en COP
$2.845.320
+2,3% · 24h
₿
Bitcoin
BTC
0,01548 BTC
≈ $1.878.640
Ethereum
ETH
0,2156 ETH
≈ $786.180
Tether
USDT
45,0000 USDT
≈ $180.500
Inicio
Mercado
Historial
Perfil
INTERIOR · variante b
9:41
Bitcoin
BTC · COP
$458.320.000
+2,4% · 24h
Comprar BTC
Vender
Volumen 24h
$45,2M
Cap. mercado
$2,41T
Máximo 24h
$123,4k
Mínimo 24h
$118,1k

Observaciones

1

Home muestra el wordmark, no un título genérico tipo "Inicio". La marca es el ancla cuando el usuario está en la raíz.

2

Interior usa back arrow + nombre del activo. Trailing: star para favorito (roadmap futuro).

3

Bottom nav presente en Home, oculto en detalle de BTC. Patrón consistente con components-bottom-nav.

4

Status bar continuo. La hora y los íconos del sistema viven sobre el mismo fondo que el app bar — sin escalón cromático.

5

Gesture nav en la base se ve translúcido sobre el bottom nav (home) o sobre el contenido (interior).

Implementation

Notas de implementación Flutter

Construcción del app bar

Widget canónico

Usar AppBar (Material 3) con leading, title, actions. Para scroll-off: SliverAppBar(floating: true, snap: true) dentro de CustomScrollView.

Wordmark en home

title: SvgPicture.asset('assets/brand/wordmark.svg', height: 24). Centrar a la izquierda con centerTitle: false (Material 3 default).

Scroll elevation

Material 3 lo hace automático con AppBar.scrolledUnderElevation y surfaceTintColor. En MiCapi preferimos border-bottom 1dp por sobriedad — override con un NotificationListener<ScrollNotification>.

Edge-to-edge

SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge) en main(). AppBar nativo respeta MediaQuery.padding.top — no envolver en SafeArea.

Status bar style

SystemUiOverlayStyle.dark en light mode (íconos oscuros), SystemUiOverlayStyle.light en dark mode (íconos claros). Set via AppBar.systemOverlayStyle.

Back button

leading: BackButton() o IconButton(icon: Icon(Icons.arrow_back), onPressed: () => context.pop()). Sin haptic — navegación atrás no requiere.

// Interior screen — variante b
AppBar(
  leading: IconButton(
    icon: const Icon(LucideIcons.arrowLeft),
    onPressed: () => context.pop(),
  ),
  title: const Text('Bitcoin'),
  centerTitle: false,
  scrolledUnderElevation: 0,                 // preferimos border-bottom propio
  shape: Border(
    bottom: BorderSide(
      color: scrolled ? colors.outlineVariant : Colors.transparent,
      width: 1,
    ),
  ),
  actions: [
    IconButton(
      icon: const Icon(LucideIcons.star),
      onPressed: _toggleFavorite,
    ),
  ],
  systemOverlayStyle: theme.brightness == Brightness.dark
    ? SystemUiOverlayStyle.light
    : SystemUiOverlayStyle.dark,
)