Módulo 8: Project Build Mercados Design System
Presentación del módulo: el capstone — el sistema de diseño de Mercado
Por qué este módulo existe aquí
Durante siete módulos construiste piezas. En el módulo 1 viste por qué un sistema de diseño existe —las capas tokens → utilidades → componentes → patrones, y el costo de no tenerlas—. En el 2 fabricaste los tokens de Mercado y los resolviste con resolveToken en dos temas. En el 3 vestiste el product-card con utilidades de Tailwind conectadas a esos tokens, y viste cómo tw() reconstruye su CSS. En el 4 construiste las escalas de espaciado, tipografía y color, y auditaste su contraste con el algoritmo real de WCAG. En el 5 empaquetaste esas utilidades en un Button con variantes —variant × size, resueltas por variants()—. En el 6 hiciste ese sistema responsive y dark, con una sola cadena de clases por resolveClasses. Y en el 7 viste que no todo hay que construirlo desde cero: las primitivas accesibles (el modelo shadcn/Radix) te dan el foco, los roles ARIA y el teclado resueltos, para que tú solo los vistas con tus tokens.
Siete piezas, siete módulos, cada uno verificado por separado. Lo que no hiciste todavía es tocarlas juntas, en el orden en que un sistema de diseño real se levanta: primero los cimientos, después lo que se apoya en ellos. Eso es este módulo. No es una lección más de un tema nuevo —es el recorrido de vuelta por las siete capas, en su orden real, hasta llegar al storefront completo de Mercado: tokens, después utilidades, después contraste verificado, después componentes con variantes, después responsive y dark, después primitivas accesibles. Un solo método, aplicado de punta a punta.
Conexión con el módulo. Esta lección no enseña una pieza nueva; instala la tesis del capstone —las siete capas anteriores son, en realidad, un solo método, no siete temas sueltos— y traza el mapa de las seis lecciones que arman el sistema por capas más la lección final que lo entrega completo. Cada lección de este módulo integra uno o dos módulos anteriores y ejecuta de nuevo su modelo en Node, esta vez sobre el sistema final y completo de Mercado, no sobre un fragmento aislado.
Una analogía: la orquesta que ensayó por secciones y ahora toca la sinfonía completa
Piensa en una orquesta preparando una sinfonía. Durante las primeras semanas de ensayo, cada sección practica por separado: las cuerdas ensayan su parte sin los vientos, los vientos sin la percusión, cada músico afinando su instrumento contra un diapasón compartido. Ensayar por secciones tiene una ventaja enorme —si el violín desafina, se corrige ahí, sin que catorce instrumentos más estén sonando encima para confundir el oído—. Pero una orquesta que solo ensayó por secciones no ha tocado la sinfonía. La sinfonía existe cuando las cuerdas entran en el compás 40 justo cuando los vientos bajan el volumen, cuando la percusión marca el pulso que todos los demás siguen sin mirarse. Esa coordinación —quién entra cuándo, quién cede el paso a quién— es una habilidad distinta de tocar bien el propio instrumento, y solo se prueba en el ensayo general completo.
Los módulos 2 a 7 fueron tus ensayos por sección. El módulo 2 afinó los tokens contra el diapasón de las tres capas. El 3 ensayó las utilidades. El 4, la sección de escalas y contraste. El 5, los componentes con variantes. El 6, responsive y dark. El 7, las primitivas accesibles. Cada uno sonó bien por separado, verificado con su propio proyecto. Este módulo es el ensayo general: la sinfonía completa, de la primera nota a la última, con las siete secciones entrando en su compás —los tokens primero (sin ellos no hay de dónde sacar un color), las utilidades leyéndolos, el contraste verificando que lo que las utilidades pintan se lee, los componentes empaquetando esas utilidades en algo reutilizable, responsive y dark hilando esas variantes con el tamaño y el tema, y las primitivas resolviendo la accesibilidad que ningún módulo anterior tocó a fondo—. Al final de este módulo no solo sabes tocar cada instrumento: sabes tocar la pieza completa, del primer compás al último.
El mapa del módulo
Lección Capa que arma Módulos que integra Modelo Node que ejecuta
──────── ───────────────────────────────────── ─────────────────── ──────────────────────────
L1 (esta) el método completo, de vuelta M1–M7 —
L2 los tokens finales de Mercado M2 resolveToken (light/dark)
L3 la config de Tailwind + el CSS real M3 tw() con colorMap
L4 la auditoría de contraste M4 contrastRatio + passesWCAG
L5 el Button y el ProductCard con M5 variants()
variantes
L6 responsive + dark, sin duplicar M6 resolveClasses
L7 primitivas accesibles (Dialog) M7 a11yAudit
──────── ───────────────────────────────────── ─────────────────── ──────────────────────────
L8 el entregable: TODO el sistema M1–M7 la corrida end-to-end
corriendo de punta a punta
Fíjate en el orden: no es alfabético ni arbitrario, es el orden de dependencia real. No puedes auditar contraste (L4) antes de tener tokens (L2) y saber cómo se emiten a CSS (L3) —¿contraste de qué colores?—. No puedes construir un Button con variantes (L5) que use bg-primary antes de que bg-primary exista como utilidad conectada a un token. No puedes hacerlo responsive y dark (L6) antes de que tenga clases que responder. Y las primitivas accesibles (L7) visten con tus tokens un componente sin estilo —necesitan que los tokens ya existan—. Cada lección se apoya en la anterior; es la misma cadena de capas del módulo 1 (tokens → utilidades → componentes → patrones), ahora recorrida con las manos.
Qué vas a entregar
Al final de la lección 8 vas a tener, en un solo lugar, el sistema de diseño completo del storefront de Mercado:
- Los tokens (
tokens.js): primitivos, semánticos y de componente, con override de tema, incluyendo dos que vas a descubrir que hacen falta en la lección 4 —color.on-primaryycolor.on-danger— cuando la auditoría de contraste encuentre que un color de texto fijo no sobrevive a los dos temas. - La config de Tailwind (
tailwind.config.js) con uncolorMapque traduce cada utilidad de color a su custom property —la pieza que completa eltw()del módulo 3—. - El
Buttony elProductCardcomo componentes con variantes (variants()), reutilizando el mismo motor para dos componentes distintos. - El catálogo responsive y dark, con
resolveClassesdemostrando que una sola cadena cubre tres anchos y dos temas. - Un
Dialogde "vista rápida" montado sobre una primitiva accesible (el patrón Radix del módulo 7), auditado contra uno construido a mano. - La corrida end-to-end: un solo script de Node que encadena las seis capas —tokens → utilidades → contraste → variantes → responsive/dark → primitivas— sobre el sistema completo, con salida literal.
Nada de esto es código nuevo por descubrir: son los mismos seis modelos que ya ejecutaste (resolveToken, tw, contrastRatio, variants, resolveClasses, y el a11yAudit que instala este módulo para las primitivas). Lo nuevo es verlos encadenados, cada uno recibiendo lo que el anterior produjo.
La frontera: qué NO entra en este módulo
- No se re-explica ningún módulo desde cero. Si
resolveToken,tw(),contrastRatio,variants()oresolveClasseste resultan nuevos, este no es el punto de entrada — repasa el módulo correspondiente (2 a 6) antes de seguir. Aquí se usan, no se enseñan por primera vez. - No se construye una nueva primitiva desde cero. El
Dialogde la lección 7 usa el modelo Radix del módulo 7; aquí no se re-explica cómo Radix resuelve el foco por debajo, solo se verifica cona11yAudit. - No entra Next.js, estado global, ni performance/deploy. Esas son las guías hermanas que vienen después de esta —
nextjs-app-router-guide,frontend-state-and-data-guide,fullstack-performance-and-deployment-guide— y la lección 8 cierra apuntando hacia ellas. - No entra ARIA a fondo. El
a11yAuditde este módulo verifica un checklist fijo de siete requisitos de unDialog; auditorías de accesibilidad más completas (lectores de pantalla, todo el spec ARIA) quedan fuera del alcance de esta guía.
Ejercicios
Ejercicio 1 — Ordena la cadena de dependencia. Sin mirar el mapa de arriba, ordena estos cinco pasos según qué necesita a qué (el primero no depende de ningún otro; el último depende de todos los anteriores):
- (a) Verificar que el texto del
Buttonse lee sobre su fondo. - (b) Definir
color.primarycomo token semántico. - (c) Escribir
bg-primaryen el JSX delButton. - (d) Resolver qué clases de
variant="primary"incluyenbg-primary. - (e) Configurar Tailwind para que
bg-primaryapunte avar(--color-primary).
Ver solución
El orden correcto es (b) → (e) → (c) → (d) → (a).
Primero existe el token (b) —sin un color.primary no hay nada que apuntar—. Después la config de Tailwind (e) lo conecta a una utilidad —sin esa conexión, bg-primary sería un nombre sin significado—. Recién ahí tiene sentido escribir la clase en el JSX (c). El motor de variantes (d) decide cuándo esa clase entra en la cadena resuelta —necesita que la clase ya exista para incluirla—. Y solo al final, con un color real resuelto y aplicado, tiene sentido auditar el contraste (a) —no puedes medir el contraste de un color que todavía no se resolvió—. Es la misma cadena tokens → utilidades → componentes → verificación que estructura las lecciones 2 a 4 de este módulo.
Ejercicio 2 — Identifica el módulo dueño. Para cada síntoma, di qué módulo (2–7) tiene el modelo que lo detecta o resuelve:
- (a) "El botón se ve bien en modo claro pero el texto casi desaparece en modo oscuro."
- (b) "El catálogo se ve perfecto en desktop pero en el teléfono las tarjetas se aprietan en cuatro columnas ilegibles."
- (c) "Cada vez que se agrega un botón nuevo, alguien copia clases de Tailwind sueltas y el resultado nunca es idéntico al anterior."
- (d) "El modal de 'agregar al carrito' no se cierra con Escape, y si haces Tab el foco se escapa hacia el fondo de la página."
Ver solución
- (a) Módulo 4 (contraste):
contrastRatiomide exactamente esto —un color que pasa en un tema y falla en el otro—. - (b) Módulo 6 (responsive + dark):
resolveClasseses el modelo que decide cuántas columnas quedan activas por ancho. - (c) Módulo 5 (componentes con variantes): el síntoma es la ausencia de un
Buttonconvariants()—cada copia suelta es drift que un componente centralizado elimina—. - (d) Módulo 7 (primitivas accesibles): foco, teclado y Escape son justo lo que una primitiva como el
Dialogde Radix resuelve, y lo que este módulo audita cona11yAuditen la lección 7.
La pregunta guía de este ejercicio es la que vas a hacerte en cada lección del capstone: cuando algo falla, ¿qué capa —de las siete— es la responsable, y qué modelo de esa capa lo prueba?
Ejercicio 3 — Verdadero o falso. Para cada afirmación sobre este módulo, di si es verdadera o falsa y por qué:
- (a) "El capstone enseña conceptos nuevos que los módulos 2 a 7 no cubrieron."
- (b) "El orden de las lecciones 2 a 7 (tokens → utilidades → contraste → variantes → responsive/dark → primitivas) es el mismo orden en que un sistema de diseño real se construye."
- (c) "La lección 8 es solo un resumen en prosa de lo que ya se vio; no agrega una corrida ejecutada nueva."
Ver solución
- (a) Falsa. El capstone no introduce conceptos nuevos —reutiliza exactamente los modelos de los módulos 2 a 7—. Lo que es nuevo es verlos encadenados sobre el sistema completo de Mercado, no fragmentos aislados.
- (b) Verdadera. Es el orden de dependencia real: tokens antes que utilidades (nada que apuntar sin token), utilidades antes que contraste (nada que medir sin color resuelto), contraste antes de confiar en un componente, componentes antes de hacerlos responsive/dark, y tokens ya resueltos antes de vestir una primitiva con ellos.
- (c) Falsa. La lección 8 corre un script de Node que encadena las seis capas en una sola ejecución sobre el sistema completo —tokens,
tw(), contraste, variantes, responsive/dark ya11yAudit, todos en la misma corrida—, con salida literal nueva, no una repetición de las salidas de las lecciones anteriores.
Resumen y siguiente paso
En esta lección instalaste la tesis del capstone: los módulos 2 a 7 no fueron siete temas sueltos — son un solo método, con un orden de dependencia real, y este módulo lo recorre completo sobre el sistema de diseño de Mercado. Con la orquesta que ensayó por secciones y ahora toca la sinfonía completa viste por qué separar el aprendizaje en capas (para poder afinar cada una sin ruido) es distinto de tocarlas juntas (que es donde el sistema realmente se prueba). Y viste el mapa completo: seis lecciones que arman el sistema capa por capa, cada una ejecutando de nuevo su modelo sobre Mercado, y una lección final que entrega todo junto con una corrida end-to-end.
Antes de avanzar deberías poder: nombrar las siete capas en su orden de dependencia (tokens → utilidades → escalas/contraste → componentes con variantes → responsive/dark → primitivas accesibles); explicar por qué ese orden no es arbitrario; y ubicar qué modelo de Node corresponde a cada capa (resolveToken, tw, contrastRatio, variants, resolveClasses, a11yAudit).
La lección 2 empieza donde todo sistema empieza: los tokens. Vas a definir el set final de Mercado —los mismos primitivos y semánticos del módulo 2, más dos tokens nuevos que la auditoría de la lección 4 va a justificar— y a resolverlos con resolveToken en los dos temas, como el primer cimiento sobre el que se apoya cada lección que sigue.
Recursos
- W3C Design Tokens Community Group — design-tokens.github.io/community-group. El estándar detrás de la capa de tokens que vas a fijar en la lección 2. En inglés.
- Tailwind CSS, documentación completa — tailwindcss.com/docs. El punto de referencia para toda la capa de utilidades y configuración que este módulo integra. En inglés.
- WCAG 2.1, "Contrast (Minimum)" — w3.org/WAI/WCAG21/Understanding/contrast-minimum.html. El umbral que la auditoría de la lección 4 aplica sobre el sistema completo. En inglés.
- cva (
class-variance-authority) — cva.style/docs. El motor de variantes detrás delButtony elProductCardde la lección 5. En inglés. - Radix Primitives — radix-ui.com/primitives. La base del
Dialogaccesible que audita la lección 7. En inglés.