Fundamentos
Hay dos capas de tokens.
Un token de valor pone nombre a un valor bruto para que se reconozca; el nombre no dice para qué se usa. Un token semántico es una decisión de diseño con nombre: enuncia algo que el diseño afirma sobre una clase de cosa, y guarda el valor con el que esa decisión se resuelve. La decisión cambia una vez, en el token semántico, y se propaga a todo lo que lo referencia.
| Categoría | Valor bruto | Token de valor | Token semántico | Qué enuncia |
|---|---|---|---|---|
| Color | #20463b | $pine-green | --text--color--display | "Color del texto de exposición". Resuelve un color de paleta distinto por tema. |
| Curva | cubic-bezier(0.22, 1, 0.36, 1) | $ease-standard | --motion--transition--feedback | "Transición de una respuesta inmediata". |
| Radio | 0.375rem | — | --checkbox--radius--box | "Radio de borde de la casilla". Mismo valor en cualquier contexto. |
Un token de valor existe solo cuando el valor no se reconoce a simple vista: #20463b no dice nada por sí solo, y por eso es $pine-green. Un color, un tinte y una curva se nombran; una medida —1px, 0.375rem, 200ms— se lee tal cual, así que no se nombra.
Una variable Sass, con un solo guion entre palabras: $pine-tint-28, $ease-standard.
El nombre dice qué valor es, nunca para qué sirve: $pine-tint-14…40 nombra un tinte de la paleta a una opacidad.
En tokens/. Al ser variables Sass se resuelven al compilar, así que no llegan a la hoja publicada: lo que se reparte son los tokens semánticos, ya con su valor dentro.
Un token semántico es el punto donde una decisión puede volver a tomarse: lo que un componente lee, y lo que un tema, una superficie de marca, una variante o un estado reescriben. Existe cuando enuncia algo que el diseño afirma sobre una clase de cosa: se puede escribir como una regla del producto sin apoyarse en otro token, y la clase sobre la que habla no es una sola pieza.
subtle, strong, solid, large— indica siempre un token así.El valor directamente cuando se lee tal cual —--text--font-family--display guarda "Syne", --checkbox--radius--box guarda 0.375rem— y un token de valor cuando no: --text--color--display guarda #{$pine-green}.
Tres bloques separados por doble guion:
--<categoría>--<qué es>--<uso>
surface, text, border, state, checkbox, toast.color es un color aplicado a texto, a una marca o como relleno; background, un color de fondo; border, un color de borde; border-width y border-style, el grosor y el tipo de un borde; radius, un radio de borde; shadow, una sombra completa (box-shadow); width, un grosor; style, un tipo de línea; size, una medida; offset, un desplazamiento; transition, una duración y una curva; duration, una duración; order, un z-index; font-family, font-size, font-weight, line-height, letter-spacing, padding, transform, mask y outline, lo que su nombre dice. Se escribe entero, y si lleva guion propio va dentro de su bloque: --text--font-family--display.primary, secondary, tertiary, solo cuando hay un conjunto que ordenar), un estado (rest, hover, active, checked), una parte (box, knob, rail, mark), una clase de cosa (document, container, caption) o un momento (feedback, reveal, entrance).--surface--color--container
--text--font-family--display
--checkbox--color--mark
El tercer bloque nombra un uso, nunca un aspecto: solid, subtle, strong, large o spring dicen cómo se ve el valor, no para qué está.
Un token semántico es genérico cuando la decisión que guarda no es de ninguna pieza, y vive en semantic-tokens/, en el fichero que nombra su categoría (al lado de tokens/, nunca dentro). Es de un componente cuando solo tiene sentido enunciarlo dentro de esa pieza, y vive en el CSS de ese componente: si su valor depende del tema, declarado en :root desde el _<nombre>.scss del componente, con el nombre del componente como categoría (--checkbox--color--mark), porque un tema solo puede redefinir lo que vive en :root; si no, junto al selector que lo usa. Lo que decide es de quién es la decisión, no cuántas piezas la leen: --menu--radius--item es genérico porque el radio de borde de una fila de menú no es de ninguna pieza en concreto, y --tooltip--radius--content es del tooltip porque solo tiene sentido dentro de esa pieza.
Un token genérico no sabe nada de sus consumidores: no nombra ningún componente, y cualquier pieza puede leerlo.
Los genéricos están en La capa semántica, agrupados por el concepto que nombran. Los de un componente están en la página de ese componente.
Una propiedad CSS escribe su valor tal cual salvo en dos casos, y en los dos apunta a un token semántico:
Fuera de esos dos casos el valor va escrito: display: flex, flex-direction: column, gap: 0.375rem.
El token al que apunta es siempre semántico, nunca uno de valor: el nombre de un token de valor no dice para qué sirve, así que leerlo desde un componente deja la decisión sin enunciar. Las dos capas se distinguen a simple vista: $ frente a --.
Un token se elige por lo que significa, no por el aspecto que produce. Si algo necesita el tono de --surface--border--container pero no es el borde de un contenedor, el token que le corresponde es otro, y hay que crearlo.
Un token semántico cuyo valor cambia con el tema se redefine desde el directorio de ese tema, nunca desde el fichero base.