Skip to content

Plan: Sistema de Diseño UI — Sidebar liviano, Dark Mode, Paleta Semántica

Date: 2026-07-25 Status: Aplicado sobre M1/M2 real (ver checklist al final) Autores: Product Owner + ui-engineer (debate de diseño con el cliente, research de tendencias fintech 2026) + Claude Code (implementación real, 2026-07-25)

Contexto

Este plan documenta un debate de diseño completo hecho en paralelo mientras Claude Code desarrollaba los módulos funcionales. Cada decisión de abajo fue validada visualmente antes de implementarse — se corrió el frontend real (Vue + Vite + Naive UI) en un entorno aparte, se tomaron capturas de cada cambio, y el cliente aprobó antes de que esto llegue acá.

Importante para Claude Code: los archivos de referencia adjuntos (reference/) son código Vue real, corrido y validado — no pseudocódigo. Son el punto de partida, no una sugerencia aproximada. Si el estado actual del repo difiere (por trabajo ya hecho en paralelo), adaptar respetando las decisiones de esta sección, no las capturas de pantalla previas al 2026-07-25.

Decisiones tomadas

1. El naranja de marca NO es el mismo color que las alertas

Se detectó que el naranja de marca (#F5821F) es visualmente casi idéntico a un color de warning, lo cual generaba ambigüedad entre "acción disponible" y "algo está mal". Se separó en dos paletas:

Marca (acciones, navegación activa):
  --color-cis-orange:       #F5821F
  --color-cis-orange-deep:  #D9690A

Semántica (estados y alertas — NUNCA usar el naranja de marca acá):
  --color-status-info:      #5B7FA6   /* ACCEPTED */
  --color-status-success:   #2F9E5B   /* PAID */
  --color-status-cancelled: #8A93A3   /* CANCELLED */
  --color-alert-warning:    #C9922B   /* saldo insuficiente, etc. */
  --color-alert-danger:     #C0392B   /* error de sync, fallo de cron */

Tarea para Claude Code: aplicar --color-status-* a los badges de estado de transacción (ACCEPTED/CANCELLED/PAID) en TransaccionesView cuando se conecte al backend real — hoy esos badges todavía no existen porque la tabla está vacía (placeholder).

2. Dark mode real (no un invertido automático)

Confirmado por research (fintech 2026: Mercury, Stripe) que dark mode es señal de sofisticación premium, no solo estética — reduce fatiga visual en jornadas largas de Backoffice/Supervisor.

  • Superficies escalonadas, no negro puro: --color-dark-bg: #0A1826--color-dark-surface: #0F2338--color-dark-surface-2: #16304A.
  • Toggle persistente en localStorage (cis-theme), ver reference/useDarkMode.ts.
  • Tailwind v4: variant por clase, no solo prefers-color-scheme — requiere @custom-variant dark (&:where(.dark, .dark *)); en style.css (ya incluido en la referencia).
  • Colores semánticos tienen variante -dark con más brillo para mantener contraste AA sobre navy oscuro (ver --color-status-success-dark, etc. en reference/style.css).

3. Sidebar liviano y colapsable (reemplaza el navy sólido)

El cliente pidió explícitamente sacar el bloque navy sólido del sidebar — pesaba visualmente. Se evaluaron 2 alternativas (ambas con el mismo mecanismo de colapso), el cliente eligió la Alternativa A:

  • Fondo blanco (no navy), texto navy, ítem activo = borde izquierdo naranja + tinte suave (bg-cis-orange/10), no relleno sólido.
  • Colapsable a 68px (solo íconos, con title nativo como tooltip), botón dedicado abajo del sidebar. Estado persistido en localStorage (cis-sidebar-collapsed).
  • Alternativa B (gris cálido #FAFAF8 en vez de blanco puro) quedó descartada pero documentada por si se quiere reconsiderar — ver capturas en el historial de la conversación de diseño.

Tarea para Claude Code: los íconos del sidebar en la referencia son trazos SVG dibujados a mano para la validación visual — reemplazar por un set real de íconos (Tabler o Lucide, mismos criterios que usa el resto de la metodología) antes de dar esto por terminado. Confirmar también si 68px de ancho colapsado sigue alcanzando si se agregan más módulos de Admin a futuro.

4. Ilustraciones contextuales (reemplazan texto, no decoran)

Research 2026 confirmó que las ilustraciones funcionan mejor sustituyendo texto explicativo, no como decoración adicional:

  • Login: ilustración de "mapa de conexión" (nodos + arcos punteados) en el panel de marca — conecta directo con el mensaje real de CIS Latam ("conectamos países y unimos personas", tomado de cislatam.com). Ver reference/LoginView.vue.
  • Empty states: ícono + copy corto en vez de solo un párrafo (ver el empty-state de TransaccionesView en la referencia) — aplicar el mismo patrón a los demás listados/ABMs cuando estén vacíos (Usuarios, Países, Estaciones, etc.).

5. Animaciones y microinteracciones

  • Login: entrada con fade + slide (<Transition appear>), delay escalonado entre panel de marca y formulario.
  • Botón de submit con spinner + active:scale-[0.98] al presionar.
  • Notificaciones flotantes vía naive-ui (useNotification), con la paleta semántica del punto 1 — requiere envolver la app en <n-notification-provider> + <n-message-provider> (ver reference/App.vue).

6. Barra de navegación contextual para mobile

El sidebar completo no tiene sentido en una pantalla chica. Se agregó una barra inferior fija con los 4 destinos de uso operativo diario (Dashboard, Transacciones, Prefondeo, Reportes) — los ABMs de Admin quedan fuera a propósito, nadie los usa desde el celular. Ver reference/AppLayout.vue.

7. Números tabulares para montos

font-variant-numeric: tabular-nums (clase .tabular-nums-financial) en cualquier cifra monetaria — tendencia 2026 confirmada específicamente para fintech (Stripe/Mercury): las columnas de números alinean, se leen más rápido. Aplicar a toda la futura tabla de Transacciones, no solo al Dashboard.

Pendiente — bloqueante parcial

Los colores de marca (navy/naranja) siguen siendo un placeholder tomado de investigar cis-express.com — el cliente todavía no subió el logo/manual de marca real de CIS Latam. Cuando lo suba: actualizar --color-cis-navy y --color-cis-orange en style.css (un solo lugar, todo el resto de los componentes ya consume la variable, no hay que tocar nada más).

Archivos de referencia adjuntos (reference/)

Código Vue real, ya corrido y validado con capturas de pantalla:

reference/
├── style.css                          → tokens de color (marca + semántica + dark), custom-variant dark
├── composables/useDarkMode.ts         → toggle de dark mode persistido
├── App.vue                             → providers de notificación de Naive UI
├── layouts/AppLayout.vue              → sidebar liviano colapsable + topbar + barra mobile
├── views/LoginView.vue                → animación de entrada + ilustración contextual
├── views/DashboardView.vue            → demo de notificaciones semánticas
├── views/TransaccionesView.vue        → empty-state ilustrado
└── assets/illustrations/connection-map.svg

Checklist para Claude Code

  • [x] Aplicar estos archivos sobre el estado actual del repo — mergeado, no sobreescrito: la referencia traía versiones placeholder de TransaccionesView/AppLayout (sin fetch real, sin filtrado por permisos) porque se armó en paralelo antes de que M1/M2 quedaran funcionales. Se tomó el diseño visual y se injertó sobre la lógica real (fetch, filtros, paginación, meStore.canRead/canWrite), no al revés.
  • [x] Reemplazar los íconos SVG dibujados a mano por un set real — @lucide/vue (no lucide-vue-next, que salió deprecado en favor de ese paquete durante esta misma sesión).
  • [x] Confirmado: no había ningún bypass de autenticación en los archivos de referencia entregados — la lógica de LoginView/authStore era idéntica a la real, solo cambiaba el template visual.
  • [x] Extendida la paleta semántica + dark: a todas las vistas propias que no estaban en la referencia (TransaccionDetalleView, PrefondeoView, ConfiguracionView, SinAccesoView) y a los 7 placeholders de Admin/Reportes (dark mode básico, sin contenido real todavía).
  • [ ] Cuando el cliente suba el logo/manual de marca real: actualizar los 2 tokens de color de marca en style.css (ver sección "Pendiente" arriba) — sigue pendiente, no depende de Claude Code.

Fix aplicado que no estaba en la referencia: el AppLayout.vue de referencia usaba active-class para todos los ítems del sidebar, incluido el de to="/" (Dashboard) — eso reproduce un bug real ya encontrado y corregido en M1 (Vue Router marca ese link como "activo" en cualquier ruta hija, porque comparten el registro de ruta padre). Se aplicó exact-active-class específicamente para ese ítem, igual que en el resto de la app. Verificado con evidencia real (classList del DOM) en /, /transacciones y /admin/configuracion: un solo ítem activo por vez.

Documentación viva — se actualiza junto con el código, no es un anexo aparte.