| Pilar | Descripción | Regla clave |
|---|---|---|
| Flat 2D | Sin sombras, gradientes ni texturas. Elementos planos y limpios. | box-shadow: none en componentes core. MUST |
| Color vibrante | Paleta de tokens semánticos. El color comunica estado, no decoración. | Usar solo tokens definidos (--primary, --danger…). MUST |
| Tipografía limpia | Inter para lectura; JetBrains Mono para datos y tokens técnicos. | No mezclar más de 2 familias tipográficas. MUST |
| Ritmo de espaciado | Escala de 4 px. Espaciado coherente en toda la interfaz. | Todos los márgenes/paddings siguen la escala 4/8/12/16/24/32. MUST |
El contraste de --text sobre --surface es 16.1:1 (AAA). El --primary sobre blanco alcanza 3.3:1 — usar solo en elementos gráficos grandes o con borde visible. Para texto sobre fondo blanco usar --text o --muted.
--sp-1--sp-2--sp-3--sp-4--sp-6--sp-8| Variante | Uso semántico | Estado hover | Token de color |
|---|---|---|---|
| Primary | Acción principal de la página (1 por vista) | Oscurecer 10% → #D95530 |
--primary |
| Secondary | Acciones secundarias (nav, filtros, exportar) | Oscurecer 10% → #7C3AED |
--secondary |
| Ghost | Cancelar, cerrar, acciones neutras | --neutral bg + --border stroke |
--border / --text |
| Danger | Eliminar, revocar acceso (siempre con confirmación) | Oscurecer 10% → #B91C1C |
--danger |
Regla: el estado focus-visible debe mostrar un anillo de 3 px con el color del token del botón + 2 px de offset. Los botones nunca usan outline:none sin reemplazarlo.
Los badges comunican estado semántico — no estilo. Nunca usar un badge de color arbitrario fuera de la paleta semántica. El icono (punto) debe incluir un atributo aria-label describiendo el estado cuando no hay texto visible.
| Elemento | Token | Regla |
|---|---|---|
| Borde superior coloreado | Color semántico de la métrica | 3 px de altura, sin border-radius superior. MUST |
| Icono contenedor | Tint del color semántico (10% opacidad) | 32×32 px, border-radius: var(--r-sm). SHOULD |
| Valor KPI | --fs-2xl + fw-800 |
Siempre --text. Nunca colorear el valor directamente. MUST |
| Indicador de cambio | --success / --danger / --muted |
Texto de 12 px con símbolo de dirección (▲ ▼ —). MUST |
Interacción: el estado focus usa border-color: var(--primary). El estado error usa border-color: var(--danger) con mensaje inline. Los labels son siempre visibles (nunca solo placeholder). Todo input debe tener id vinculado con for en el label.
| Criterio | Requisito | Cómo testar |
|---|---|---|
| 1.4.3 Contraste texto | Mínimo 4.5:1 para texto < 18pt; 3:1 para texto grande | axe-core · WebAIM Contrast Checker · --text/#111827 sobre --surface = 16.1:1 ✓ |
| 2.1.1 Teclado | Todos los botones, inputs y links accesibles con Tab/Enter/Space | Navegación completa sin ratón. Verificar orden de Tab lógico. |
| 2.4.7 Focus visible | Estado focus siempre visible (anillo 3 px mínimo) | Inspeccionar cada componente con Tab; comprobar que el outline es visible sobre cualquier fondo. |
| 3.3.1 Error identificado | Los errores de formulario se describen en texto (no solo color) | El mensaje de error aparece debajo del campo. aria-describedby vincula input con mensaje. |
| 4.1.2 Nombre/Rol/Valor | Todos los controles interactivos tienen nombre accesible | Verificar aria-label en iconos solos; labels en todos los inputs. |
| 1.4.11 Contraste no-texto | Iconos y bordes de UI: mínimo 3:1 contra fondo | --border (#E5E7EB) sobre --surface no supera 3:1 — compensar con texto o icono adicional en campos. |
Los gradientes violan el principio Flat. Aumentan el peso visual y dificultan el cálculo de contraste.
Color plano #F2673C. Sin gradiente, sin sombra. Hover oscurece uniformemente.
Contraste insuficiente. El color #cccccc sobre blanco = 1.6:1, muy por debajo del 4.5:1 requerido.
--muted sobre blanco
--muted (#6B7280) sobre blanco = 4.6:1 ✓ Supera el umbral AA.
Colores ad-hoc fuera de tokens. Rompen la coherencia y son imposibles de mantener.
Badges con tokens semánticos. Mismo lenguaje visual en toda la app.
Valores de espaciado arbitrarios. Rompen el ritmo de la cuadrícula de 4 px.
Tokens de espaciado. Múltiplos de 4 px. Mantenibles y predecibles.
-
✓Sin sombras en componentes core Grep por
box-shadowen CSS de componentes. Solo permitido en modales/dropdowns con valor máximo0 2px 8px rgba(0,0,0,.08). -
✓Sin gradientes en fondos interactivos Grep por
linear-gradientyradial-gradient. Solo permitido en gráficas de datos. -
✓Todos los colores usan tokens CSS No debe haber valores hex directos en estilos de componentes (excepto en la definición de los propios tokens en
:root). -
Contraste AA verificado con axe-core Ejecutar
npx axe --dir ./dist. Cero violaciones de contraste en nivel AA. -
Focus visible en todos los elementos interactivos Navegar con Tab por toda la vista sin ratón. Cada elemento debe mostrar anillo de focus de al menos 3 px.
-
Labels en todos los inputs Comprobar con
document.querySelectorAll('input:not([aria-label]):not([id])')— debe devolver lista vacía. -
Espaciado en múltiplos de 4 px Revisar que todos los
paddingymarginusan tokens--sp-*o valores de la escala 4/8/12/16/24/32. -
Tipografía solo Inter / JetBrains Mono Grep por
font-familydistinto devar(--font)ovar(--mono). -
✓Botón danger con confirmación Todas las acciones irreversibles (eliminar, revocar) deben tener modal o diálogo de confirmación antes de ejecutar.
-
✓Estados vacío/carga/error definidos en cada componente No mostrar componentes vacíos sin un estado explícito (skeleton, mensaje, ilustración).
Versión del sistema: 1.0.0 · Generado para NutriTrack SaaS ·
Revisado con CULTIVA IA Design System Flat Skill (id: 92ae96a9) ·
WCAG 2.2 AA