▪ Design System Expresivo

Hooka Design
System

Sistema de diseño listo para ingeniería. Tokens, componentes, estados, accesibilidad WCAG 2.2 AA y checklist de QA. Stack: React + Tailwind CSS.

Versión 1.0.0
Tipografía IBM Plex Mono
Accesibilidad WCAG 2.2 AA
Contexto SaaS B2B Outreach
00

Contexto e intención de diseño

Hooka es una plataforma de automatización de outreach para equipos B2B. El sistema de diseño debe transmitir energía y precisión técnica — una interfaz que se siente rápida, confiable y moderna. IBM Plex Mono como fuente principal refuerza la identidad técnica y monoespaciada. La paleta centrada en el rosa intenso (#db2777) crea diferenciación en el mercado SaaS gris.

01

Tokens de color

Usar siempre tokens semánticos, nunca valores hexadecimales en componentes. Los tokens son la fuente única de verdad.

--color-primary
#db2777
CTA, acciones primarias, enfoque
--color-primary-hover
#be185d
Estado hover del primario
--color-secondary
#2563eb
Acciones secundarias, enlaces
--color-success
#16a34a
Estados activos, confirmación
--color-warning
#d97706
Advertencias, pausado
--color-danger
#dc2626
Errores, acciones destructivas
--color-text
#111827
Texto principal (modo claro)
--color-text-muted
#6b7280
Labels, metadatos, hints
02

Escala tipográfica

IBM Plex Mono en todos los niveles. La escala monoespaciada refuerza la identidad técnica. Usar siempre los tokens de tamaño, nunca px directos en componentes.

--text-3xl 40px / Bold 700
Display, H1
Hooka
--text-2xl 32px / Bold 700
H2, hero sections
Campañas activas
--text-xl 24px / Semibold 600
H3, section titles
LinkedIn Outreach Q2
--text-lg 18px / Semibold 600
H4, card titles
Secuencia de seguimiento
--text-base 16px / Regular 400
Body text, párrafos
Esta campaña ha alcanzado 1.240 prospectos en los últimos 30 días.
--text-sm 14px / Regular 400
Labels, botones, inputs
Tasa de apertura · Respuestas · Conversiones
--text-xs 12px / Semibold 600
Badges, meta, microcopy
CAMPAÑA ACTIVA · SECUENCIA 3 DE 5
03

Escala de espaciado

Base 4px. Seis pasos semánticos. Nunca usar valores intermedios no definidos en la escala.

--space-1 4px
Separación mínima, íconos
--space-2 8px
Gap entre elementos inline
--space-3 12px
Padding input, microbloques
--space-4 16px
Padding card, gap columnas
--space-6 24px
Separación de secciones
--space-8 32px
Padding de página, headers
04

Botones

El botón es el elemento de acción principal. Cada variante tiene un uso semántico concreto — no combinar colores por estética.

Variantes 4 tipos
Cuándo usar cada variante
primary — 1 sola por pantalla. CTA principal de la vista.
secondary — Acciones secundarias que complementan el CTA.
ghost — Cancelar, descartar, navegación sin peso visual.
danger — Solo para acciones destructivas irreversibles.
Reglas de implementación
must — Incluir aria-label si el texto solo es ícono.
must — Estado :focus-visible visible a 3px de ring.
mustaria-disabled + disabled juntos cuando inactivo.
should — Añadir spinner + aria-busy="true" en loading.
Tamaños 3 tallas
Cuándo usar cada tamaño
sm 6/14px — Acciones dentro de tablas, filas densas.
md 10/20px — Tamaño por defecto. 95% de los casos.
lg 14/28px — Hero sections, CTAs de onboarding.
Área de toque mínima
must — 44×44px mínimo en móvil (WCAG 2.5.5).
must — No usar btn-sm en interfaces táctiles.
05

Inputs de texto

Los campos de formulario siguen una anatomía fija: label + input + hint. Nunca omitir el label visible.

Estados de campo 5 estados
Será visible solo para tu equipo.
Max. 60 caracteres recomendados.
⚠ Introduce un email válido.
Dominio verificado correctamente.
Disponible en plan Growth.
Anatomía del campo
label — Siempre visible. Nunca solo placeholder. for vinculado al id.
input — Border 1.5px. Focus ring 3px rgba(219,39,119,0.18).
hint — Mensaje de ayuda, error o éxito. Asociado con aria-describedby.
Reglas de implementación
mustaria-invalid="true" en estado error.
mustaria-describedby apuntando al hint en todos los estados.
must — Contraste del placeholder ≥ 3:1 (WCAG 1.4.3).
should — Icono de estado dentro del campo, no exterior.
06

Badges de estado

Las etiquetas de estado comunican el ciclo de vida de las campañas. Son solo informativas — nunca usar como botones.

Estados de campaña 5 variantes
Activa Pausada Error Borrador Nueva
Semántica de colores
Activa — Verde #16a34a. Campaña en ejecución.
Pausada — Ámbar #d97706. Detenida manualmente.
Error — Rojo #dc2626. Requiere atención urgente.
Borrador — Gris neutro. No publicada aún.
Nueva — Primario rosa. Creada hace menos de 24h.
Reglas de implementación
must — No comunicar estado solo por color (WCAG 1.4.1). Incluir texto.
must — Añadir role="status" si cambia dinámicamente.
must — El punto parpadeante de "Activa" debe respetar prefers-reduced-motion.
don't — No usar badge como botón clickeable (usar chip separado).
07

Card de campaña

La card es la unidad de información primaria del dashboard. Contiene estado, métricas clave y acciones contextuales.

Card — variante dashboard estado activo
Campaña LinkedIn
Q3 SaaS Founders
Activa
1.240
Prospectos
34%
Apertura
48
Respuestas
Progreso de secuencia 3 de 5 pasos
Email Outreach
Webinar SaaS Dic
Error
⚠ Límite de envíos diarios alcanzado
La campaña se reanudará mañana a las 09:00. Revisa la configuración de tu proveedor de email.
620
Prospectos
18%
Apertura
9
Respuestas
Anatomía de la card
header — Título + badge de estado. Fondo ligeramente diferenciado.
body — Métricas en grid 3col + barra de progreso o alerta.
footer — Timestamp + acciones contextuales (icon-btn).
Reglas de implementación
must — El contenedor card debe tener role="article" o ser un <article>.
must — Todos los icon-btn deben tener aria-label descriptivo.
must — Hover: elevar border-color con alpha primario + shadow.
should — Estado de error cambia el border-color de la card completa.
08

Accesibilidad WCAG 2.2 AA

Criterios de aceptación testables. Cada punto debe verificarse en code review antes de merge.

Contraste de color
Texto normal: ratio mínimo 4.5:1 sobre surface.
Texto grande (+18px bold): ratio mínimo 3:1.
#db2777 sobre blanco = 4.6:1 (pasa AA).
Placeholder text: mínimo 3:1 (WCAG 1.4.3).
Texto muted (#6b7280) sobre blanco = 4.6:1. En dark usar #9ca3af.
Navegación por teclado
Todos los elementos interactivos alcanzables con Tab.
Focus visible: ring 3px var(--color-focus-ring), offset 2px.
Botones: activables con Enter y Space.
Menús: navegables con flechas, Esc cierra.
Tab order debe seguir el orden visual. Nunca tabindex > 0.
ARIA y semántica
Usar elementos HTML nativos cuando sea posible.
aria-label obligatorio en icon-buttons.
aria-live="polite" para cambios de estado dinámicos.
role="status" en badges que cambian en tiempo real.
aria-describedby vincula hints de error a inputs.
Movimiento y animación
Respetar prefers-reduced-motion en todas las animaciones.
Animaciones decorativas: @media (prefers-reduced-motion: reduce).
Spinner de carga: animación CSS en lugar de GIF.
El punto parpadeante del badge activo debe detenerse si el usuario prefiere menos movimiento.
09

Anti-patrones prohibidos

Implementaciones que deben rechazarse en code review. Cada anti-patrón incluye la alternativa correcta.

✖ Incorrecto
Botón sin fuente del sistema

Usar font-family: Arial o estilos del navegador en lugar de var(--font-primary).

El botón rompe la coherencia tipográfica y los tests de screenshot.

✔ Correcto
Botón con token de fuente

Siempre font-family: var(--font-primary) y tamaño desde tokens.

Fuente consistente. Tamaño desde --text-sm. Border-radius desde --radius-md.

✖ Incorrecto
Color solo para comunicar estado

Badge con color rojo pero sin texto de estado — falla WCAG 1.4.1.

Usuarios con daltonismo no pueden distinguir el estado.

✔ Correcto
Color + texto en el badge

Siempre combinar indicador de color con texto descriptivo explícito.

Error

El texto "Error" es suficiente sin depender del color.

✖ Incorrecto
Input sin label visible

Usar solo placeholder como label — desaparece al escribir, invisible para lectores de pantalla.

✔ Correcto
Input con label + placeholder

Label visible siempre presente. Placeholder es ayuda opcional, no sustituto.

10

QA Checklist

Ejecutar antes de cada merge que afecte componentes UI. Todos los items deben estar marcados.

△ Tokens y fundamentos
Todos los colores usan variables CSS (var(--color-*)), sin hex directos.
Toda tipografía usa tokens de tamaño (var(--text-*)).
Spacing usa la escala de 4px (var(--space-*)).
IBM Plex Mono cargada correctamente en todos los breakpoints.
Border-radius utiliza tokens (var(--radius-*)).
✗ Componentes — Botones
Solo 1 btn-primary por vista/modal.
Estado hover visible y diferenciado del default.
Estado focus-visible: ring 3px, offset 2px, color primario.
Estado disabled: opacidad 0.38, cursor not-allowed.
Estado loading: spinner + aria-busy="true" + pointer-events:none.
Área de toque mínima 44px en mobile.
◯ Componentes — Inputs
Label visible asociado con for/id.
Hint de error asociado con aria-describedby.
aria-invalid="true" en estado error.
Contraste del placeholder ≥ 3:1.
Estado disabled no editable ni navegable por teclado.
◈ Accesibilidad general
Contraste de texto ≥ 4.5:1 (herramienta: axe DevTools).
Todo el flujo navegable solo con teclado.
Screen reader (VoiceOver/NVDA) anuncia correctamente los cambios de estado.
Animaciones respetan prefers-reduced-motion.
No hay información comunicada solo por color.
Icon-buttons tienen aria-label descriptivo.