Estándares, ratios de contraste, patrones de foco, navegación por teclado y buenas prácticas para que cada pieza de Flow sea usable por todas las personas.
Flow sigue WCAG 2.1 nivel AA como estándar mínimo. El objetivo: cero barreras para el 100% de los usuarios.
Toda la información y los componentes de la interfaz se presentan de manera que los usuarios puedan percibirlos — visual, auditiva o táctilmente.
Todos los componentes de navegación e interacción son operables mediante teclado, ratón, pantalla táctil y tecnologías asistivas.
La información y la operación de la interfaz son comprensibles — lenguaje claro, comportamiento predecible, ayuda contextual.
El contenido es lo suficientemente robusto para ser interpretado por una variedad de agentes de usuario, incluidos lectores de pantalla.
Todos los deliverables de Flow — web, presentaciones, documentos, landing pages — deben cumplir al menos el nivel AA. Donde sea viable, apuntamos a AAA para ratios de contraste de texto.
Auditoría completa de las combinaciones de color de Flow contra los criterios WCAG 2.1.
Combinaciones principales del modo claro contra surface.primary (#f7f5f3).
Combinaciones sobre surface.inverse (#0f2c24).
Green-500 (#3beb64) nunca como texto sobre fondo claro. Ratio 2.2:1 — falla todos los niveles WCAG. Usarlo solo como background de botón, borde activo o indicador decorativo.
Tertiary (#9faba7) solo como placeholder o texto deshabilitado en modo claro. Ratio 2.5:1 — no cumple para contenido informativo. Aceptable para hints decorativos con contexto adicional.
Warning (#f0a730) requiere siempre ícono acompañante. Ratio 2.4:1 — no confiar solo en el color para comunicar la advertencia.
Error (#e84545) usar en bold (≥18px) o acompañar con ícono. Pasa AA Large pero no AA Normal.
Los componentes UI y gráficos requieren un mínimo de 3:1 contra el fondo adyacente.
| Componente | Color | Fondo | Ratio | Estado |
|---|---|---|---|---|
| Botón primario | #3beb64 |
#f7f5f3 |
2.2:1 | ✗ Requiere borde |
| Borde de input | #cfd5d3 |
#f7f5f3 |
1.4:1 | ✗ Requiere label visible |
| Input focus ring | #3beb64 |
#f7f5f3 |
2.2:1 | ✓ + box-shadow visible |
| Checkbox marcado | #2fd954 |
#f7f5f3 |
2.3:1 | ✗ Requiere marca interior (✓) |
| Charcoal borde botón | #0f2c24 |
#f7f5f3 |
14.7:1 | ✓ Excelente |
El botón primario (green-500 background) tiene texto charcoal que ofrece 6.7:1 de contraste interno. El botón como unidad es distinguible por su forma, sombra y label. Esto cumple WCAG 1.4.11 a través de múltiples indicadores visuales.
Indicadores de foco claros y consistentes para todos los elementos interactivos.
| Contexto | Outline | Offset | Color |
|---|---|---|---|
| Botón primario (fondo verde) | 3px solid |
3px |
charcoal — contraste con verde |
| Botón secundario / ghost | 3px solid |
3px |
green-500 |
| Links de texto | 3px solid |
3px |
green-500 |
| Inputs | border-color: green-500 + box-shadow: 0 0 0 3px rgba(59,235,100,0.12) |
||
| Sobre fondo oscuro | 3px solid |
3px |
green-500 — alta visibilidad sobre charcoal |
Presiona Tab para ver los indicadores de foco en acción.
:focus-visible para focus de tecladooutline: none globalmente:focus con :focus-visibleCada componente interactivo debe ser completamente operable sin ratón.
| Componente | Tecla | Acción |
|---|---|---|
| Botón | Tab | Navegar al botón |
| Enter | Activar el botón | |
| Space | Activar el botón | |
| Modal | Esc | Cerrar modal |
| Tab | Ciclar foco dentro del modal (focus trap) | |
| Shift+Tab | Ciclar foco en reversa | |
| Dropdown / Select | ↑ ↓ | Navegar opciones |
| Enter | Seleccionar opción activa | |
| Esc | Cerrar dropdown | |
| Tabs | ← → | Cambiar entre tabs |
| Tab | Mover foco al contenido del tab activo | |
| Toggle / Switch | Space | Cambiar estado on/off |
| Enter | Cambiar estado on/off | |
| Tooltip | Tab (al trigger) | Mostrar tooltip |
| Esc | Ocultar tooltip | |
| Toast | Tab | Navegar a acción del toast (si la hay) |
| Esc | Descartar toast |
El orden de tabulación debe seguir el flujo visual del contenido. Nunca usar tabindex mayor a 0. Usar solo tabindex="0" (orden natural) o tabindex="-1" (removible del flujo, enfocable por JS).
Estructura correcta para lectores de pantalla y SEO.
<h1> por página| Elemento HTML | Rol implícito | Cuándo usar |
|---|---|---|
<button> |
button |
Acciones en la página (no navegación) |
<a href> |
link |
Navegación a otra página o sección |
<nav> |
navigation |
Grupos de enlaces de navegación |
<main> |
main |
Contenido principal (1 por página) |
<ul> / <ol> |
list |
Listas de ítems (lectores anuncian conteo) |
<img alt="..."> |
img |
Imágenes con texto alternativo obligatorio |
<table> |
table |
Datos tabulares (nunca para layout) |
Siempre preferir el elemento HTML nativo sobre role="...". Un <button> ya tiene el role, los listeners de teclado, y el estado accesible. Un <div role="button"> requiere recrear todo manualmente.
Atributos ARIA esenciales para componentes de Flow.
| Componente | Atributos ARIA | Notas |
|---|---|---|
| Modal | role="dialog", aria-modal="true", aria-labelledby |
Referenciar el título con aria-labelledby |
| Dropdown | aria-expanded, aria-haspopup="listbox", aria-controls |
Actualizar expanded al abrir/cerrar |
| Tabs | role="tablist", role="tab", role="tabpanel", aria-selected |
Un solo tab con aria-selected="true" |
| Toggle | role="switch", aria-checked |
Actualizar checked al cambiar |
| Toast | role="status", aria-live="polite" |
Polite para info, assertive para errores |
| Tooltip | role="tooltip", aria-describedby |
Vincular trigger con describedby |
| Loading | aria-busy="true", aria-live="polite" |
Anunciar cuando termine la carga |
| Accordion | aria-expanded, aria-controls |
El trigger indica si está abierto/cerrado |
| Valor | Comportamiento | Usar para |
|---|---|---|
polite |
Espera a que el lector termine de hablar | Toasts informativos, actualizaciones de estado, contadores |
assertive |
Interrumpe inmediatamente | Errores críticos, alertas de seguridad, validaciones de formulario |
off |
No se anuncia | Contenido que cambia frecuentemente (ticker, reloj) |
Labels, errores, y patrones de validación que funcionan para todos.
<label for="id"> visiblearia-describedbyaria-invalid="true"aria-required="true" + indicador visual (*)<fieldset> + <legend>Respetar la preferencia del sistema operativo del usuario. Referencia completa: motion-guide.html § 8.
prefers-reduced-motion siempreImágenes, multimedia, y contenido textual para todos.
| Tipo de Imagen | Alt Text | Ejemplo |
|---|---|---|
| Informativa | Descripción concisa del contenido | alt="Equipo de Flow en sesión de diseño colaborativo" |
| Decorativa | Alt vacío | alt="" + role="presentation" |
| Funcional (botón/link) | Describir la acción, no la imagen | alt="Cerrar modal" no alt="Ícono de X" |
| Compleja (gráfico/datos) | Resumen breve + descripción larga | alt="Crecimiento Q1-Q4" + aria-describedby="chart-desc" |
| Texto como imagen | Reproducir el texto exacto | alt="Flow Collective Studio" |
Flow usa Lucide Icons (stroke 1.5px). Reglas:
Lista de verificación obligatoria antes de entregar cualquier deliverable de Flow.
<th scope> y <caption>lang="es" en el HTMLaria-invalid + aria-describedbyaria-requiredalt=""aria-labelprefers-reduced-motionAutomatizadas: axe DevTools, Lighthouse Accessibility, WAVE, Pa11y
Manual: Navegar con Tab, probar con VoiceOver (Mac) / NVDA (Windows), verificar zoom 200%
Contraste: WebAIM Contrast Checker, Colour Contrast Analyser (CCA)