01 · Contexto y objetivos

Intent: Unificar la interfaz del dashboard de NovaPay con un sistema coherente, predecible y mantenible por un equipo de desarrollo sin diseñador dedicado. Cada token, regla y componente debe poder implementarse directamente sin interpretación subjetiva.

Componentes base
7
Button, Input, Badge, Card, Alert, Table, Modal
Tokens de color
7
primary · secondary · success · warning · danger · surface · text
Escala tipográfica
6
12 / 14 / 16 / 20 / 24 / 32 px

02 · Tokens de color

Los tokens son la única fuente de verdad para colores. Usar siempre el token semántico, nunca el valor hexadecimal directo en componentes.

--color-primary
#000000
--color-secondary
#111111
--color-success
#16A34A
--color-warning
#D97706
--color-danger
#DC2626
--color-surface
#FFFFFF
--color-text
#111827
--color-muted
#6B7280
/* tokens.css — importar en index.css */
:root {
  --color-primary: #000000;
  --color-success: #16A34A;
  --color-warning: #D97706;
  --color-danger:  #DC2626;
  --color-surface: #FFFFFF;
  --color-text:   #111827;
}

03 · Tipografía

Escala de 6 tamaños. Font primaria: Geist (texto y display). Font mono: Fira Code (labels, código, métricas).

fs-2xl
32px / 700 / -0.03em
Dashboard
fs-xl
24px / 600 / -0.02em
Transacciones del mes
fs-lg
20px / 600 / -0.01em
Resumen de pagos
fs-md / body
16px / 400 / 0
Tu factura ha sido enviada correctamente al cliente.
fs-sm / default
14px / 400 / 0
Última actualización: 16 jun 2026 a las 14:32
fs-xs / mono
12px / 500 / +0.08em
IMPORTE · ESTADO · REFERENCIA

04 · Espaciado

Escala de 4px base. Todos los márgenes, padding y gaps deben usar estos valores. Nunca usar valores arbitrarios.

sp-1 · 4px
4px
sp-2 · 8px
8px
sp-3 · 12px
12px
sp-4 · 16px
16px
sp-6 · 24px
24px
sp-8 · 32px
32px

05 · Componente — Button

El botón es el componente de acción principal. Cada variante tiene una semántica clara y no debe usarse fuera de su contexto.

Variantes
MUST
Solo un btn-default (CTA primario) por vista. Si hay dos acciones, la secundaria usa btn-outline.
SHOULD
Los labels deben ser verbos de acción concretos: "Enviar factura" ✓ — "OK" ✗, "Confirmar" ✗.
NEVER
No usar btn-danger para la CTA principal. Solo para acciones destructivas irreversibles (eliminar, cancelar contrato).

06 · Componente — Input

Campos de texto, número e importe. Cuatro estados requeridos: default, focus, error, disabled.

Aparecerá en el PDF de la factura enviado al cliente.
Dirección de email no válida.
No editable. Modifica en Configuración > Empresa.

07 · Componente — Badge

Etiquetas de estado para transacciones, facturas y usuarios. Nunca usar color sin significado semántico claro.

Pagado Pendiente Vencido Borrador Archivado
Mapeo semántico: success=Pagado · warning=Pendiente/En revisión · danger=Vencido/Error · default=Borrador/Neutro · outline=Archivado/Inactivo

08 · Componente — Table

Tabla de datos para listados de facturas y transacciones. Headers siempre en monospace mayúsculas. Importes en Fira Code.

REFERENCIA CLIENTE CONCEPTO FECHA IMPORTE ESTADO
NP-2026-001 Tienda Natura SL Consultoría marketing IA 01/06/2026 +3.200,00 € Pagado
NP-2026-002 Farmacia Roca Automatización WhatsApp 08/06/2026 +1.850,00 € Pendiente
NP-2026-003 Clínica Ortiz Agente IA atención cliente 01/05/2026 +900,00 € Vencido
NP-2026-004 LogiTrans SL Dashboard analítico 14/06/2026 Borrador

09 · Componente — Alert

Mensajes del sistema no interruptivos. Para errores críticos de flujo, usar Modal. Para confirmaciones post-acción, usar Alert success transitorio (auto-dismiss 5s).

Factura enviada correctamente
La factura NP-2026-002 ha sido enviada a farmaciaroca@email.com. El cliente recibirá un email de confirmación.
Método de pago próximo a vencer
La tarjeta Visa terminada en 4821 vence el 30/06/2026. Actualiza los datos para evitar interrupciones.
Error al procesar el pago
La transacción fue rechazada por el banco emisor (código: insufficient_funds). Revisa el saldo o usa otro método.
Nuevo: Domiciliación bancaria disponible
Tus clientes pueden pagar con SEPA Direct Debit. Actívalo en Configuración > Métodos de pago.

10 · Componente — Card

Contenedor de sección con header, body y footer opcionales. El footer siempre alinea acciones a la derecha.

Confirmar envío de recordatorio
Se enviará un email de recordatorio de pago a los clientes con facturas vencidas.
3 facturas vencidas seleccionadas
Total pendiente: 4.750,00 € · Clientes: Clínica Ortiz, Reparte SL, Moda Urban

12 · Accesibilidad WCAG 2.2 AA

Cada criterio es testeable en implementación. Sin excepciones estéticas que sacrifiquen accesibilidad.

CONTRASTE · MUST
Ratio mínimo 4.5:1 para texto normal, 3:1 para texto grande (>18px bold). color-text (#111827) sobre surface (#FFF) = 16.1:1 ✓. color-muted (#6B7280) sobre blanco = 4.63:1 ✓.
FOCUS VISIBLE · MUST
Todos los elementos interactivos deben tener un anillo de foco visible: box-shadow: 0 0 0 2px rgba(0,0,0,0.12). No usar outline: none sin reemplazo equivalente.
Estados de foco — demo
LABELS · MUST
Cada <input> debe tener un <label> asociado con for o aria-label. Nunca usar solo placeholder como label.
ROLES ARIA · MUST
Modales: role="dialog" aria-modal="true" aria-labelledby. Alerts: role="alert" para mensajes que aparecen dinámicamente.
KEYBOARD-FIRST · SHOULD
Modales deben atrapar el foco (focus trap) y cerrarse con Escape. Tablas con tabindex="0" en filas accionables.

13 · Anti-patterns prohibidos

Implementaciones incorrectas frecuentes en dashboards. Cada "no hacer" va acompañado de su alternativa correcta.

NO HACER
Color arbitrario sin token · label ambiguo · border-radius inconsistente
color: #7C3AED; /* valor hardcoded */
border-radius: 2px; /* fuera de escala */
HACER
Token semántico · label de acción · radio consistente
background: var(--color-primary);
border-radius: var(--radius-md);
NO HACER
<input placeholder="Email" />
/* sin label, sin aria */
Placeholder como único label → invisible en screen readers
HACER
<label for="email">Email</label>
<input id="email"
  placeholder="empresa@email.com"
  aria-describedby="email-hint" />

14 · QA Checklist — Code Review

Ejecutar en cada PR que modifique componentes o añada nueva UI. Bloquear merge si algún punto falla.

  • TOKENS
    Ningún valor de color hexadecimal hardcoded fuera de tokens.css. Buscar con grep -r "#[0-9A-Fa-f]{6}" en componentes.
  • TIPOGRAFÍA
    Solo tamaños de la escala (12/14/16/20/24/32px). No font-size: 13px ni font-size: 15px.
  • ESPACIADO
    Padding/margin/gap usan valores de la escala o múltiplos de 4px. Cero valores arbitrarios como padding: 7px 11px.
  • CONTRASTE
    Verificar con axe DevTools o Lighthouse. Ratio ≥ 4.5:1 en texto normal. Ningún warning abierto en WCAG AA.
  • KEYBOARD
    Navegar toda la vista nueva solo con Tab/Shift+Tab/Enter/Escape. Ningún elemento interactivo sin foco visible.
  • LABELS
    Cada <input> y <select> tiene label asociado. Cada icon-only button tiene aria-label.
  • ESTADOS
    Componentes interactivos implementan todos los estados requeridos: default, hover, focus, disabled. Loading state si la acción es asíncrona.
  • BADGES SEMÁNTICOS
    Cada Badge usa el token correcto para su significado (success=completado, warning=acción requerida, danger=error/urgente). Ningún color decorativo.
  • MODAL / DIALOG
    Incluye role="dialog", aria-modal="true", focus trap activo, cierre con Escape, botón de escape visible.
  • RESPONSIVE
    Vista validada en 1280px (desktop), 768px (tablet). Ningún overflow horizontal en contenedores principales.
Nota del sistema
Este documento es la fuente de verdad del sistema de diseño de NovaPay v1.0. Generado con la skill sistema-diseno-shadcn de CULTIVA IA (Branding & Diseño). Cualquier excepción a estas reglas requiere decisión documentada en el PR.