v2.0 — Colorful Design System

NutriPlan Design System

Guía de implementación lista para ingeniería y diseño. Sistema colorido, accesible y moderno para el rediseño de la plataforma clínica.

WCAG 2.2 AA Inter + JetBrains Mono 8pt Grid React / Figma Tokens CSS

🎯 Contexto y Objetivo de Diseño

NutriPlan v2.0 reemplaza una interfaz Bootstrap 3 heredada por un sistema vibrante, coherente y accesible. Los profesionales sanitarios usan la plataforma 6–8 horas/día, por lo que la legibilidad, los estados de interacción explícitos y el confort visual son requisitos no negociables.

Principios rectores

  • 01Energía con propósito — Cada color señaliza significado (progreso, alerta, acción). No se usa color solo para decorar.
  • 02Claridad de estado — Todo componente interactivo expone sus estados: default, hover, focus, active, disabled, error.
  • 03Accesibilidad no opcional — WCAG 2.2 AA en cada texto y UI component. Si hay conflicto estético, gana la accesibilidad.
  • 04Tokens primero — Nunca hardcodear valores de color o espaciado. Usar siempre tokens semánticos.

Componentes Fase 1

1 Botones (primary, secondary, ghost, danger, gradient)
2 Patient Card (estado nutricional, progreso, acciones)
3 Badges de estado nutricional (5 variantes)
4 Inputs de formulario de plan alimentario
5 Alertas y banners de sistema (4 variantes)

🎨 Tokens de Color

Paleta de 5 familias semánticas + neutros. Usar siempre el token semántico en componentes, nunca el valor hex directamente. Los gradientes son tokens de primera clase para superficies de énfasis.

Colores primarios y de marca

Primary 500
#3B82F6
--color-primary-500
Primary 600
#2563EB
--color-primary-600
Secondary 500
#8B5CF6
--color-secondary-500
Success 500
#16A34A
--color-success-500
Warning 500
#D97706
--color-warning-500
Danger 500
#DC2626
--color-danger-500

Gradientes de marca

--gradient-brand
--gradient-success
--gradient-energy

Tabla de contraste (WCAG 2.2)

Muestra Token Valor Sobre blanco Nivel Uso semántico
--color-primary-700 #1D4ED8 7.3:1 AAA Texto enlace
--color-primary-600 #2563EB 5.9:1 AAA Hover state
--color-primary-500 #3B82F6 3.6:1 AA UI Botón primario (texto blanco sobre fondo azul: 4.5+)
--color-success-700 #166534 8.7:1 AAA Texto badge "Óptimo"
--color-danger-700 #991B1B 9.2:1 AAA Texto badge "Déficit"
--text-primary #111827 18.1:1 AAA Texto corporal, etiquetas
--text-secondary #374151 10.7:1 AAA Texto meta, hints, placeholders visibles

Aa Tipografía

Escala de 7 pasos sobre una base de 16px. Inter para cuerpo e UI; JetBrains Mono para valores numéricos clínicos (kcal, macros, métricas). Pesos disponibles: 100–900.

--text-3xl40px · 800 · 1.25
Plan Nutricional
--text-2xl32px · 700 · 1.25
Dashboard Pacientes
--text-xl24px · 600 · 1.35
Seguimiento Semanal
--text-lg20px · 600 · 1.4
Resumen de macronutrientes
--text-base16px · 400 · 1.5
El paciente ha alcanzado el 87% de su objetivo calórico semanal. Revisar la distribución de proteínas.
--text-sm14px · 400 · 1.5
Última actualización: 14 jun 2026 · Próxima revisión: 21 jun 2026
--text-xs12px · 500 · 1.4
ETIQUETA DE CATEGORÍA
Mono numeric24px · 700 · 1.2
2.340 kcal · 187g PRO · 62g GRA

Espaciado — Grid de 8pt

Todos los márgenes, paddings y gaps deben ser múltiplos de 8px. La excepción permitida es 4px (--space-1) para ajustes internos de componentes pequeños.

--space-1
4px
--space-2
8px
--space-3
12px
--space-4
16px
--space-5
20px
--space-6
24px
--space-8
32px
--space-10
40px
--space-12
48px
--space-16
64px

Botones

Touch target mínimo de 44px de altura. Todos los botones deben tener :focus-visible visible con un outline de 3px en --color-primary-300. El estado :active añade translateY(1px) para retroalimentación táctil.

Variantes

Tamaños

Estados

default
:hover
:focus-visible
:disabled
loading

Reglas de uso

Badges de Estado Nutricional

Cinco variantes semánticas para comunicar el estado del plan nutricional de un paciente. Siempre incluyen un dot de color para no depender solo del color (accesibilidad daltonismo).

Óptimo Déficit calórico Revisar macros En revisión Sin datos

Anatomía

  • Dot: 6×6px, border-radius 50%. Refuerza el significado sin texto.
  • Label: 12px, weight 600. Máximo 2 palabras.
  • Padding: 3px vertical, 10px horizontal.
  • Radius: --radius-full (pill).

Tokens por variante

Óptimo success-50 / success-700
Déficit danger-50 / danger-700
Revisar warning-50 / warning-600
En revisión primary-50 / primary-700
Sin datos neutral-100 / neutral-700

👤 Patient Card

Tarjeta de resumen de paciente. El borde superior de 4px codifica el estado nutricional. Incluye avatar con gradiente, estadísticas clave en monoespacio y barra de progreso calórico.

María García López
Diabética T2 · Plan Mediterráneo · 4 semanas
2.140
kcal/día
142g
Proteína
-2.3kg
Progreso
Progreso calórico semanal 94%
Carlos Ruiz Martínez
Pérdida de peso · Plan hipocalórico · 8 semanas
1.480
kcal/día
98g
Proteína
-0.4kg
Progreso
Progreso calórico semanal 58%
Ana Sánchez Vega
Deportista · Plan alto en proteínas · 2 semanas
2.680
kcal/día
241g
Proteína
+1.1kg
Progreso
Progreso calórico semanal 78%

Reglas del componente

  • Anatomía: borde-top (4px) → header (avatar + nombre + meta) → stats (3 cols) → progress → footer (badge + CTA).
  • Avatar: Iniciales (2 chars), 44×44px mínimo, gradiente según contexto. Si hay foto, usar <img alt="Foto de [nombre]">.
  • Stats: Valores en --font-mono para alineación tabular. Máximo 3 métricas.
  • Hover: box-shadow: var(--shadow-lg); translateY(-2px). Solo si prefers-reduced-motion: no-preference.
  • Focus: outline: 3px solid --color-primary-300 cuando recibe foco por teclado.
  • aria-label: Obligatorio: "Paciente [nombre], estado [estado]".

Formularios — Plan Alimentario

Inputs con altura mínima de 44px. Borde de 2px para visibilidad; pasa a --color-primary-500 en focus con ring de 3px. El estado error usa --color-danger-500 y siempre incluye mensaje de texto (no solo color).

✓ Rango saludable para el perfil del paciente
⚠ Excede el límite recomendado (máx. 240g para este perfil)

Alergias, intolerancias, preferencias culturales.

Alertas y Banners de Sistema

Cuatro variantes semánticas. Siempre incluyen título + descripción (nunca solo icono). Los banners críticos (danger) también deben enviarse por notificación al dietista responsable.

Sincronización pendiente
Los datos de actividad del dispositivo wearable se sincronizarán en los próximos 15 minutos. Las calorías quemadas pueden variar hasta entonces.
Objetivo semanal alcanzado
María García ha completado el 100% de sus objetivos nutricionales esta semana. El plan está funcionando correctamente.

Accesibilidad — Requisitos y Criterios Testables

WCAG 2.2 AA como mínimo no negociable. Los criterios de aceptación deben estar en los tickets de QA y ser verificables con axe DevTools, Lighthouse y prueba manual de teclado.

Criterios obligatorios

  • AA Contraste texto normal ≥ 4.5:1. Verificar con axe DevTools en cada PR.
  • AA Contraste UI components y bordes de focus ≥ 3:1.
  • AA Toda la interacción navegable por teclado. Tab order lógico (DOM order). Focus visible en :focus-visible, nunca outline: none.
  • AA Touch targets ≥ 44×44px. Verificar con Chrome DevTools > Layers en mobile viewport.
  • AA Errores de formulario en texto (role="alert" o aria-describedby). Nunca solo en color.
  • AA prefers-reduced-motion: deshabilitar todas las transiciones y animaciones. Testar en macOS: Accesibilidad > Reducir movimiento.
  • AA Imágenes y avatares decorativos: aria-hidden="true". Contenidos: alt descriptivo.
  • Sem HTML semántico primero, ARIA solo cuando el semántico no es suficiente. No usar role="button" en un <div> cuando se puede usar <button>.

Herramientas de test

axe DevTools
Integrar en Playwright CI. npm i axe-core. Zero violations en cada PR.
Lighthouse
Score accesibilidad ≥ 95 en CI/CD. Umbral en lighthouserc.json.
Test manual teclado
Tab por todo el formulario + patient cards. Enter/Space activan botones. Escape cierra modales.
Lector de pantalla
VoiceOver (macOS/iOS) + NVDA (Windows). Probar flujo: listar pacientes → abrir plan → guardar cambios.

Anti-patrones y Migraciones

Patrones heredados de Bootstrap 3 que deben eliminarse en el rediseño. Cada anti-patrón tiene su alternativa correcta y notas de migración.

✗ No hacer — Bajo contraste
Texto gris sobre fondo gris claro. Ratio ~1.8:1 — falla WCAG.
Objetivo calórico: 2.140 kcal

color: #9CA3AF; background: #F3F4F6
✓ Hacer — Contraste suficiente
Texto oscuro o usar --text-secondary sobre blanco.
Objetivo calórico: 2.140 kcal

color: --text-secondary (#374151) — ratio 10.7:1
✗ No hacer — Botón sin label descriptivo
Label ambiguo que no describe la acción.


<button>OK</button>
✓ Hacer — Label accionable
El label describe exactamente qué ocurrirá.


<button>Guardar plan nutricional</button>
✗ No hacer — Error solo en color
Borde rojo sin mensaje de texto. Invisible para usuarios daltónicos.
border: 2px solid red; /* sin mensaje */
✓ Hacer — Error con texto y color
Borde rojo + mensaje de texto con role="alert".
border-color: --color-danger-500;
<span role="alert">Campo requerido</span>
✗ No hacer — Hardcodear valores
Valores mágicos que rompen la coherencia del sistema.
background: #3B82F6;
padding: 11px 19px;
border-radius: 6px;
✓ Hacer — Tokens semánticos
Tokens que se actualizan globalmente al cambiar el tema.
background: var(--color-primary-500);
padding: var(--space-3) var(--space-5);
border-radius: var(--radius-md);

Guía de migración desde Bootstrap 3

Patrón Bootstrap 3Reemplazo NutriPlan DSNotas
btn btn-defaultbtn btn-ghostActualizar todos los botones de cancelar/secundarios
btn btn-primarybtn btn-primaryMantener semántica, actualizar estilos CSS
label label-successbadge badge-optimalAñadir dot de color para no-daltonismo
alert alert-infoalert alert-infoAñadir role="status" o role="alert" según criticidad
form-controlinputAltura 44px, borde 2px, focus ring obligatorio
panel panel-defaultpatient-cardAñadir borde semántico, role="article", tabindex

QA Checklist — Code Review

Lista de verificación ejecutable en cada PR que afecte a componentes del sistema de diseño. Copiar al description del PR y marcar antes de solicitar review.

Tokens y fundamentos
  • Todos los colores usan variables CSS (var(--color-...)), sin hex hardcodeados
  • Todos los espaciados son múltiplos de 8px (o 4px para ajustes micro)
  • Tipografía usa escala definida (--text-xs a --text-3xl)
  • Gradientes solo desde tokens --gradient-*
  • Radios de borde desde tokens --radius-*
Accesibilidad
  • axe DevTools: cero violaciones
  • Lighthouse Accessibility ≥ 95
  • Todos los botones accesibles por teclado (Tab + Enter/Space)
  • Focus visible en todos los interactivos (:focus-visible, nunca outline:none)
  • Touch targets ≥ 44×44px en viewport móvil
  • Contraste texto ≥ 4.5:1 (normal) o ≥ 3:1 (UI components)
  • Errores de formulario en texto, no solo en color
  • prefers-reduced-motion deshabilita animaciones
Componentes
  • Botones tienen todos los estados: default, hover, focus, active, disabled, loading
  • Patient cards tienen role="article", aria-label y tabindex="0"
  • Badges siempre incluyen dot de color + texto (no dependen solo del color)
  • Alertas críticas tienen role="alert" o aria-live="assertive"
  • Inputs tienen label visible asociado con for/id
  • Select tiene appearance:none con icono custom
Responsive y edge cases
  • Testar en viewport 375px (iPhone SE) y 1440px
  • Textos largos en patient cards no rompen layout (overflow ellipsis)
  • Formularios apilados en 1 columna en mobile
  • Botones de texto largo: mínimo 44px altura, texto no cortado
  • Progress bars no desborden su contenedor
  • Badges no se rompen si el texto del estado es largo
  • Estado vacío (0 pacientes) diseñado y no muestra layout roto