Módulo 2: Design Tokens
Presentación del módulo: design tokens
De las cuatro capas a la primera
En el módulo 1 dibujaste el mapa completo del sistema: las cuatro capas —tokens → utilidades → componentes → patrones—, cada una apoyada en la de abajo. Viste que el problema que un sistema resuelve es el drift —la divergencia silenciosa de "el mismo" azul escrito a mano en cinco pantallas, que la máquina contó como cuatro valores distintos— y cerraste el módulo haciendo el inventario de Mercado: la lista de piezas que el storefront necesita, capa por capa. Ese inventario es un plano. Todavía no construiste una sola pieza.
Aquí empieza la construcción, y empieza por donde tiene que empezar: los cimientos. Este módulo baja a la capa más baja de las cuatro —los tokens— y la vuelve real. Deja de ser "una decisión nombrada una vez" (el concepto del módulo 1) y pasa a ser algo que defines, escribes y usas: un valor con nombre, en tres niveles, expresado en CSS de verdad, capaz de cambiar un tema entero desde un solo lugar. Al terminar sabrás definir el conjunto de tokens de una app, organizarlos en las tres capas correctas, escribirlos como CSS custom properties y hacer que un mismo token dé un valor en tema claro y otro en tema oscuro sin tocar ni un componente.
No entramos en todo lo que se apoya encima de los tokens todavía. Las escalas concretas —cuántos pasos de espaciado, qué ratios tipográficos— son el módulo 4. Tailwind, la herramienta que consume estos tokens como utilidades, es el módulo 3. Las variantes de componente son el 5. Aquí nos quedamos en la capa 1: qué es un token, en qué tres niveles se organiza, cómo vive en el navegador y cómo cambia con el tema. Es el módulo más "de cimientos" de la guía —todo lo demás referencia lo que definas aquí—.
Conexión con el módulo. Esta es la lección-mapa del módulo 2. No entra a fondo en ninguna pieza: instala la tesis (un token es un valor nombrado por su rol, resuelto por una cadena de tres capas), da el mapa de las ocho lecciones, y ejecuta el primer teaser que conecta el drift del módulo 1 con su cura mecánica. La lección 2 define qué es un token. La 3 presenta las tres capas de tokens —primitivos, semánticos y de componente— y el resolveToken que las recorre. La 4 los baja al navegador con CSS custom properties. La 5 fija la regla dura de nombrarlos por su rol. La 6 los pone a hacer theming claro/oscuro. La 7 arma la paleta completa de Mercado. Y la 8 te pone a definir el set entero tú.
Una analogía: la paleta del pintor
Un pintor que recién empieza mezcla cada color en el momento. Necesita un azul de cielo, así que toma blanco, un poco de azul, una pizca de gris, y mezcla sobre la marcha. Media hora después necesita "el mismo" azul de cielo para otra esquina del cuadro, y vuelve a mezclar —de memoria—. Sale parecido. Pero puestos lado a lado, los dos cielos no son el mismo azul: uno tiene un pelo más de gris, el otro un pelo más de blanco. Es el drift del módulo 1, ahora con pintura: cada mezcla es una decisión ad-hoc, hermosa en aislamiento, divergente en conjunto.
El pintor con oficio hace otra cosa. Antes de empezar, prepara su paleta: mezcla sus colores una vez, los pone en pocillos y los etiqueta por lo que son en el cuadro —"cielo", "sombra", "piel", "acento"—. De ahí en adelante no vuelve a mezclar: moja el pincel en "cielo". Todos los cielos del cuadro salen del mismo pocillo, así que son, físicamente, el mismo azul. Y si a mitad del cuadro decide que el cielo será más cálido, cambia lo que hay en el pocillo "cielo" una vez, y todos los cielos que pinte después salen cálidos —sin repintar los anteriores uno por uno—.
Esa paleta etiquetada son tus tokens. Y fíjate en la distinción que el pintor hace sin pensarlo, porque es el corazón de este módulo:
- El pocillo con el pigmento —"azul de ftalocianina #2563eb"— es el color crudo. Existe, tiene un valor exacto, pero no dice para qué sirve en este cuadro. Eso es un token primitivo.
- La etiqueta "cielo" pegada a un pocillo es el color por su papel en la obra. No dice qué pigmento es; dice qué rol cumple. Eso es un token semántico. Y aquí está el truco: la etiqueta "cielo" puede apuntar al pocillo de ftalocianina hoy y a otro más cálido mañana. Cambias a qué pocillo apunta la etiqueta y todos los cielos cambian —la etiqueta es un interruptor—.
- Y cuando el pintor dice "el acento del marco usa el color de 'sombra'", ató una parte concreta del cuadro a un rol. Eso es un token de componente.
Un pincel que moja en "cielo", que apunta a "azul de ftalocianina", que es #2563eb. Tres eslabones, del papel al pigmento. Esa cadena —de componente a semántico a primitivo a valor— es lo que vas a definir, escribir y ejecutar en este módulo.
Ejemplo trabajado: una decisión, muchos usos
El módulo 1 midió la enfermedad (el drift: cuatro azules donde debía haber uno). Este teaser mide la cura, y es la propiedad que hace de un token un token: está definido en un solo lugar, muchas piezas lo referencian, y cambiarlo una vez actualiza a todas.
Como el navegador no corre en un agente, modelamos la idea con puro JavaScript. Un token —color.primary— vive en un objeto. Tres piezas del storefront (Button, Badge, SearchBar) no copian su valor: lo referencian con una función token(). Luego cambiamos el valor en su único lugar y volvemos a preguntar:
// L1 intro — un token es un valor con nombre; las piezas lo REFERENCIAN, no lo copian.
const tokens = {
'color.primary': '#2563eb',
'space-4': '16px',
'radius-md': '8px',
};
function token(name) {
if (!(name in tokens)) throw new Error('Token desconocido: ' + name);
return tokens[name];
}
// Tres piezas del storefront que REFERENCIAN el mismo token de color.
const usedBy = ['Button', 'Badge', 'SearchBar'];
console.log('=== color.primary, referenciado por 3 piezas ===');
for (const piece of usedBy) {
console.log(' ' + piece.padEnd(10) + '-> color.primary = ' + token('color.primary'));
}
// Una sola decision: cambiamos el VALOR del token en un lugar.
tokens['color.primary'] = '#16a34a'; // la marca pasa de azul a verde
console.log('\n=== cambiamos color.primary en UN lugar ===');
for (const piece of usedBy) {
console.log(' ' + piece.padEnd(10) + '-> color.primary = ' + token('color.primary'));
}
Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:
=== color.primary, referenciado por 3 piezas ===
Button -> color.primary = #2563eb
Badge -> color.primary = #2563eb
SearchBar -> color.primary = #2563eb
=== cambiamos color.primary en UN lugar ===
Button -> color.primary = #16a34a
Badge -> color.primary = #16a34a
SearchBar -> color.primary = #16a34a
Lee las dos mitades. En la primera, tres piezas distintas del storefront muestran el mismo valor —no porque alguien se acordara de escribir #2563eb tres veces, sino porque las tres apuntan al mismo token—. En la segunda, cambiamos color.primary de azul a verde en una sola línea, y las tres piezas se actualizaron solas. Nadie tocó Button, ni Badge, ni SearchBar. Ese es el superpoder de la capa 1: la marca pasó de azul a verde con una edición, y la onda subió sola por todo lo que referencia el token.
Compara esto con el drift del módulo 1. Allá, "el mismo" azul escrito a mano dio cuatro valores porque cada pantalla lo copiaba. Aquí da un solo valor porque todas lo referencian —y cuando cambia, cambia para todas a la vez—. Copiar crea verdades que divergen; referenciar mantiene una sola. Un token es, mecánicamente, ese acto de referenciar en vez de copiar. Todo el módulo desarrolla esa idea: cómo se define el token, en qué niveles se organiza, cómo se escribe en CSS y cómo un mismo token da distinto valor por tema.
Una pregunta para que la cargues por el resto del módulo: si en vez de color.primary el token se hubiera llamado blue, ¿seguiría teniendo sentido su nombre después de cambiarlo a verde? (Guarda la incomodidad que sentiste al leer blue = #16a34a; la lección 5 la convierte en una regla dura.)
El mapa del módulo
Guarda esta ruta; es cómo cada lección construye la capa de tokens de abajo hacia arriba:
Idea Lección Concepto clave
───────────────────────────────────────── ──────── ─────────────────────────────────────
Qué es un token L2 un valor con nombre; la UI son
referencias a tokens, no valores crudos
Primitivos, semánticos y de componente L3 las 3 capas de tokens y resolveToken:
button.bg -> color.primary -> blue.600
CSS custom properties L4 --color-primary: el token real en el
navegador (:root y el tema)
Nombrar los tokens por su rol L5 color.primary, no blue; el nombre debe
sobrevivir al cambio de valor
Theming claro y oscuro L6 cambiar el VALOR del token semántico,
no el componente
La paleta de Mercado en la práctica L7 las 3 capas juntas, el set real del
storefront resuelto en ambos temas
───────────────────────────────────────── ──────── ─────────────────────────────────────
Proyecto: el set de tokens de Mercado L8 definir primitivos + semánticos + de
componente, en CSS, resueltos en 2 temas
La frontera: qué NO entra en este módulo
Saber la frontera te evita mezclar capas que otras lecciones y guías cubren:
- Las escalas concretas —cuántos pasos de espaciado (base 4/8px), qué ratios de la escala tipográfica, los pasos 50–900 de una paleta— son el módulo 4. Aquí los tokens de espaciado y tipografía aparecen nombrados (
space-4,text-lg) como ejemplos de que existen esos roles, pero no construimos la escala que los ordena. - Tailwind y el utility-first —
p-4,bg-primary, cómo se configura Tailwind para que lea tus tokens— es el módulo 3. Aquí definimos los tokens; allá se consumen como utilidades. - Las variantes de componente —
variant,size, el patróncva— son el módulo 5. Aquí un token de componente (button.bg) es un valor atado a una pieza, no un sistema de variantes. - El detalle de responsive y dark mode en Tailwind (
md:,dark:) es el módulo 6. Aquí hacemos el theming por el valor del token (el mecanismo de fondo); allá se conecta con los prefijos de Tailwind. - El contraste accesible —si un par de colores es legible, el algoritmo WCAG— es el módulo 4. Aquí elegimos pares de tokens para claro y oscuro; medir si pasan AA/AAA es allá.
Errores comunes
Creer que "token" es solo otra palabra para "variable de CSS". Qué pasa: alguien oye "design token" y piensa "ah, es --color-primary, una variable, ya lo sé". Por qué pasa: la forma final de un token en el navegador sí es una CSS custom property, así que parece que ahí se acaba la historia. Cómo detectarlo: defines --blue: #2563eb y --padding: 16px sueltos, sin niveles ni roles, y crees que ya tienes un sistema de tokens. Cómo corregirlo: la variable de CSS es el vehículo, no el concepto. Un token es un valor nombrado por su rol y organizado en tres capas (primitivo, semántico, de componente) que se resuelven en cadena. La lección 3 muestra esas capas y la 4 muestra cómo se vuelven CSS custom properties —el orden importa: primero entiendes las capas, después las escribes—.
Querer definir el color perfecto antes de tener el sistema. Qué pasa: se gastan horas eligiendo el hex exacto del azul de marca antes de haber decidido cómo se organiza la paleta. Por qué pasa: el valor concreto se siente como "lo importante" y la estructura como burocracia. Cómo detectarlo: tienes un #2563eb perfecto pero no sabes si es un primitivo, un semántico, ni cómo lo va a referenciar un botón. Cómo corregirlo: el valor exacto es lo último y lo más fácil de cambiar —lo viste: cambió de azul a verde en una línea—. Lo que da valor al sistema es la estructura: los roles, las capas, la cadena. Define primero los niveles y los nombres; el hex se ajusta al final y las veces que haga falta.
Saltarse el mapa de las capas y "poner tokens donde caigan". Qué pasa: se empieza a crear tokens sin decidir si cada uno es primitivo, semántico o de componente, y terminan mezclados. Por qué pasa: al principio los tres niveles se sienten iguales —todos son "name → value"—. Cómo detectarlo: tienes un token blue.600 junto a button.bg junto a color.primary sin saber cuál puede apuntar a cuál. Cómo corregirlo: hay una dirección obligatoria —de componente a semántico a primitivo a valor—, igual que las cuatro capas del módulo 1 iban de abajo hacia arriba. La lección 3 la fija; llévala como brújula todo el módulo: ¿es un valor crudo? primitivo. ¿es un rol? semántico. ¿está atado a una pieza? de componente.
Ejercicios
Ejercicio 1 — Referencia o copia. Para cada situación, di si describe una referencia a un token (una sola fuente de verdad) o una copia de su valor (una futura fuente de drift):
- (a) El
Buttonescribebackground: #2563ebdirectamente en su estilo. - (b) El
Badgeusabackground: token('color.primary'). - (c) Tres pantallas escriben cada una
padding: 16pxa mano en su contenedor. - (d) Tres pantallas usan
padding: token('space-4').
Ver solución
- (a) Copia. El valor
#2563ebestá escrito en elButton. Es una fuente independiente: el día que alguien escriba#3c83f6en otra pieza, apareció el drift. Nada garantiza que sea el mismo azul que las demás. - (b) Referencia. El
Badgeapunta al tokencolor.primary; no sabe ni le importa qué hex es hoy. Si el token cambia, elBadgecambia con él —sin tocarlo—. - (c) Copia (×3). Tres lugares con el mismo
16pxescrito a mano son tres verdades que nacen idénticas y divergen con el tiempo. Es la fábrica de drift del módulo 1. - (d) Referencia (×3). Las tres apuntan a
space-4. Cambiar la escala en un lugar mueve las tres a la vez; siempre serán el mismo espacio porque salen del mismo token.
La regla que se repite todo el módulo: si el valor está escrito en la pieza, es copia y va a divergir; si está nombrado una vez y la pieza lo referencia, es token y se mantiene solo.
Ejercicio 2 — Predice la salida. Sin correr nada, di qué imprimiría la segunda mitad del ejemplo trabajado si, en vez de cambiar color.primary, cambiáramos así:
tokens['color.primary'] = '#7c3aed'; // la marca pasa a morado
Ver solución
Imprimiría las tres piezas con el nuevo valor:
Button -> color.primary = #7c3aed
Badge -> color.primary = #7c3aed
SearchBar -> color.primary = #7c3aed
La razón es exactamente la del ejemplo: las tres piezas no guardan un valor, referencian el token. Cualquier valor que le pongas a color.primary —azul, verde, morado— aparece en las tres a la vez, con una sola edición. El valor concreto es lo más fácil de cambiar; la estructura (una fuente, muchas referencias) es lo que no cambia.
Ejercicio 3 — Ubica la pieza en su capa. El módulo 1 te dio las cuatro capas del sistema (tokens → utilidades → componentes → patrones). Para cada afirmación sobre este módulo 2, di si es verdadera o falsa y por qué:
- (a) "Este módulo construye la capa de componentes."
- (b) "Un token puede referenciar a otro token."
- (c) "Tailwind es lo que define los tokens."
Ver solución
- (a) Falsa. Este módulo construye la capa 1: los tokens —los cimientos—. Los componentes son la capa 3 y su construcción con variantes es el módulo 5. Aquí solo nombramos piezas como
Buttonpara mostrar quién referencia los tokens. - (b) Verdadera. Es justo el corazón del módulo: un token de componente (
button.bg) referencia a un semántico (color.primary), que referencia a un primitivo (blue.600), que es el valor final. Esa cadena de tres niveles es la lección 3. - (c) Falsa. Los tokens los defines tú, en este módulo. Tailwind (módulo 3) es una herramienta que consume tus tokens para generar utilidades; no los define. Se configura con tus tokens, no al revés.
Resumen y siguiente paso
En esta lección instalaste la tesis del módulo 2: un token es un valor nombrado por su rol, definido una vez y referenciado por muchas piezas —la cura mecánica del drift que el módulo 1 diagnosticó—. Con la paleta del pintor viste la distinción que estructura todo lo que viene: el pigmento crudo (primitivo), la etiqueta por su papel en el cuadro (semántico, que funciona como un interruptor), y la parte del cuadro atada a un rol (de componente). Y lo comprobaste ejecutando: color.primary, referenciado por tres piezas, cambió de azul a verde con una edición y actualizó a las tres solas. Copiar divergía; referenciar mantiene una sola verdad.
Antes de avanzar deberías poder: explicar la diferencia entre copiar un valor y referenciar un token; nombrar las tres capas de tokens que verás; y decir por qué el valor concreto es lo más fácil de cambiar y la estructura lo que da el sistema.
La lección 2 baja el primer escalón: qué es exactamente un token. Vas a ver que un token no es solo de color —hay tokens de espaciado, de radio, de sombra, de tipografía— y que el "estilo" de una pieza del storefront no es una lista de valores crudos, sino una lista de referencias a tokens que se resuelven a sus valores. Es la definición formal de la pieza que aquí usaste de forma intuitiva.
Recursos
- Design Tokens Community Group (W3C) — design-tokens.github.io/community-group. El grupo que estandariza qué es un design token y cómo se estructura; la referencia formal de todo este módulo. En inglés.
- MDN, "Using CSS custom properties (variables)" — developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties. El vehículo real de los tokens en el navegador, que verás a fondo en la lección 4. En inglés.
- Nathan Curtis, "Naming Tokens in Design Systems" — medium.com/eightshapes-llc/naming-tokens-in-design-systems-9e86c7444676. El artículo de referencia sobre cómo se nombran y estructuran los tokens por niveles; base de las lecciones 3 y 5. En inglés.
- Material Design 3, "Design tokens" — m3.material.io/foundations/design-tokens/overview. Un sistema real que organiza sus tokens en las mismas capas que este módulo; útil para ver el concepto a escala. En inglés.