Sistema de Tokens
Los tokens de diseño son los valores nombrados del sistema. No se escribe #FF7043 en un componente. Se escribe primary. No se escribe 16px directamente. Se escribe space-4. Cada valor con nombre es una decisión de diseño capturada como vocabulario compartido entre equipos.
Los tokens son independientes de la plataforma: el mismo nombre se resuelve al valor correcto en Flutter, en CSS, en React Native o en cualquier otro sistema de implementación. Cuando un token cambia, el cambio se propaga automáticamente a todo el sistema.
Categorías de tokens
El sistema define seis categorías de tokens. Cada categoría cubre un dominio visual distinto.
graph LR A["Tokens"] --> B["Color"] A --> C["Tipografía"] A --> D["Espaciado"] A --> E["Elevación"] A --> F["Bordes"] A --> G["Motion"]
Tokens de color
Jerarquía de color
El sistema usa dos niveles de tokens de color. Los tokens de nivel primitivo son los valores hexadecimales sin semántica. Los tokens de nivel semántico asignan significado a los primitivos y son los únicos que se usan en componentes.
En código no se hace referencia nunca a un primitivo directamente. Siempre se usa el token semántico.
Primitivo: orange-600 = #FF7043Semántico: primary = orange-600Uso: background = primary ✓ background = #FF7043 ✗Tokens primarios
| Token | Valor primitivo | Hex | Uso |
|---|---|---|---|
primary | orange-600 | #FF7043 | Acciones principales, botones CTA, íconos activos |
onPrimary | white | #FFFFFF | Texto e íconos sobre primary |
primaryContainer | orange-50 | #FFF2E8 | Fondos de secciones destacadas, chips activos |
onPrimaryContainer | orange-800 | #E64A19 | Texto sobre primaryContainer |
primaryHover | orange-700 | #F4511E | Estado hover del color primario (solo web) |
primaryPressed | orange-800 | #E64A19 | Estado pressed del color primario |
primaryDisabled | orange-200 | #FFCCBC | Estado deshabilitado de elementos primarios |
Tokens secundarios
| Token | Valor primitivo | Hex | Uso |
|---|---|---|---|
secondary | blue-700 | #1976D2 | Acciones secundarias, información, enlaces |
onSecondary | white | #FFFFFF | Texto e íconos sobre secondary |
secondaryContainer | blue-50 | #E1F4FF | Fondos informativos |
onSecondaryContainer | blue-900 | #0D47A1 | Texto sobre secondaryContainer |
Tokens terciarios
| Token | Valor primitivo | Hex | Uso |
|---|---|---|---|
tertiary | green-700 | #388E3C | Confirmaciones, estados exitosos |
onTertiary | white | #FFFFFF | Texto e íconos sobre tertiary |
tertiaryContainer | green-50 | #E8F5E8 | Fondos de estado correcto |
onTertiaryContainer | green-900 | #1B5E20 | Texto sobre tertiaryContainer |
Tokens de superficie
Las superficies son la base sobre la que se construye todo el contenido. Son blancas o gris muy claro y nunca llevan color de marca saturado.
| Token | Hex | Uso |
|---|---|---|
surface | #FFFFFF | Fondo base de pantallas, tarjetas, modales |
surfaceDim | #F8F9FA | Fondo de listas, secciones alternadas |
surfaceContainer | #F5F6F7 | Fondo de inputs, chips, elementos neutros |
surfaceContainerHighest | #EEF0F2 | Secciones con mayor jerarquía visual neutra |
surfaceTint | #FFF8F6 | Superficie con subtono naranja muy sutil (uso mínimo) |
scrim | rgba(0,0,0,0.30) | Overlay detrás de modales y bottom sheets |
Tokens de texto
| Token | Hex | Uso |
|---|---|---|
onSurface | #1A1C1E | Texto primario: títulos, valores, etiquetas |
onSurfaceVariant | #6C7075 | Texto secundario: subtítulos, metadatos, hints |
onSurfaceDisabled | #ADADAD | Texto en estado deshabilitado |
outline | #D4D7DA | Bordes de inputs, divisores, separadores |
outlineVariant | #EAECEF | Bordes sutiles, fondos de hover neutros |
Tokens de estado semántico
Los estados semánticos tienen siempre dos tokens: el color base (para texto, íconos, bordes) y el contenedor (para fondos sutiles). Nunca se mezclan con tokens de otro estado.
| Estado | Token base | Hex base | Token contenedor | Hex contenedor |
|---|---|---|---|---|
| Error | error | #D32F2F | errorContainer | #FFEBEE |
| Éxito | success | #2E7D32 | successContainer | #E8F5E8 |
| Advertencia | warning | #F57C00 | warningContainer | #FFF3E0 |
| Información | info | #1976D2 | infoContainer | #E1F4FF |
| Pendiente | pending | #EC407A | pendingContainer | #FCE4EC |
| Cancelado | cancelled | #90A4AE | cancelledContainer | #F5F5F5 |
Tokens de tipografía
El sistema usa dos familias tipográficas con roles estructurales diferenciados. Poppins para jerarquía y acción. Inter para lectura y datos.
Escala tipográfica
La escala sigue cinco rangos semánticos. Cada nivel define familia, peso, tamaño y altura de línea como un bloque indivisible. No se combina el tamaño de un nivel con el peso de otro.
Display — pantallas de impacto y dashboards
| Token | Familia | Peso | Tamaño | Alto de línea |
|---|---|---|---|---|
display-large | Poppins | 600 | 57px/sp | 64px |
display-medium | Poppins | 600 | 45px/sp | 52px |
display-small | Poppins | 500 | 36px/sp | 44px |
Uso: números de estado en dashboards, métricas de gran tamaño, pantallas de confirmación de impacto.
Headline — encabezados de sección y pantalla
| Token | Familia | Peso | Tamaño | Alto de línea |
|---|---|---|---|---|
headline-large | Poppins | 600 | 32px/sp | 40px |
headline-medium | Poppins | 600 | 28px/sp | 36px |
headline-small | Poppins | 500 | 24px/sp | 32px |
Uso: título principal de pantalla (headline-large en mobile, headline-medium en desktop), título de sección.
Title — encabezados de tarjeta y lista
| Token | Familia | Peso | Tamaño | Alto de línea |
|---|---|---|---|---|
title-large | Poppins | 500 | 22px/sp | 28px |
title-medium | Poppins | 500 | 16px/sp | 24px |
title-small | Poppins | 500 | 14px/sp | 20px |
Uso: título de tarjeta (title-medium), nombre de ítem en lista, encabezado de columna de tabla.
Body — texto de contenido y datos
| Token | Familia | Peso | Tamaño | Alto de línea |
|---|---|---|---|---|
body-large | Inter | 400 | 16px/sp | 24px |
body-medium | Inter | 400 | 14px/sp | 20px |
body-small | Inter | 400 | 12px/sp | 16px |
Uso: texto de párrafo, valores en campos, contenido de celdas de tabla, descripciones.
Label — etiquetas de interfaz y botones
| Token | Familia | Peso | Tamaño | Alto de línea |
|---|---|---|---|---|
label-large | Poppins | 500 | 14px/sp | 20px |
label-medium | Poppins | 500 | 12px/sp | 16px |
label-small | Poppins | 500 | 11px/sp | 16px |
Uso: texto de botones (label-large), etiquetas de input, chips, tabs, badges.
Tokens de espaciado
El sistema usa una escala de espaciado basada en múltiplos de 4px. Cada valor de espaciado tiene un nombre que indica el número de unidades de 4px.
| Token | Valor | Uso típico |
|---|---|---|
space-1 | 4px | Microajustes, iconos internos, gaps mínimos |
space-2 | 8px | Padding interno de badges y chips |
space-3 | 12px | Padding de botones pequeños, separación de ítems |
space-4 | 16px | Padding base de componentes (botones, inputs) |
space-5 | 20px | Separación entre grupos de elementos |
space-6 | 24px | Padding base de tarjetas, margen de sección |
space-8 | 32px | Separación entre secciones de una pantalla |
space-10 | 40px | Margen entre componentes de alto nivel |
space-12 | 48px | Altura mínima de área táctil, separación de bloques |
space-16 | 64px | Espaciado estructural, top bars, footers |
space-20 | 80px | Separación entre secciones de alto impacto visual |
space-24 | 96px | Espaciado de layouts de landing y dashboards |
Los valores fuera de esta escala (3px, 5px, 11px, 17px) no existen en el sistema y no se aceptan en implementación.
Tokens de elevación
La elevación comunica la jerarquía de capas de la interfaz. Cada nivel tiene una sombra box-shadow que produce la sensación correcta de profundidad sin saturar visualmente la pantalla.
| Token | box-shadow (CSS) | Uso |
|---|---|---|
elevation-0 | none | Superficies sin elevación (fondos planos) |
elevation-1 | 0 1px 3px rgba(0,0,0,0.08) | Tarjetas en reposo, inputs |
elevation-2 | 0 2px 8px rgba(0,0,0,0.10) | Dropdowns, tooltips, tarjetas elevadas |
elevation-3 | 0 4px 16px rgba(0,0,0,0.12) | Bottom sheets, popovers, modales ligeros |
elevation-4 | 0 8px 32px rgba(0,0,0,0.16) | Modales, diálogos, drawers |
Las sombras siempre son negras con opacidad. No existen sombras de color. No se mezclan niveles de elevación en el mismo nivel visual de la interfaz.
Tokens de radio de borde
El sistema define seis valores de radio de borde. El radio transmite personalidad: un radio mayor comunica modernidad y suavidad; el radio cero comunica sobriedad técnica. El sistema usa valores intermedios que equilibran modernidad con funcionalidad.
| Token | Valor | Uso |
|---|---|---|
radius-none | 0px | Tablas, separadores, elementos de lista en ERP |
radius-sm | 4px | Chips, badges, inputs en contexto ERP |
radius-md | 8px | Botones en desktop, inputs estándar |
radius-lg | 12px | Botones en mobile, tarjetas compactas |
radius-xl | 16px | Tarjetas de contenido, bottom sheets |
radius-2xl | 24px | Modales, paneles flotantes |
radius-full | 9999px | Avatares, indicadores circulares, FAB |
Tokens de motion
El motion tiene su propio sistema de tokens. Las animaciones sin tokens de duración y curva producen interfaces inconsistentes aunque visualmente correctas en aislado.
Duración
| Token | Valor | Uso |
|---|---|---|
duration-instant | 50ms | Feedback táctil inmediato (cambio de color en pressed) |
duration-fast | 100ms | Estados de hover, transiciones de color |
duration-normal | 200ms | Transiciones de componentes: expand, collapse, fade |
duration-slow | 300ms | Entrada/salida de elementos de UI (modal, sheet) |
duration-xslow | 500ms | Animaciones de impacto, transiciones de pantalla |
Curva de animación
| Token | Valor | Uso |
|---|---|---|
easing-standard | cubic-bezier(0.2, 0, 0, 1) | Movimientos de transición estándar |
easing-enter | cubic-bezier(0, 0, 0, 1) | Elementos que entran a la pantalla |
easing-exit | cubic-bezier(0.3, 0.1, 1, 1) | Elementos que salen de la pantalla |
easing-linear | linear | Indicadores de progreso, loaders |
Reglas de motion
- Nada se anima si no sirve a la comprensión del cambio de estado. El motion que no comunica es ruido.
- Las transiciones de pantalla completa usan
duration-xslowconeasing-standard. Es la transición más lenta del sistema y se usa raramente. - Los estados de hover y press usan
duration-fastpara que la interfaz sienta respuesta inmediata. - En contextos de alto rendimiento (listas largas, tablas de ERP), las animaciones se reducen o eliminan.
Cómo implementar tokens
Los tokens son agnósticos de tecnología. Cada plataforma los implementa en su formato nativo.
/* CSS Custom Properties */:root { --color-primary: #ff7043; --color-on-primary: #ffffff; --color-surface: #ffffff; --color-on-surface: #1a1c1e; --space-4: 16px; --radius-lg: 12px; --duration-normal: 200ms; --easing-standard: cubic-bezier(0.2, 0, 0, 1);}// Flutter — ThemeData tokensstatic const Color primary = Color(0xFFFF7043);static const Color onPrimary = Color(0xFFFFFFFF);static const Color surface = Color(0xFFFFFFFF);static const Color onSurface = Color(0xFF1A1C1E);static const double space4 = 16.0;static const double radiusLg = 12.0;static const Duration durationNormal = Duration(milliseconds: 200);// TypeScript / Reactexport const tokens = { color: { primary: "#FF7043", onPrimary: "#FFFFFF", surface: "#FFFFFF", onSurface: "#1A1C1E", }, space: { 4: "16px", 6: "24px", }, radius: { lg: "12px", }, duration: { normal: "200ms", },};Resumen
- Los tokens son los valores nombrados del sistema; nunca se usan valores en crudo en componentes.
- El color tiene dos niveles: primitivos (hex) y semánticos (significado); se usan siempre los semánticos.
- El naranja primario (
#FF7043) define la acción; las superficies son blancas o gris muy claro; azul y verde solo para estados informacionales y de éxito. - El espaciado usa una escala de múltiplos de 4px con trece niveles definidos; no se usan valores fuera de la escala.
- Motion tiene tokens de duración (50ms a 500ms) y curva; sin tokens de motion no hay animaciones en el sistema.
- Los tokens se implementan como Custom Properties en CSS, constantes en Flutter y objetos en TypeScript; el formato cambia, el valor no.