Saltar a contenido

Documento del prototipo

Las reglas vigentes viven en diseno/sistema-diseno.md. Este archivo documenta lo que el código hace hoy, incluidos los literales Color(0x...) y dp que deben migrarse a tokens.


Tema y diseño

Sistema visual de IslaBox: colores, tipografía, formas, espaciados, fondos y decisiones de diseño.


Identidad visual (de los assets)

Elemento Descripción
Logo principal Palmera (azul navy 0xFF001129) dentro de círculo azul con isla en rojo 0xFFBB0016 (paleta cubana)
Logo horizontal Palmera + texto "isla" (navy) + "box" (rojo)
Logo isotipo-texto Solo texto "isla" navy + "box" rojo
Imagen de éxito Sello/badge con checkmark

⚠️ Los 4 drawables referenciados en IslaImages.kt no existen en res/drawable/. La app crashea al abrir Welcome, Success, y la top bar del dashboard.


Colores

Definidos en ui/theme/Color.kt. Paleta M3 completa con énfasis en el azul navy como primario y el rojo cubano como secundario.

Primary (azul navy)

Token Color Uso
Primary #001129 Botones primarios, texto destacado, íconos principales
OnPrimary #FFFFFF Texto sobre Primary
PrimaryContainer #0F2644 Containers navy (claro)
OnPrimaryContainer #798EB1 Texto sobre containers
InversePrimary #B2C7ED Primary invertido
PrimaryFixed #D5E3FF
PrimaryFixedDim #B2C7ED
OnPrimaryFixed #031C39
OnPrimaryFixedVariant #334767

Secondary (rojo cubano)

Token Color Uso
Secondary #BB0016 Acentos, alertas, mensajes importantes
OnSecondary #FFFFFF
SecondaryContainer #E1272B Containers rojos (medio)
OnSecondaryContainer #FFFBFF
SecondaryFixed #FFDAD6
SecondaryFixedDim #FFB4AC
OnSecondaryFixed #410003
OnSecondaryFixedVariant #93000E

Tertiary (carbón)

Token Color Uso
Tertiary #0E1112 Texto casi-negro, íconos de soporte
OnTertiary #FFFFFF
TertiaryContainer #232627 Containers carbón
OnTertiaryContainer #8B8D8E
TertiaryFixed #E1E3E4
TertiaryFixedDim #C5C7C8
OnTertiaryFixed #191C1D
OnTertiaryFixedVariant #454748

Error

Token Color
Error #BA1A1A
OnError #FFFFFF
ErrorContainer #FFDAD6
OnErrorContainer #93000A

Background y Surface

Token Color Notas
Background #F8F9FF Casi blanco, tinte azul muy sutil
OnBackground #0B1C30
Surface #F8F9FF Igual a Background
OnSurface #0B1C30
SurfaceVariant #D3E4FE Tonos azul claro
OnSurfaceVariant #44474E
SurfaceDim #CBDBF5
SurfaceBright #F8F9FF
SurfaceContainerLowest #FFFFFF
SurfaceContainerLow #EFF4FF
SurfaceContainer #E5EEFF
SurfaceContainerHigh #DCE9FF
SurfaceContainerHighest #D3E4FE
Outline #74777E
OutlineVariant #C4C6CE
InverseSurface #213145
InverseOnSurface #EAF1FF
SurfaceTint #4B5F80

Otros colores hardcodeados (fuera de la paleta M3)

Color Hex Uso
Navy 0xFF001129 Mismo que Primary, usado directamente en componentes
Red 0xFFBB0016 Mismo que Secondary
Blue soft 0xFFE3F2FD (alpha 0.8) Burbuja de fondo LiquidGlass
Pink soft 0xFFFCE4EC (alpha 0.7) Burbuja de fondo LiquidGlass
White 0xFFFFFFFF Cards, surface variants
Gray light Color.LightGray Bordes sutiles, íconos deshabilitados
Gray (semitransparent) Color.LightGray.copy(alpha = 0.5f) Dividers
Pink accent 0xFFE91E63 "EMPIEZA AQUÍ" en FeaturedGuideCard, badge "MIA", dot de notificación
Red custom 0xFFD32F2F Botón "Cerrar Sesión"
Green success 0xFF4CAF50 Status dot identificador activo
Red error dot 0xFFE53935 Stat card "En Tránsito"
Gray dot 0xFF9E9E9E Stat card "En Almacén"
Red damaged 0xFFF44336 StorageControl cuando quedan ≤ 3 días
Yellow warning 0xFFFFC107 StorageControl 4-10 días
Surface para inputs Color(0xFFF1F4F9), Color(0xFFF0F4F8), Color(0xFFF0F0F5) Backgrounds de celdas, íconos

Inconsistencias: - Hay 3 grises diferentes para backgrounds: 0xFFF1F4F9, 0xFFF0F4F8, 0xFFF0F0F5. Unificar. - Hay 2 rojos: 0xFFBB0016 (paleta), 0xFFD32F2F (Cerrar Sesión), 0xFFE91E63 (acentos rosa). Unificar o documentar cuándo usar cada uno.


Tipografía

Definida en ui/theme/Type.kt. Usa FontFamily.SansSerif (placeholder para "Inter").

val Inter = FontFamily.SansSerif  // TODO: cargar Inter desde res/font

val Typography = Typography(
    displayLarge    = 48sp / 56sp / Bold / -0.02 sp
    headlineLarge   = 32sp / 40sp / Bold / -0.01 sp
    headlineMedium  = 24sp / 32sp / SemiBold
    headlineSmall   = 20sp / 28sp / SemiBold
    bodyLarge       = 18sp / 28sp / Normal
    bodyMedium      = 16sp / 24sp / Normal
    bodySmall       = 14sp / 20sp / Normal
    labelLarge      = 12sp / 16sp / Bold / +0.05 sp
    labelMedium     = 16sp / 24sp / SemiBold / +0.1 sp
)

Observaciones: - ✅ Cobertura completa de los 9 estilos M3. - ⚠️ labelMedium tiene fontSize = 16sp que es igual a bodyMedium. Esto es inusual (normalmente labelMedium es 12sp). Es probable que se use mal. - ❌ Falta agregar la fuente Inter en res/font/ (el comentario dice "Por ahora usaremos FontFamily.SansSerif como base").


Shapes

val Shapes = Shapes(
    extraSmall = RoundedCornerShape(4.dp),
    small      = RoundedCornerShape(8.dp),
    medium     = RoundedCornerShape(12.dp),
    large      = RoundedCornerShape(16.dp),
    extraLarge = RoundedCornerShape(24.dp)
)

Usos: - small (8dp): OutlinedTextField, IslaPrimaryButton default - medium (12dp): Algunos cards, dropdowns - large (16dp): (definido pero no usado) - extraLarge (24dp): (definido pero no usado)

💡 Los IslaCard usan RoundedCornerShape(20.dp) hardcoded (no del theme). Considerar usar large o extraLarge.


Spacing

val Spacing = Spacing(
    default       = 0.dp,
    xs            = 4.dp,
    base          = 8.dp,
    sm            = 12.dp,
    md            = 16.dp,   // Margen estándar
    lg            = 24.dp,   // Separación entre secciones
    xl            = 48.dp,   // Separación grande (top hero, fin de pantalla)
    gutter        = 16.dp,   // Coincide con md
    containerMax  = 1200.dp  // Para layouts web (no se usa en app)
)

val LocalSpacing = staticCompositionLocalOf { Spacing() }

Disponible vía:

val spacing = LocalSpacing.current
spacing.md  // 16.dp

Observación: containerMax = 1200.dp no tiene sentido en una app móvil. Es residuo de un proyecto web.


Tema — IslaBoxTheme

@Composable
fun IslaBoxTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colorScheme = if (darkTheme) DarkColorScheme else LightColorScheme  // ⚠️ mismo esquema
    val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            val window = (view.context as Activity).window
            val insetsController = WindowCompat.getInsetsController(window, view)
            window.statusBarColor = android.graphics.Color.TRANSPARENT
            window.navigationBarColor = android.graphics.Color.TRANSPARENT
            val isLightBackground = true  // ⚠️ HARDCODED
            insetsController.isAppearanceLightStatusBars = isLightBackground
            insetsController.isAppearanceLightNavigationBars = isLightBackground
        }
    }
    CompositionLocalProvider(LocalSpacing provides Spacing()) {
        MaterialTheme(colorScheme, Typography, Shapes, content)
    }
}

Observaciones críticas:

  1. DarkColorScheme y LightColorScheme son idénticos (mismas asignaciones token por token). No hay dark mode real.
  2. isLightBackground = true hardcoded: los iconos de status bar siempre serán oscuros. Si en el futuro se quiere dark mode, hay que cambiar esto a !darkTheme.
  3. Edge-to-edge correctamente configurado: statusBarColor y navigationBarColor transparentes. ✅
  4. Compose pinta todo: el tema XML (Theme.IslaBox Material 1) no se ve, así que da igual su configuración.

Fondos

DotGridBackground — auth screens

Patrón técnico minimalista:

  • Fondo blanco #FFFFFF
  • Cuadrícula de 64dp con líneas discontinuas (dashPathEffect floatArrayOf(10f, 15f))
  • Círculos de 3/4 decorativos (~12% de las intersecciones, posición aleatoria)
  • Color: outline.copy(alpha = 0.3f) (gris medio)
  • Animación de entrada: las líneas se "arman" desde los bordes (pares desde un lado, impares desde el otro) en 2.5s con EaseOutQuart
  • Stroke 1.1px

Usado en: Welcome, Login, Register, ForgotPassword, VerificationCode, Success.

LiquidGlassBackground — pantallas principales

Patrón orgánico con gradientes radiales desenfocados:

  • Fondo base #F8F9FA
  • Círculo superior izquierdo 400dp en 0xFFE3F2FD alpha 0.8 → transparente (azul suave)
  • Círculo inferior derecho 450dp en 0xFFFCE4EC alpha 0.7 → transparente (rosa suave)
  • Blur de 100-120dp con BlurredEdgeTreatment.Unbounded

Usado en: MainLayout (Dashboard, Reportes, Paquetes, Guía, Perfil), ReporteDetalle, Notifications.

Observación: este fondo es computacionalmente caro (blur grande en cada frame). Si se nota lag en devices低端, considerar: - Reducir tamaño de los círculos. - Reducir radio de blur. - Cachear el fondo como bitmap. - Hacerlo opcional.


Diseño "Transatlantic Precision"

El comentario en IslaButtons.kt menciona un sistema llamado "Transatlantic Precision" como guía. La filosofía parece ser:

  • Limpio, sin sombras pesadas: border 1dp en lugar de elevación.
  • Esquinas redondeadas pero marcadas: 20dp en cards.
  • Acentos puntuales en rojo: solo para alertas y CTAs primarios.
  • Espaciado generoso: 24dp entre secciones, 48dp al final de pantallas.
  • Mobile-first: la mayoría de componentes asumen ancho 360-414dp.

Decisiones de diseño pendientes

# Decisión Opciones Estado
1 Dark mode real (a) Implementar M3 dark, (b) Siempre light, (c) Auto según sistema Sin definir
2 Fuente Inter (a) Cargar Inter en res/font, (b) Usar otra similar, (c) Mantener SansSerif Sin definir
3 Color único de rojo Unificar BB0016 / D32F2F / E91E63 Sin definir
4 Color único de gris claro Unificar F1F4F9 / F0F4F8 / F0F0F5 Sin definir
5 Forma de cards RoundedCornerShape(20.dp) hardcoded vs Shapes.large (16dp) o extraLarge (24dp) Sin definir
6 Liquid Glass en todos los fondos Hoy está en todas las pantallas principales Sin definir
7 Bordes vs elevación Hoy mayoría usa border 1dp sin elevación Decidido: border
8 Tema XML Mantener Material.Light.NoActionBar o migrar a Material 3 Sin definir
9 labelMedium fontSize 16sp (actual, raro) o 12sp (estándar M3) Sin definir
10 Status bar en dark mode Hoy siempre claro; en dark debería ser oscuro Pendiente al implementar dark

Tareas de tema y diseño

# Tarea Prioridad
1 Decidir sobre dark mode (y por lo menos eliminar el isLightBackground = true hardcoded) Media
2 Cargar fuente Inter en res/font/ (o dejar documentado que es SansSerif) Baja
3 Unificar la paleta de rojos (1 solo red o documentar cuándo usar cada uno) Media
4 Unificar la paleta de grises claros Baja
5 Estandarizar RoundedCornerShape de los cards (usar Shapes.large o extraLarge) Baja
6 Evaluar performance de LiquidGlassBackground en devices低端 Media
7 Migrar themes.xml a Material 3 (Theme.Material3.DayNight.NoActionBar) Baja
8 Revisar labelMedium (16sp es inusual; debería ser 12sp) Baja
9 Eliminar colors.xml (legacy, no se usa) Baja
10 Eliminar containerMax = 1200.dp de Spacing (no aplica a móvil) Baja