Módulo 1: What A Design System Is
Presentación del módulo: qué es un sistema de diseño
Por qué este módulo existe aquí
Ya sabes escribir CSS a mano —lo aprendiste en web-fundamentals-html-css: el box model, la cascada, Flexbox, Grid, el diseño responsivo— y ya sabes construir componentes que reciben props —lo aprendiste en react-fundamentals—. Con esas dos habilidades puedes hacer que cualquier pantalla se vea como quieras. Y aquí está el problema que esta guía viene a resolver: hacer que una pantalla se vea bien no es lo mismo que hacer que veinte pantallas se vean coherentes entre sí, y que sigan coherentes seis meses después, con tres personas tocándolas. Eso último no se logra escribiendo más CSS; se logra escribiendo CSS de otra forma: como un sistema.
Este módulo es el mapa mental de esa forma. No enseña todavía la mecánica —los tokens son el módulo 2, Tailwind el 3, las escalas y el contraste el 4, las variantes el 5—; enseña qué problema resuelve un sistema de diseño y de qué piezas se compone. Es la lección-mapa: si entiendes bien por qué existe un sistema y cuáles son sus capas, todo lo mecánico que viene después encaja en su lugar en vez de sentirse como una pila de trucos sueltos.
Vamos con la forma en que casi todo el mundo escribe estilos al principio, para que el contraste se sienta. Necesitas un botón azul, así que lo escribes:
.btn {
background: #3b82f6;
padding: 12px 16px;
border-radius: 8px;
font-size: 16px;
}
Se ve bien. Funciona. Al día siguiente necesitas otro botón en otra pantalla, no encuentras el anterior, y lo vuelves a escribir —de memoria—:
.button-primary {
background: #3c83f6; /* casi el mismo azul... pero no */
padding: 10px 16px; /* casi el mismo padding... pero no */
border-radius: 6px; /* casi el mismo radio... pero no */
font-size: 15px; /* casi la misma tipografía... pero no */
}
Cada botón, por sí solo, se ve perfecto. Pero puestos lado a lado no son el mismo botón: uno es un poco más azul, otro un poco más chico, otro con la esquina un poco menos redondeada. Nadie lo decidió; simplemente pasó, porque cada valor se escribió a mano, de memoria, en un momento distinto. A esa divergencia silenciosa —que nadie eligió y que se acumula— se le llama drift, y es la enfermedad que un sistema de diseño previene. La tesis del módulo se resume en una frase:
Un sistema de diseño reemplaza mil decisiones ad-hoc
por unas pocas decisiones tomadas una vez.
Léela con calma. La palabra clave es una vez. En un sistema, "el azul de marca" se decide una sola vez, se le pone un nombre (color.primary), y de ahí en adelante todas las pantallas lo referencian en vez de re-escribirlo. Lo mismo con el espaciado, con la tipografía, con los radios, con el botón entero. La coherencia deja de ser un acto de disciplina —"acuérdate de usar el mismo azul"— y pasa a ser una propiedad estructural: es coherente porque, físicamente, sale del mismo lugar.
Conexión con el módulo. Esta es la lección-mapa: no entramos a fondo en ninguna pieza todavía, sino que instalamos la tesis (un sistema reemplaza decisiones ad-hoc por decisiones nombradas), presentamos el caso (el sistema de diseño del storefront de Mercado), y damos el mapa de las cuatro capas. La lección 2 muestra el salto de CSS ad-hoc a un sistema. La 3 presenta las cuatro capas (tokens → utilidades → componentes → patrones), la columna vertebral de toda la guía. La 4 mide el costo del drift y por qué la consistencia importa. La 5 conecta el sistema con la mantenibilidad (una única fuente de verdad). La 6 muestra la accesibilidad como propiedad del sistema —algo que se garantiza una vez y vale para todo—. La 7 arma la anatomía completa del sistema de Mercado. Y la 8 te pone a hacer su inventario. Todo el módulo se para sobre esta única idea: sistema, no decisiones sueltas. Si la interiorizas aquí, el resto de la guía encaja solo.
Y una promesa que se cumple en todo el módulo: nada se cita de memoria, todo se comprueba. El navegador y Tailwind no corren dentro de un agente, así que hacemos lo honesto: el CSS, las clases de Tailwind y el JSX real —el que tú escribirás— se muestran en los bloques de código, y la lógica del sistema se ejecuta en Node, con solo JavaScript, sin instalar nada. Verás funciones cortas —un modelo de drift, un inventario del sistema— que cuentan cosas concretas: cuántos valores distintos hay para un mismo rol, cuántas piezas tiene cada capa. Cada salida que aparezca en un bloque "Qué esperar" es la salida literal de correr ese código con Node 18. Puedes copiarlo y reproducirlo idéntico.
Una analogía: el juego de LEGO contra tallar cada pieza a mano
Imagina que tienes que construir un castillo de juguete, y te dan dos opciones.
La primera es un bloque de madera, un cuchillo y una lija. Cada muro, cada torre, cada ventana la tallas tú, a mano, mirando la anterior para que "más o menos" combine. La primera pieza sale hermosa. La segunda, casi igual —pero un milímetro más gruesa—. La décima ya no encaja del todo con la primera. Y cuando decides que todo el castillo debería ser un poco más alto, no hay un botón para eso: hay que volver a tallar, pieza por pieza, y rezar para que no se te olvide ninguna. Ese es el CSS ad-hoc: cada pieza tallada a mano, hermosa en aislamiento, divergente en conjunto, imposible de cambiar de golpe.
La segunda es una caja de LEGO. Las piezas ya vienen fabricadas con medidas estándar: todos los bloques de 2×4 son idénticos, todos los conectores encajan, todos los colores salen de una paleta fija. No tallas nada; compones con piezas que garantizan encajar. El castillo se ve coherente no porque tú tuvieras buen pulso, sino porque las piezas no pueden divergir: son las mismas. Y si mañana quieres cambiar todos los bloques rojos por azules, cambias la caja de rojos por una de azules y listo. Eso es un sistema de diseño: piezas estándar que garantizan encajar, y que se cambian de golpe desde un solo lugar.
La analogía tiene tres consecuencias que son, tal cual, por qué importa un sistema.
Las piezas estándar no limitan; liberan. Podría parecer que tallar a mano da más libertad —"puedo hacer cualquier forma"—. Pero en la práctica esa libertad se gasta en re-decidir cosas triviales una y otra vez ("¿qué azul era?", "¿cuánto padding le puse?"). Con LEGO, no piensas en la pieza; piensas en el castillo. Un sistema de diseño te libera de re-decidir el azul cada vez, para que gastes tu atención en lo que de verdad importa: qué construyes, no de qué milímetro es cada ladrillo.
La coherencia es una propiedad de las piezas, no de tu memoria. El castillo de LEGO se ve armónico aunque lo arme un niño distraído, porque la armonía está en las piezas. En un sistema de diseño, la consistencia no depende de que cada programador recuerde el valor correcto: depende de que todos usen la misma pieza. Sacas el error humano de la ecuación.
Cambiar todo de golpe solo es posible si hay un "todo". No puedes "cambiar todos los rojos" si cada rojo es un tallado único ligeramente distinto. Solo puedes cambiar de golpe lo que sale de un mismo lugar. Un sistema crea ese lugar único —el token, la pieza, el componente— y con él, la capacidad de evolucionar la UI entera con un cambio pequeño. Guarda esta imagen de la caja de LEGO contra el cuchillo y la lija; es todo el módulo.
El caso que nos acompaña: el sistema de diseño del storefront de Mercado
Toda la guía usa un mismo caso, para que no aprendas los conceptos en el vacío sino construyendo algo real. Mercado es un marketplace (el mismo del ecosistema). En react-fundamentals lo miraste como una jerarquía de componentes (ProductCard, Button, SearchBar, Cart); aquí lo miramos como lo que hace que esos componentes se vean coherentes: el sistema de diseño que hay detrás.
Es el mismo storefront —las mismas pantallas, los mismos componentes—, pero ahora con un sistema real: tokens (color.primary, space-4, una escala tipográfica), los componentes estilados con Tailwind y con variantes (un Button que puede ser primary, secondary o ghost, en tamaño sm, md o lg), modo claro/oscuro por tokens, y contraste verificado. Los identificadores, clases y tokens van siempre en inglés (color.primary, space-4, text-lg, bg-primary, Button, variant, size, ProductCard); solo la prosa va en español.
En este módulo 1 el storefront nos sirve para una pregunta concreta: ¿qué piezas necesita su sistema de diseño? Al final de estas ocho lecciones vas a saber listarlas —los tokens, las utilidades, los componentes con sus variantes, los patrones— y a detectar dónde una versión ad-hoc del storefront tiene drift. Ese inventario es el plano sobre el que los módulos siguientes construyen la mecánica.
Ejemplo trabajado: el drift, contado por una máquina
Nada convence como verlo pasar. El drift —esa divergencia silenciosa de los dos botones de arriba— suena a un problema estético, difuso, opinable. No lo es: es contable. Vamos a tomar un solo rol de diseño —"el azul de marca"— tal como quedó escrito a mano en cinco pantallas del storefront, y a preguntarle a una máquina una pregunta muy simple: ¿cuántos valores distintos hay para esto que debería ser uno solo?
Como no tenemos navegador, modelamos el problema con puro JavaScript. Cinco pantallas, cada una con su hex escrito de memoria, y un Set —la estructura de JavaScript que elimina duplicados— para contar cuántos valores realmente distintos aparecieron:
// L1 intro — drift teaser: "el azul de marca" escrito a mano en 5 pantallas.
const adHocPrimary = ['#3b82f6', '#3c83f6', '#3b83f7', '#2563eb', '#3b82f6'];
const distinctAdHoc = [...new Set(adHocPrimary)];
console.log('=== "El azul de marca" en 5 pantallas ===\n');
console.log('Sin sistema (cada pantalla lo escribe a mano):');
console.log(' valores usados: ' + adHocPrimary.join(', '));
console.log(' valores DISTINTOS para un mismo rol: ' + distinctAdHoc.length);
// Con un sistema: un solo token, referenciado en las 5 pantallas.
const token = { 'color.primary': '#2563eb' };
const withSystem = Array(5).fill(token['color.primary']);
const distinctSystem = [...new Set(withSystem)];
console.log('\nCon un sistema (las 5 pantallas usan el token color.primary):');
console.log(' valores usados: ' + withSystem.join(', '));
console.log(' valores DISTINTOS para un mismo rol: ' + distinctSystem.length);
Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:
=== "El azul de marca" en 5 pantallas ===
Sin sistema (cada pantalla lo escribe a mano):
valores usados: #3b82f6, #3c83f6, #3b83f7, #2563eb, #3b82f6
valores DISTINTOS para un mismo rol: 4
Con un sistema (las 5 pantallas usan el token color.primary):
valores usados: #2563eb, #2563eb, #2563eb, #2563eb, #2563eb
valores DISTINTOS para un mismo rol: 1
Lee las dos mitades lado a lado, porque en ellas está la tesis del módulo entero.
La versión sin sistema usó cinco valores para "el mismo" azul, y la máquina contó 4 distintos. Ninguno está "mal" en aislamiento: #3b82f6 y #3c83f6 son azules casi idénticos, imperceptibles por separado. El problema no es cada valor; es que hay cuatro. Cuatro fuentes de verdad para una sola idea ("el color de marca de Mercado"). Nadie decidió tener cuatro azules; se acumularon, uno por pantalla, cada uno escrito de memoria. Eso es el drift, y ahora tiene un número: 4 en vez de 1.
La versión con sistema es la misma idea resuelta de otra forma: hay un token, color.primary, con un valor, y las cinco pantallas lo referencian. La máquina cuenta 1 distinto. No porque los programadores fueran más disciplinados, sino porque estructuralmente no hay dónde divergir: todas apuntan al mismo lugar. Ese salto —de 4 a 1— es, literal, lo que hace un sistema de diseño. No te pide recordar el azul correcto; hace imposible tener el incorrecto.
Fíjate en algo importante para no confundir las capas de la guía: aquí solo contamos el problema. Cómo se define ese token, cómo se referencia desde el CSS, cómo Tailwind lo consume —toda la mecánica— es de los módulos 2 y 3. Este módulo 1 se queda en el qué y el por qué: qué es el drift, por qué un sistema lo elimina, y de qué piezas se compone ese sistema.
El mapa del módulo
Guarda esta ruta; es cómo cada lección construye una parte de "qué es un sistema de diseño":
Idea Lección Concepto clave
─────────────────────────────────────── ──────── ──────────────────────────────────────
De CSS ad-hoc a un sistema L2 el mismo estilo escrito N veces vs
una decisión nombrada una vez
Las cuatro capas del sistema L3 tokens -> utilities -> components ->
patterns (cada una sobre la anterior)
Consistencia y el costo del drift L4 el drift es contable; medir el caos
Mantenibilidad y única fuente de verdad L5 un cambio en 1 lugar, no en N
Accesibilidad como propiedad del sistema L6 se garantiza 1 vez, vale para todo
Anatomía del sistema de Mercado L7 tokens + utilities + components +
variantes + patterns, todo junto
─────────────────────────────────────── ──────── ──────────────────────────────────────
Proyecto: el inventario de Mercado L8 listar el sistema y detectar su drift
La frontera: qué NO entra en este módulo
Esta guía tiene guías hermanas que cubren lo de alrededor. Saber la frontera te ahorra confusión.
- La mecánica de los tokens —cómo se declara
--color-primary, la diferencia entre primitivo (blue.600) y semántico (color.primary), el theming por CSS custom properties— es del módulo 2. Aquí los tokens aparecen como concepto ("una decisión nombrada una vez"), no como sintaxis. - Tailwind y el CSS utility-first —
p-4,flex,bg-primary, cómo funcionan por debajo, cómo se configura— es del módulo 3. Aquí las "utilidades" son una de las cuatro capas, nombradas pero no operadas. - Las escalas y el contraste —la escala de espaciado base 4/8px, la escala tipográfica, el algoritmo WCAG de contraste— son del módulo 4. Aquí mencionamos que la coherencia sale de una escala, sin construirla.
- Los componentes con variantes —el patrón
cva,base+variants+defaultVariants— son del módulo 5. Aquí un componente con variantes es una pieza del inventario, no un mecanismo. - El CSS a mano —box model, cascada, Flexbox, Grid, media queries— es de
web-fundamentals-html-css(prerequisito). Esta guía lo asume y lo conecta (verás en el módulo 3 por qué las utilidades de Tailwind funcionan gracias a la cascada que ya conoces), no lo re-enseña. - La lógica de los componentes —
useState, eventos, el flujo de props— es dereact-fundamentals(prerequisito). Aquí los componentes se estilan y varían; su comportamiento no se re-enseña.
Errores comunes
Creer que "sistema de diseño = librería de componentes". Qué pasa: alguien oye "sistema de diseño" y piensa inmediatamente en un Button bonito, una carpeta de componentes de React, quizás shadcn. Por qué pasa: los componentes son la capa visible del sistema, la que se toca al programar. Cómo detectarlo: tienes componentes reutilizables, pero cada uno define sus propios colores y espaciados a mano —o sea, tienes las piezas grandes pero no los tornillos que las mantienen coherentes—. Cómo corregirlo: un sistema de diseño es cuatro capas, y los componentes son solo la tercera. Debajo de ellos están los tokens (los valores nombrados) y las utilidades; encima, los patrones. Saltarse los tokens y empezar por los componentes es construir la casa desde el segundo piso: los componentes se ven bien, pero divergen entre sí porque no comparten una base. La lección 3 desarma este error mostrando las cuatro capas y por qué el orden importa.
Nombrar los tokens por su valor y no por su rol. Qué pasa: se crea un token llamado blue (o blue600) con el valor #2563eb. Por qué pasa: es lo más literal —"es azul, le pongo blue"—. Cómo detectarlo: cuando decides que el color de marca ahora será verde, tienes un token llamado blue que vale verde, una contradicción que envenena todo el código. Cómo corregirlo: los tokens se nombran por su rol, no por su valor: color.primary, no blue. color.primary describe para qué sirve (el color de marca, el de las acciones principales), y por eso puede cambiar de azul a verde sin mentir. El nombre correcto sobrevive al cambio de valor; el nombre por valor se rompe con el primer cambio. Es una regla que se profundiza en el módulo 2, pero conviene grabarla desde ya.
Copiar y pegar estilos "para ir rápido". Qué pasa: necesitas un botón parecido a otro, copias su CSS, lo pegas y lo ajustas "tantito". Por qué pasa: en el momento, copiar y pegar es más rápido que buscar y reutilizar la pieza existente. Cómo detectarlo: lo viste ejecutado —cinco copias del "mismo" azul produjeron cuatro azules distintos—. Cada copia es una futura fuente de drift: nace idéntica, pero cada una evoluciona por su lado. Cómo corregirlo: cuando te descubras copiando un estilo, esa es la señal de que ahí hace falta una pieza del sistema —un token o un componente— que las dos partes referencien en vez de duplicar. Copiar crea dos verdades que divergirán; referenciar mantiene una sola. La regla: si te oyes decir "copio esto y lo ajusto", detente y pregúntate qué pieza del sistema estás a punto de no reutilizar.
Ejercicios
Ejercicio 1 — Detecta el drift. Aquí están los estilos de tres botones de distintas pantallas del storefront, escritos a mano. Sin correr nada, di cuántos valores distintos hay para cada propiedad (background, padding, border-radius) y qué debería ser cada una en un sistema.
/* pantalla home */
.btn-a { background: #3b82f6; padding: 12px 16px; border-radius: 8px; }
/* pantalla catálogo */
.btn-b { background: #3c83f6; padding: 12px 16px; border-radius: 6px; }
/* pantalla producto */
.btn-c { background: #3b82f6; padding: 10px 16px; border-radius: 8px; }
Ver solución
background: valores#3b82f6,#3c83f6,#3b82f6→ 2 distintos (#3b82f6y#3c83f6). Debería ser 1: el tokencolor.primary.padding: valores12px 16px,12px 16px,10px 16px→ 2 distintos (por el12pxvs10pxvertical). Debería ser 1: un tamaño de botón que sale de la escala de espaciado.border-radius: valores8px,6px,8px→ 2 distintos. Debería ser 1: el tokenradius-md.
Ningún botón está "mal" por sí solo, pero los tres juntos tienen seis valores para lo que deberían ser tres decisiones. Eso es drift: tres botones que casi son el mismo, y que un sistema volvería exactamente el mismo al hacerlos referenciar los mismos tokens.
Ejercicio 2 — Predice el conteo. Sin correr nada, di qué imprimiría el modelo del ejemplo trabajado ([...new Set(valores)].length) para esta lista de valores de un mismo rol de espaciado: ['16px', '16px', '16px', '1rem']. Recuerda que el modelo del ejemplo no normaliza unidades: compara los strings tal cual.
Ver solución
Imprimiría 2.
El Set compara los strings exactamente como están: '16px' aparece tres veces (cuenta como uno) y '1rem' una vez (cuenta como otro). Son dos strings distintos → 2.
El detalle fino, y es importante: 1rem equivale a 16px (cuando la base es 16px), así que visualmente el espaciado sería idéntico en las cuatro. Pero el modelo cuenta representaciones distintas, no valores visuales. Que la misma medida esté escrita de dos formas ya es una forma de drift: el día que alguien cambie la base tipográfica, los 1rem se moverán y los 16px no. Un sistema evita esto teniendo un token (space-4) que se escribe de una forma. (En la lección 2 verás una versión del modelo que sí normaliza a píxeles para comparar el valor visual —y aun así encuentra caos.)
Ejercicio 3 — ¿Sistema o decisión suelta? Para cada situación, di si describe una decisión ad-hoc (escrita a mano, fuente de drift) o una decisión de sistema (nombrada una vez, referenciada):
- (a) "Cada pantalla del checkout define su propio
padding: 24pxen el contenedor." - (b) "Todos los espaciados salen de una escala; el contenedor usa
space-6." - (c) "Copié el CSS del botón de home y lo ajusté para la página de producto."
- (d) "El
Buttones un componente; se usa el mismo en las cinco pantallas."
Ver solución
- (a) Ad-hoc. El valor
24pxestá escrito a mano en cada pantalla. Cada una es una fuente independiente: el día que uno escriba22pxde memoria, apareció el drift. No hay un lugar único que gobierne ese espaciado. - (b) De sistema. El espaciado sale de una escala y se referencia por su nombre (
space-6). Hay una única fuente de verdad; todas las pantallas apuntan a ella. Si la escala cambia, todas se mueven juntas. - (c) Ad-hoc (y del peor tipo). Copiar y pegar crea dos verdades que nacen idénticas y divergen con el tiempo. Es la fábrica clásica de drift. La corrección es extraer la pieza compartida (un componente
Button) y que ambas la referencien. - (d) De sistema. Un solo componente usado en cinco lugares garantiza que las cinco se vean —y se comporten— igual. Cambiar el componente cambia las cinco a la vez. Es la esencia de la caja de LEGO: una pieza estándar, reutilizada.
La regla que se repite: si el valor o el estilo está escrito en cada lugar, es ad-hoc y va a divergir; si está nombrado una vez y los lugares lo referencian, es sistema y se mantiene solo.
Resumen y siguiente paso
En esta lección instalaste el cambio de mentalidad que sostiene toda la guía: un sistema de diseño reemplaza mil decisiones ad-hoc por unas pocas decisiones tomadas una vez. Viste, con la caja de LEGO contra el cuchillo y la lija, que la coherencia de un sistema no depende de tu memoria sino de la estructura —las piezas estándar no pueden divergir porque son las mismas—, y que solo lo que sale de un lugar único se puede cambiar de golpe. Y lo comprobaste ejecutando: "el mismo" azul escrito a mano en cinco pantallas produjo 4 valores distintos (drift), y referenciado desde un token produjo 1 —mismo problema, resuelto por estructura y no por disciplina—. Conociste el caso que nos acompaña (el sistema de diseño del storefront de Mercado) y trazaste la frontera: aquí el qué y el por qué; la mecánica de tokens es el módulo 2, Tailwind el 3.
Antes de avanzar deberías poder: explicar qué es el drift y por qué es contable; decir por qué un sistema lo elimina por estructura y no por disciplina; y distinguir una decisión ad-hoc (escrita en cada lugar) de una de sistema (nombrada una vez, referenciada).
La lección 2 baja el primer escalón concreto: de CSS ad-hoc a un sistema. Vas a ver el mismo estilo del storefront escrito a mano en varias pantallas —con su drift medido en píxeles reales— y el mismo estilo resuelto como una decisión nombrada una vez. Es el "antes y después" que motiva todo lo que sigue: el momento en que el CSS deja de ser una pila de valores sueltos y empieza a ser un sistema.
Recursos
- Brad Frost, "Atomic Design" — atomicdesign.bradfrost.com. El libro que popularizó pensar la UI como un sistema de piezas que se componen (átomos → moléculas → organismos), la idea madre de las capas de este módulo. En inglés.
- Material Design 3 — m3.material.io. El sistema de diseño de Google, un ejemplo completo y público de tokens, componentes y patrones trabajando juntos; útil para ver un sistema "de verdad" a escala. En inglés.
- Tailwind CSS, documentación — tailwindcss.com/docs. La herramienta de la capa de utilidades que usarás desde el módulo 3; por ahora, un vistazo a su filosofía. En inglés.
- shadcn/ui — ui.shadcn.com. La colección de componentes accesibles que verás en el módulo 7 (primitivas que vistes con tus tokens); un ejemplo vivo de la capa de componentes. En inglés.
- Design Tokens Community Group (W3C), especificación — tr.designtokens.org/format. El estándar en formación para describir tokens de diseño; la referencia formal de la capa que abre el módulo 2. En inglés.