@netzi/tokens 0.1.0-beta.10 → 0.1.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -549
- package/README.md +86 -724
- package/package.json +4 -20
- package/styles/base.css +1 -51
- package/styles/fonts.css +0 -72
- package/styles/tokens.css +544 -1280
- package/lib/brand-context.d.ts +0 -10
- package/lib/brand-context.js +0 -65
- package/lib/brand.d.ts +0 -90
- package/lib/brand.js +0 -256
- package/lib/contrast.d.ts +0 -14
- package/lib/contrast.js +0 -34
- package/public-tokens.json +0 -460
package/README.md
CHANGED
|
@@ -41,45 +41,38 @@ En tu CSS, consume los tokens:
|
|
|
41
41
|
|
|
42
42
|
```css
|
|
43
43
|
.boton {
|
|
44
|
-
background: var(--netzi-
|
|
45
|
-
color: var(--netzi-on-
|
|
46
|
-
border-radius: var(--netzi-radius
|
|
47
|
-
box-shadow: var(--netzi-
|
|
44
|
+
background: var(--netzi-blue);
|
|
45
|
+
color: var(--netzi-on-accent);
|
|
46
|
+
border-radius: var(--netzi-radius);
|
|
47
|
+
box-shadow: var(--netzi-shadow);
|
|
48
48
|
}
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
Usa los tokens por **papel** (superficie, texto, espaciado de grupo, radio de control,
|
|
52
|
-
estilo de título), no los pasos de una escala: el papel dice para qué es y la escala de
|
|
53
|
-
debajo puede cambiar sin tocar tu app. Las escalas con nombre de paso (`--netzi-space-4`,
|
|
54
|
-
`--netzi-radius-sm`, `--netzi-font-size-md`…) están en desuso para las apps (ver
|
|
55
|
-
«Escalas que pasan a internas»).
|
|
56
|
-
|
|
57
51
|
## Espaciado (`--netzi-space-*`)
|
|
58
52
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
| `--netzi-space-
|
|
66
|
-
| `--netzi-space-
|
|
67
|
-
| `--netzi-space-
|
|
68
|
-
| `--netzi-space-
|
|
69
|
-
| `--netzi-space-
|
|
70
|
-
| `--netzi-space-
|
|
71
|
-
| `--netzi-space-
|
|
72
|
-
| `--netzi-space-
|
|
73
|
-
|
|
74
|
-
Bajo `[data-density='compact']`
|
|
75
|
-
cambian), coherente con la densidad de los controles
|
|
76
|
-
densidad.
|
|
53
|
+
Escala de espaciado para gaps y paddings de layout (base 4px). Úsala en vez de
|
|
54
|
+
píxeles/rem sueltos para mantener el ritmo del sistema de diseño.
|
|
55
|
+
|
|
56
|
+
| Token | Valor | Compacto |
|
|
57
|
+
| ----------------- | ----- | -------- |
|
|
58
|
+
| `--netzi-space-0` | 0 | 0 |
|
|
59
|
+
| `--netzi-space-1` | 2px | 2px |
|
|
60
|
+
| `--netzi-space-2` | 4px | 4px |
|
|
61
|
+
| `--netzi-space-3` | 8px | 8px |
|
|
62
|
+
| `--netzi-space-4` | 12px | 10px |
|
|
63
|
+
| `--netzi-space-5` | 16px | 12px |
|
|
64
|
+
| `--netzi-space-6` | 24px | 20px |
|
|
65
|
+
| `--netzi-space-7` | 32px | 28px |
|
|
66
|
+
| `--netzi-space-8` | 48px | 40px |
|
|
67
|
+
|
|
68
|
+
Bajo `[data-density='compact']` los pasos medios/grandes se reducen (los finos no
|
|
69
|
+
cambian), coherente con la densidad de los controles.
|
|
77
70
|
|
|
78
71
|
```css
|
|
79
72
|
.tarjeta {
|
|
80
|
-
padding: var(--netzi-space-
|
|
73
|
+
padding: var(--netzi-space-5);
|
|
81
74
|
display: flex;
|
|
82
|
-
gap: var(--netzi-space-
|
|
75
|
+
gap: var(--netzi-space-3);
|
|
83
76
|
}
|
|
84
77
|
```
|
|
85
78
|
|
|
@@ -96,312 +89,46 @@ Va aparte de `index.css`; impórtalo si tu app usa las fuentes de marca:
|
|
|
96
89
|
```
|
|
97
90
|
|
|
98
91
|
Las rutas son relativas al paquete y las reescriben Vite y el CLI de Angular, que
|
|
99
|
-
copian los woff2 al build.
|
|
100
|
-
|
|
101
|
-
Mientras llegan, el texto se pinta con un **respaldo del sistema con las métricas
|
|
102
|
-
ajustadas** (Arial o Liberation Sans, y Courier New o Liberation Mono, con `size-adjust`,
|
|
103
|
-
`ascent-override`, `descent-override` y `line-gap-override`): ocupa casi lo mismo que la
|
|
104
|
-
fuente de marca y la página no salta al cambiar. Los tokens `--netzi-font-sans` y
|
|
105
|
-
`--netzi-font-mono` ya lo nombran detrás de la de marca; si cambias la familia en línea,
|
|
106
|
-
deja `'Plus Jakarta Sans Fallback'` (o `'Fira Code Fallback'`) justo detrás. De dónde
|
|
107
|
-
salen los números está en el propio `fonts.css`. Licencia OFL-1.1, adjunta en `styles/fonts/`. Ninguna hoja
|
|
92
|
+
copian los woff2 al build. Licencia OFL-1.1, adjunta en `styles/fonts/`. Ninguna hoja
|
|
108
93
|
publicada carga nada desde fuera: todo viaja dentro del paquete.
|
|
109
94
|
|
|
110
|
-
## Tipografía (`--netzi-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
95
|
+
## Tipografía (`--netzi-font-size-*`, `--netzi-line-height-*`, `--netzi-font-weight-*`)
|
|
96
|
+
|
|
97
|
+
Escala de texto para todo lo que **no** es un control: líneas secundarias, pies,
|
|
98
|
+
metadatos, títulos. Todos los tamaños escalan con `--netzi-font-scale` (el ajuste
|
|
99
|
+
de accesibilidad del panel), igual que los controles. `md` = 14px es el 100 %.
|
|
100
|
+
|
|
101
|
+
| Token | Valor | Para qué |
|
|
102
|
+
| ----------------------- | ------ | --------------------------------------- |
|
|
103
|
+
| `--netzi-font-size-xs` | 11px | metadatos, etiquetas en mayúsculas |
|
|
104
|
+
| `--netzi-font-size-sm` | 12.5px | líneas secundarias, pies, celdas densas |
|
|
105
|
+
| `--netzi-font-size-md` | 14px | texto corriente |
|
|
106
|
+
| `--netzi-font-size-lg` | 16px | texto destacado, títulos de tarjeta |
|
|
107
|
+
| `--netzi-font-size-xl` | 18px | títulos de sección |
|
|
108
|
+
| `--netzi-font-size-2xl` | 22px | títulos de página |
|
|
109
|
+
| `--netzi-font-size-3xl` | 28px | cifras grandes, portadas |
|
|
110
|
+
|
|
111
|
+
| Interlineado | Valor | Peso | Valor |
|
|
112
|
+
| ----------------------------- | ----- | ------------------------------- | ----- |
|
|
113
|
+
| `--netzi-line-height-none` | 1 | `--netzi-font-weight-regular` | 400 |
|
|
114
|
+
| `--netzi-line-height-tight` | 1.25 | `--netzi-font-weight-medium` | 500 |
|
|
115
|
+
| `--netzi-line-height-normal` | 1.5 | `--netzi-font-weight-semibold` | 600 |
|
|
116
|
+
| `--netzi-line-height-relaxed` | 1.65 | `--netzi-font-weight-bold` | 700 |
|
|
117
|
+
| | | `--netzi-font-weight-extrabold` | 800 |
|
|
130
118
|
|
|
131
119
|
Los tamaños de los **controles** (`--netzi-control-fs-sm/md/lg`) son otra familia,
|
|
132
|
-
ligada a la altura del control; no salen de
|
|
120
|
+
ligada a la altura del control; no salen de esta escala. La densidad compacta no
|
|
133
121
|
cambia el texto (encoge el aire, no la letra).
|
|
134
122
|
|
|
135
|
-
### Estilos de texto
|
|
136
|
-
|
|
137
|
-
En CSS cada estilo es el atajo `font` (tokens `typography` de DTCG) y su espaciado entre letras
|
|
138
|
-
va aparte, porque `font` no lo incluye. El tamaño solo sale también aparte
|
|
139
|
-
(`--netzi-typography-body-font-size`, #155), para la hoja que pone el peso y el interlineado
|
|
140
|
-
por su cuenta y no quiere que el atajo se los pise:
|
|
141
|
-
|
|
142
|
-
| Estilo | Tamaño | Peso | Interlineado | Espaciado | Para qué |
|
|
143
|
-
| ----------------------------- | ------ | ---- | ------------ | --------- | ----------------------------------------- |
|
|
144
|
-
| `--netzi-typography-display` | 28px | 800 | 1.25 | -0.5px | cifras grandes, portadas |
|
|
145
|
-
| `--netzi-typography-headline` | 22px | 700 | 1.25 | -0.2px | títulos de página |
|
|
146
|
-
| `--netzi-typography-title` | 18px | 700 | 1.25 | 0 | títulos de sección |
|
|
147
|
-
| `--netzi-typography-title-sm` | 16px | 600 | 1.25 | 0 | texto destacado, títulos de tarjeta |
|
|
148
|
-
| `--netzi-typography-body` | 16px | 400 | 1.5 | 0 | texto corrido: párrafos, descripciones |
|
|
149
|
-
| `--netzi-typography-body-ui` | 14px | 400 | 1.5 | 0 | interfaz: opciones, pestañas, celdas |
|
|
150
|
-
| `--netzi-typography-body-sm` | 12.5px | 400 | 1.5 | 0 | líneas secundarias, pistas, pies |
|
|
151
|
-
| `--netzi-typography-caption` | 11px | 600 | 1.25 | 0.5px | metadatos, etiquetas cortas en mayúsculas |
|
|
152
|
-
|
|
153
123
|
```css
|
|
154
|
-
.titulo-de-seccion {
|
|
155
|
-
font: var(--netzi-typography-title);
|
|
156
|
-
letter-spacing: var(--netzi-typography-title-letter-spacing);
|
|
157
|
-
}
|
|
158
124
|
.meta {
|
|
159
|
-
font: var(--netzi-
|
|
160
|
-
|
|
125
|
+
font-size: var(--netzi-font-size-xs);
|
|
126
|
+
line-height: var(--netzi-line-height-none);
|
|
127
|
+
font-weight: var(--netzi-font-weight-semibold);
|
|
161
128
|
text-transform: uppercase;
|
|
162
129
|
}
|
|
163
|
-
.celda {
|
|
164
|
-
font-size: var(--netzi-typography-body-ui-font-size);
|
|
165
|
-
}
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Siguen a `--netzi-font-sans` si la app la cambia. El atajo `font` reinicia también el
|
|
169
|
-
interlineado y el peso: ponlo primero y cambia después lo que quieras (una familia mono para
|
|
170
|
-
un código, por ejemplo). Las mayúsculas de `caption` las pone quien lo usa (`text-transform`),
|
|
171
|
-
no el estilo. Detrás hay una escala de tamaños, pesos e interlineados que es de la fuente: sus
|
|
172
|
-
tokens (`--netzi-font-size-*`, `--netzi-font-weight-*`, `--netzi-line-height-*`) están en
|
|
173
|
-
desuso para las apps.
|
|
174
|
-
|
|
175
|
-
## Movimiento (`--netzi-duration-*`, `--netzi-ease-*`)
|
|
176
|
-
|
|
177
|
-
Duraciones y curvas con **nombre de intención**, no de valor: el componente dice qué hace
|
|
178
|
-
(un hover, un panel que entra) y el token decide cuánto dura. Así el ritmo del kit se
|
|
179
|
-
cambia en un sitio y el movimiento reducido también.
|
|
180
|
-
|
|
181
|
-
| Duración | Valor | Para qué |
|
|
182
|
-
| -------------------------- | ----- | ----------------------------------------------------- |
|
|
183
|
-
| `--netzi-duration-instant` | 100ms | la respuesta a una pulsación |
|
|
184
|
-
| `--netzi-duration-fast` | 150ms | hover, foco, cambios de color; lo pequeño que aparece |
|
|
185
|
-
| `--netzi-duration-base` | 200ms | lo que se despliega o gira (flechas, acordeón) |
|
|
186
|
-
| `--netzi-duration-slow` | 280ms | los paneles y capas que entran (modal, drawer) |
|
|
187
|
-
|
|
188
|
-
| Curva | Valor | Para qué |
|
|
189
|
-
| ----------------------- | ---------------------------------- | ------------------------------------------ |
|
|
190
|
-
| `--netzi-ease-standard` | `cubic-bezier(0.25, 0.1, 0.25, 1)` | lo que cambia sin entrar ni salir (`ease`) |
|
|
191
|
-
| `--netzi-ease-enter` | `cubic-bezier(0.16, 1, 0.3, 1)` | lo que aparece: frena al llegar |
|
|
192
|
-
| `--netzi-ease-exit` | `cubic-bezier(0.4, 0, 1, 1)` | lo que se va: acelera al irse |
|
|
193
|
-
| `--netzi-ease-settle` | `cubic-bezier(0.34, 1.45, 0.5, 1)` | lo que llega, se pasa un poco y se asienta |
|
|
194
|
-
|
|
195
|
-
### Bucles y destello
|
|
196
|
-
|
|
197
|
-
Lo que se repite sin fin no es un cambio de estado: su token da la duración de **una vuelta**
|
|
198
|
-
y queda fuera de la escala de arriba (que no pasa de 300 ms). El destello es un aviso que se
|
|
199
|
-
apaga solo, largo a propósito para que dé tiempo a verlo.
|
|
200
|
-
|
|
201
|
-
| Duración | Valor | Para qué |
|
|
202
|
-
| ----------------------------- | ------ | ----------------------------------------------------------------- |
|
|
203
|
-
| `--netzi-duration-loop-spin` | 700ms | el giro de un indicador de carga |
|
|
204
|
-
| `--netzi-duration-loop-orbit` | 1100ms | el anillo que recorre el borde de un ítem o una pestaña |
|
|
205
|
-
| `--netzi-duration-loop-pulse` | 1200ms | el latido de opacidad que sustituye al giro (movimiento reducido) |
|
|
206
|
-
| `--netzi-duration-loop-sweep` | 1200ms | la barra de progreso indeterminada |
|
|
207
|
-
| `--netzi-duration-loop-shine` | 1300ms | el brillo del skeleton |
|
|
208
|
-
| `--netzi-duration-flash` | 1400ms | un aviso que se enciende, se deja ver y se apaga solo |
|
|
209
|
-
|
|
210
|
-
| Curva | Valor | Para qué |
|
|
211
|
-
| -------------------- | -------------------------------- | -------------------------------------------------------------- |
|
|
212
|
-
| `--netzi-ease-swing` | `cubic-bezier(0.42, 0, 0.58, 1)` | lo que va y vuelve: latidos, barridos, brillos (`ease-in-out`) |
|
|
213
|
-
| `--netzi-ease-spin` | `cubic-bezier(0, 0, 1, 1)` | lo que gira sin fin a velocidad constante (`linear`) |
|
|
214
|
-
|
|
215
|
-
Los bucles **no cambian** con `prefers-reduced-motion`: una duración de bucle no para una
|
|
216
|
-
animación infinita. Cada componente quita su bucle o lo cambia por un latido de opacidad en
|
|
217
|
-
su propia regla reducida:
|
|
218
|
-
|
|
219
|
-
```css
|
|
220
|
-
.cargando {
|
|
221
|
-
animation: giro var(--netzi-duration-loop-spin) var(--netzi-ease-spin) infinite;
|
|
222
|
-
}
|
|
223
|
-
@media (prefers-reduced-motion: reduce) {
|
|
224
|
-
.cargando {
|
|
225
|
-
animation: latido var(--netzi-duration-loop-pulse) var(--netzi-ease-swing) infinite;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
130
|
```
|
|
229
131
|
|
|
230
|
-
### Desplazamiento y fundido: dos familias, un solo sitio para el movimiento reducido
|
|
231
|
-
|
|
232
|
-
Con `prefers-reduced-motion: reduce` lo que **se desplaza, gira, escala o cambia de
|
|
233
|
-
geometría** no debe moverse (WCAG 2.3.3), pero un cambio de color o de opacidad no es
|
|
234
|
-
movimiento y puede seguir suavizándose. Por eso hay dos familias:
|
|
235
|
-
|
|
236
|
-
- `--netzi-duration-{instant,fast,base,slow}` son las de los **fundidos** (color, fondo,
|
|
237
|
-
borde, sombra, opacidad). No cambian con la preferencia.
|
|
238
|
-
- `--netzi-duration-move-{fast,base,slow}` son las del **desplazamiento** (`transform`,
|
|
239
|
-
`translate`, `rotate`, `scale`, `top`/`left`, alturas, filas de rejilla, márgenes). Valen
|
|
240
|
-
lo mismo que su fundido, y bajo `@media (prefers-reduced-motion: reduce)` `tokens.css` las
|
|
241
|
-
pone a `0.01ms` **en un solo bloque**: todo lo que las usa salta a su estado final.
|
|
242
|
-
|
|
243
|
-
Van a `0.01ms` y no a `0` para que `transitionend` y `animationend` sigan llegando a quien
|
|
244
|
-
los espera (con duración cero no hay transición y el evento no se dispara nunca).
|
|
245
|
-
|
|
246
|
-
```css
|
|
247
|
-
.panel {
|
|
248
|
-
transition:
|
|
249
|
-
transform var(--netzi-duration-move-slow) var(--netzi-ease-enter),
|
|
250
|
-
opacity var(--netzi-duration-slow) var(--netzi-ease-enter);
|
|
251
|
-
}
|
|
252
|
-
/* Con reduce, el panel ya no se desliza (salta) pero sigue apareciendo con un fundido:
|
|
253
|
-
no hace falta escribir ninguna regla @media. */
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
Para cambiar el ritmo en tu app, redefine `--netzi-duration-{fast,base,slow}`: las `move`
|
|
257
|
-
apuntan a ellas y las siguen, y el bloque de movimiento reducido las sigue anulando. Si
|
|
258
|
-
redefines un token `move` directamente, tu regla de `:root` gana a la de `tokens.css` también
|
|
259
|
-
con la preferencia, así que repite la anulación en tu propio `@media`:
|
|
260
|
-
|
|
261
|
-
```css
|
|
262
|
-
:root {
|
|
263
|
-
--netzi-duration-move-slow: 320ms;
|
|
264
|
-
}
|
|
265
|
-
@media (prefers-reduced-motion: reduce) {
|
|
266
|
-
:root {
|
|
267
|
-
--netzi-duration-move-slow: 0.01ms;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
Una transición que mueve con una duración de **fundido** sí sigue moviéndose con la
|
|
273
|
-
preferencia: elige la familia por lo que anima, no por cuánto dura. Si una capa mezcla
|
|
274
|
-
las dos (`transition: 0.15s`, que es `all`), necesita su propia regla reducida. Las
|
|
275
|
-
**animaciones** con `@keyframes` también: la duración de una animación infinita no la para.
|
|
276
|
-
En `@netzi/ui` lo vigilan dos guardianes: el de movimiento reducido entiende estos tokens
|
|
277
|
-
(una transición que solo mueve con `move` ya está reducida) y otro falla con cualquier
|
|
278
|
-
duración o curva literal en las hojas del kit, también en los bucles (solo pasan `0s` y el
|
|
279
|
-
`0.01ms` de la regla reducida).
|
|
280
|
-
|
|
281
|
-
La salida DTCG resuelta publica la escala sin la preferencia (tipos `duration` y
|
|
282
|
-
`cubicBezier`): cada plataforma nativa lee el ajuste de movimiento reducido de su sistema.
|
|
283
|
-
|
|
284
|
-
## Tamaños de ventana (`--netzi-window-*`)
|
|
285
|
-
|
|
286
|
-
El diseño cambia en cinco **tamaños de ventana con nombre** (ADR 0016 del repo), siempre en
|
|
287
|
-
los mismos cortes. Cada token es el ancho en el que **empieza** ese tamaño:
|
|
288
|
-
|
|
289
|
-
| Token | Valor | Tamaño | Ancho | Paneles |
|
|
290
|
-
| ---------------------------- | ------ | ----------- | ------------ | ------- |
|
|
291
|
-
| (ninguno) | 0 | compacto | < 600 px | 1 |
|
|
292
|
-
| `--netzi-window-medium` | 600px | medio | 600–839 px | 1 o 2 |
|
|
293
|
-
| `--netzi-window-expanded` | 840px | expandido | 840–1199 px | 2 |
|
|
294
|
-
| `--netzi-window-large` | 1200px | grande | 1200–1599 px | 2 |
|
|
295
|
-
| `--netzi-window-extra-large` | 1600px | extragrande | ≥ 1600 px | hasta 3 |
|
|
296
|
-
|
|
297
|
-
`--netzi-window-reflow` (375px) no es un tamaño: es el corte de **reflujo** dentro de
|
|
298
|
-
compacto. Por debajo (teléfonos de 320 y 360 y el zoom al 400 %, WCAG 1.4.10) lo que va en
|
|
299
|
-
fila dentro de un panel flotante se apila.
|
|
300
|
-
|
|
301
|
-
Una `var()` no vale dentro de `@media`, así que en una hoja se escribe el número del token,
|
|
302
|
-
siempre en forma de rango y con el mismo sentido:
|
|
303
|
-
|
|
304
|
-
```css
|
|
305
|
-
/* Compacto: por debajo del medio. */
|
|
306
|
-
@media (width < 600px) {
|
|
307
|
-
}
|
|
308
|
-
/* Del expandido hacia arriba. */
|
|
309
|
-
@media (width >= 840px) {
|
|
310
|
-
}
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
En `@netzi/ui` un guardián falla con cualquier otro corte de ventana en las hojas del kit.
|
|
314
|
-
Lo que depende de su **propia caja** y no de la ventana (una rejilla que cabe o no en su
|
|
315
|
-
columna) usa una consulta de contenedor con nombre, `@container <nombre> (…)`. En el código,
|
|
316
|
-
`@netzi/ui` exporta los mismos cortes (`NETZI_WINDOW_BREAKPOINTS`) y una señal con el tamaño
|
|
317
|
-
actual (`NetziWindowSizeService`). La salida DTCG resuelta los publica como `dimension` en px.
|
|
318
|
-
|
|
319
|
-
## Capas (`--netzi-layer-*`)
|
|
320
|
-
|
|
321
|
-
El orden de apilamiento (`z-index`) sale de una escala con **nombre de intención**: quien
|
|
322
|
-
pinta algo encima dice qué es (un desplegable, un aviso) y la escala decide qué tapa a qué.
|
|
323
|
-
De abajo arriba:
|
|
324
|
-
|
|
325
|
-
| Token | Valor | Para qué |
|
|
326
|
-
| ------------------------ | ----- | --------------------------------------------------------------------------- |
|
|
327
|
-
| `--netzi-layer-content` | 0 | el contenido de la página: el punto de partida |
|
|
328
|
-
| `--netzi-layer-sticky` | 2 | encabezados y columnas fijas (la tabla de datos) |
|
|
329
|
-
| `--netzi-layer-bar` | 20 | lo del marco que pasa sobre el contenido: plegar el menú, la barra de carga |
|
|
330
|
-
| `--netzi-layer-flyout` | 50 | submenús del menú plegado y menús contextuales anclados al contenido |
|
|
331
|
-
| `--netzi-layer-scrim` | 80 | el velo de un panel lateral que se abre encima (el menú en el móvil) |
|
|
332
|
-
| `--netzi-layer-modal` | 100 | diálogos y paneles laterales, con su velo dentro |
|
|
333
|
-
| `--netzi-layer-dropdown` | 120 | paneles anclados a un control y la paleta de comandos |
|
|
334
|
-
| `--netzi-layer-toast` | 200 | el aviso, que se ve aunque haya un modal o un desplegable abiertos |
|
|
335
|
-
| `--netzi-layer-tooltip` | 300 | la etiqueta de lo que tiene el puntero o el foco |
|
|
336
|
-
| `--netzi-layer-blocking` | 1000 | la pantalla que bloquea la app hasta resolver algo (sin conexión) |
|
|
337
|
-
| `--netzi-layer-top` | 10000 | lo que nunca puede quedar tapado: el enlace «Ir al contenido» con foco |
|
|
338
|
-
|
|
339
|
-
Reglas, las mismas que sigue `@netzi/ui` (un guardián falla con cualquier número suelto en
|
|
340
|
-
sus hojas):
|
|
341
|
-
|
|
342
|
-
- Dentro de la capa de un componente, el orden local va con `-1`, `0` o `1` (la capa de
|
|
343
|
-
cristal detrás de su panel, una celda fijada sobre las demás).
|
|
344
|
-
- Lo que tiene que quedar justo encima o debajo de otra cosa de su misma capa va un escalón
|
|
345
|
-
más allá: `calc(var(--netzi-layer-dropdown) + 1)`. Nunca más de uno: si hace falta más,
|
|
346
|
-
falta una capa en la escala.
|
|
347
|
-
- En `@netzi/ui` cada uso lleva el valor del token como respaldo
|
|
348
|
-
(`var(--netzi-layer-dropdown, 120)`): sin `tokens.css` el kit apila igual, y el guardián
|
|
349
|
-
comprueba que el número coincide con el token.
|
|
350
|
-
- Un desplegable dentro de un modal no necesita nada: el modal abre su propio contexto de
|
|
351
|
-
apilamiento y lo que lleva dentro va en su capa.
|
|
352
|
-
|
|
353
|
-
```css
|
|
354
|
-
.mi-barra-fija {
|
|
355
|
-
position: sticky;
|
|
356
|
-
top: 0;
|
|
357
|
-
z-index: var(--netzi-layer-bar); /* por encima de los encabezados fijos de la tabla */
|
|
358
|
-
}
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
Los huecos entre valores dejan sitio a la app: una capa propia entre dos del kit se escribe
|
|
362
|
-
con `calc()` sobre la de debajo. La salida DTCG publica la escala como `number`; en móvil el
|
|
363
|
-
orden lo da la composición, y la escala sirve de referencia si una pieza tiene que ordenar.
|
|
364
|
-
|
|
365
|
-
## Forma y elevación (`--netzi-radius-*`, `--netzi-elevation-*`)
|
|
366
|
-
|
|
367
|
-
Radios por **papel**:
|
|
368
|
-
|
|
369
|
-
| Token | Valor | Compacto | Para qué |
|
|
370
|
-
| --------------------------- | ------ | -------- | --------------------------------------------------------------------------- |
|
|
371
|
-
| `--netzi-radius-control` | 6px | 5px | controles y piezas pequeñas: botones, campos, ítems de menú, iconos en caja |
|
|
372
|
-
| `--netzi-radius-surface-sm` | 8px | 6px | superficies pequeñas o pegadas a un control: el panel de un select, avisos |
|
|
373
|
-
| `--netzi-radius-surface` | 10px | 8px | superficies: tarjetas, diálogos, popovers, paneles |
|
|
374
|
-
| `--netzi-radius-pill` | 9999px | 9999px | lo del todo redondeado: píldoras, puntos, avatares, interruptores |
|
|
375
|
-
|
|
376
|
-
En una pieza cuadrada, `pill` es un círculo; en una alargada, una píldora. Sustituye a los
|
|
377
|
-
`999px` y `50%` sueltos, y la densidad no lo toca.
|
|
378
|
-
|
|
379
|
-
La elevación dice **cuánto se despega** una pieza de lo que tiene debajo, con nombre de
|
|
380
|
-
intención y de menos a más:
|
|
381
|
-
|
|
382
|
-
| Token | Para qué |
|
|
383
|
-
| ---------------------------- | -------------------------------------------------------------------------------- |
|
|
384
|
-
| `--netzi-elevation-base` | pegado a su superficie, sin sombra: para devolver a cero lo que la hereda |
|
|
385
|
-
| `--netzi-elevation-raised` | levantado sobre su superficie: el pulgar de un interruptor, una tecla |
|
|
386
|
-
| `--netzi-elevation-floating` | pequeño y suelto sobre el contenido: el tooltip, la etiqueta de una gráfica |
|
|
387
|
-
| `--netzi-elevation-modal` | lo que se abre encima y lo aparta: desplegables, menús, aviso, diálogos, paneles |
|
|
388
|
-
|
|
389
|
-
```css
|
|
390
|
-
.mi-tarjeta-flotante {
|
|
391
|
-
border: 1px solid var(--netzi-border);
|
|
392
|
-
border-radius: var(--netzi-radius-surface);
|
|
393
|
-
box-shadow: var(--netzi-elevation-floating);
|
|
394
|
-
}
|
|
395
|
-
.mi-punto {
|
|
396
|
-
border-radius: var(--netzi-radius-pill);
|
|
397
|
-
}
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
Una sombra **nunca es lo único** que separa una capa: lleva su borde. En oscuro las sombras son
|
|
401
|
-
más densas, en contraste alto `raised` se marca más y en papel no hay ninguna. La salida DTCG
|
|
402
|
-
publica los mismos niveles (tipo `shadow`): en móvil cada plataforma pinta el nivel a su
|
|
403
|
-
manera.
|
|
404
|
-
|
|
405
132
|
## Tema claro / oscuro
|
|
406
133
|
|
|
407
134
|
El tema se controla con el atributo `data-theme` en un ancestro (normalmente `<html>`):
|
|
@@ -412,36 +139,7 @@ El tema se controla con el atributo `data-theme` en un ancestro (normalmente `<h
|
|
|
412
139
|
</html>
|
|
413
140
|
```
|
|
414
141
|
|
|
415
|
-
Sin el atributo, aplica el tema claro (`:root`).
|
|
416
|
-
al claro dentro de una página oscura (#237): pinta lo mismo que una página clara con el preset,
|
|
417
|
-
el contraste y el cristal de la página. Si tu app redefine tokens en `:root` para el claro,
|
|
418
|
-
ponlos también en `[data-theme='light']`, como haces en `[data-theme='dark']` para el oscuro.
|
|
419
|
-
|
|
420
|
-
## Impresión
|
|
421
|
-
|
|
422
|
-
Al imprimir, el papel sale claro, opaco y quieto sin que la app haga nada:
|
|
423
|
-
|
|
424
|
-
- Los bloques que fijan `data-theme`, `data-glass` o `data-ambient` van en
|
|
425
|
-
`@media not print`: en papel no aplican y sale el tema claro y opaco, con el preset, el
|
|
426
|
-
contraste alto y la densidad intactos.
|
|
427
|
-
- En `@media print`, la raíz pierde las sombras y el desenfoque del velo, y cada duración
|
|
428
|
-
baja a `0.01ms`.
|
|
429
|
-
- El bloque de papel se declara en la raíz y en `[data-contrast='high']`, que redefine la
|
|
430
|
-
sombra pequeña: una sección con su propio contraste alto tampoco imprime sombras.
|
|
431
|
-
- El contrato de contraste se comprueba también en papel: un color que el contexto de
|
|
432
|
-
impresión redefina y no llegue a su mínimo rompe el build.
|
|
433
|
-
- `base.css` pone el papel en blanco, subraya los enlaces (en blanco y negro el color no los
|
|
434
|
-
distingue) y quita animaciones y transiciones a medio camino.
|
|
435
|
-
- Con el atributo `data-print-urls` en un enlace o en un contenedor, cada enlace externo
|
|
436
|
-
imprime su dirección detrás. Es opcional: en toda la página llenaría de direcciones el menú.
|
|
437
|
-
|
|
438
|
-
En `@netzi/ui`, el marco de `netzi-layout` y las capas flotantes no se imprimen. Un modal o
|
|
439
|
-
un drawer abierto sí: una vez, sin el velo y en el flujo de la página, donde está el
|
|
440
|
-
componente, sin tapar nada. Fijo, el navegador lo repetiría encima de cada hoja, y puede ser
|
|
441
|
-
justo lo que se quiere en papel (un recibo).
|
|
442
|
-
|
|
443
|
-
Lo propio de la app que no va en papel se oculta con su regla `@media print`. Si redefines
|
|
444
|
-
un token del tema oscuro en tu hoja, envuélvelo también en `@media not print`.
|
|
142
|
+
Sin el atributo, aplica el tema claro (`:root`).
|
|
445
143
|
|
|
446
144
|
## Overrides (white-label por app)
|
|
447
145
|
|
|
@@ -450,153 +148,22 @@ tokens que quieras en tu propio scope. Las nuevas versiones de `@netzi/tokens`
|
|
|
450
148
|
cambian solo los _defaults_; nunca pisan lo que tu app sobreescribe.
|
|
451
149
|
|
|
452
150
|
```css
|
|
453
|
-
/* tema de la app "Acme": radios
|
|
151
|
+
/* tema de la app "Acme": cambia el azul de marca y los radios */
|
|
454
152
|
:root {
|
|
153
|
+
--netzi-blue: #6c3cff;
|
|
455
154
|
--netzi-radius: 8px;
|
|
456
|
-
--netzi-radius-lg: 14px;
|
|
457
|
-
}
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
El movimiento se personaliza por las duraciones de fundido (`--netzi-duration-{fast,base,slow}`),
|
|
461
|
-
que arrastran a las de desplazamiento. Redefinir un `--netzi-duration-move-*` obliga a repetir
|
|
462
|
-
su `0.01ms` dentro de tu `@media (prefers-reduced-motion: reduce)`: ver «Movimiento».
|
|
463
|
-
|
|
464
|
-
Los colores no se cambian de uno en uno: cada token de color se pinta encima o
|
|
465
|
-
debajo de otro, y cambiar solo uno rompe el par. Para poner el color de tu marca,
|
|
466
|
-
sigue el contrato de la sección siguiente.
|
|
467
|
-
|
|
468
|
-
## Estados de interacción
|
|
469
|
-
|
|
470
|
-
Hover, foco, presionado, arrastrado, seleccionado y deshabilitado son un solo sistema (#156).
|
|
471
|
-
Cada estado es una **capa** translúcida del color del texto que se pinta encima del fondo del
|
|
472
|
-
control, sin cambiarlo; la opacidad va aparte para quien pinte la capa con su propio color:
|
|
473
|
-
|
|
474
|
-
| Token | Opacidad | Para qué |
|
|
475
|
-
| -------------------------------- | -------- | ---------------------------------------------------- |
|
|
476
|
-
| `--netzi-state-hover` | 0.08 | El puntero encima |
|
|
477
|
-
| `--netzi-state-focus` | 0.12 | Lo enfocado dentro de un compuesto (más su anillo) |
|
|
478
|
-
| `--netzi-state-pressed` | 0.12 | Mientras se pulsa, con el ratón o con el dedo |
|
|
479
|
-
| `--netzi-state-dragged` | 0.16 | La pieza que se lleva con el puntero |
|
|
480
|
-
| `--netzi-state-selected` | — | Lo seleccionado: el tinte del primario |
|
|
481
|
-
| `--netzi-state-disabled-opacity` | 0.6 | Lo deshabilitado, sobre el control entero |
|
|
482
|
-
| `--netzi-primary-pressed` | — | El relleno de marca presionado (cada preset el suyo) |
|
|
483
|
-
|
|
484
|
-
```css
|
|
485
|
-
.mi-control:active:not(:disabled) {
|
|
486
|
-
background-image: linear-gradient(var(--netzi-state-pressed), var(--netzi-state-pressed));
|
|
487
|
-
}
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
Como imagen de fondo la capa no se interpola: aparece al instante, también con movimiento
|
|
491
|
-
reducido. El build comprueba que `--netzi-text` llega a 4.5:1 sobre cada superficie con
|
|
492
|
-
cualquier capa encima y que el texto deshabilitado se queda a 3:1. Un relleno de marca no lleva
|
|
493
|
-
la capa (acercaría el fondo a su tinta): usa `--netzi-primary-pressed`.
|
|
494
|
-
|
|
495
|
-
## Marca propia (`@netzi/tokens/brand`)
|
|
496
|
-
|
|
497
|
-
La marca va en el **primario**, no en `--netzi-blue`. `--netzi-blue` es un acento de
|
|
498
|
-
Netzi y además el color de estado `--netzi-info`, y `--netzi-on-accent` (la tinta de
|
|
499
|
-
los contadores y de los rellenos de acento) se mide sobre él: cambiarlo a un morado
|
|
500
|
-
deja esa tinta en 3.35:1. Si aun así lo cambias, redefine con él `--netzi-blue-text`,
|
|
501
|
-
`--netzi-blue-dark` y `--netzi-on-accent`, y comprueba el contraste de los tres.
|
|
502
|
-
|
|
503
|
-
### El contrato: ocho tokens que se redefinen juntos
|
|
504
|
-
|
|
505
|
-
| Token | Papel | Se mide sobre | Mínimo |
|
|
506
|
-
| ------------------------- | --------------------------------------------- | ----------------------------------------------- | ------ |
|
|
507
|
-
| `--netzi-primary` | Relleno de marca: botón, interruptor, barra | (fondo de `on-primary`) | — |
|
|
508
|
-
| `--netzi-primary-hover` | El relleno al pasar el puntero | (fondo de `on-primary`) | — |
|
|
509
|
-
| `--netzi-primary-pressed` | El relleno presionado (#156) | (fondo de `on-primary`) | — |
|
|
510
|
-
| `--netzi-on-primary` | Tinta sobre el relleno, su hover y presionado | `primary`, `primary-hover`, `primary-pressed` | 4.5:1 |
|
|
511
|
-
| `--netzi-primary-dark` | Relleno de lo marcado (checkbox, radio) | cada superficie | 3:1 |
|
|
512
|
-
| `--netzi-on-primary-dark` | Tinta sobre el primario oscuro (blanco) | `primary-dark` | 3:1 |
|
|
513
|
-
| `--netzi-primary-text` | El primario que se lee (enlaces, ítem activo) | cada superficie y `primary-tint` sobre cada una | 4.5:1 |
|
|
514
|
-
| `--netzi-primary-graphic` | Lo no textual que comunica (progreso, anillo) | cada superficie y `primary-tint` sobre cada una | 3:1 |
|
|
515
|
-
|
|
516
|
-
Lo demás sale solo del primario: los tintes (`--netzi-primary-tint`, 10 % en claro y
|
|
517
|
-
15 % en oscuro; `--netzi-primary-tint-strong`, 22 % y 28 %), el anillo de foco
|
|
518
|
-
(`--netzi-focus-ring` es `--netzi-primary-text`) y el fondo ambiental. Pero el
|
|
519
|
-
relleno también se mide por ellos: `--netzi-text` tiene que llegar a 4.5:1 sobre el
|
|
520
|
-
tinte marcado y el pulgar de las barras de desplazamiento (`--netzi-text-2`) a 3:1
|
|
521
|
-
sobre el suave. Todo en claro y en oscuro, sobre `bg`, `surface`, `surface-2` y
|
|
522
|
-
`surface-3`; el alto contraste no cambia el primario y solo sube los textos.
|
|
523
|
-
|
|
524
|
-
### Derivarlo de un color
|
|
525
|
-
|
|
526
|
-
`deriveBrand` devuelve los ocho tokens de cada modo ya calibrados. El relleno es tu
|
|
527
|
-
color tal cual mientras alguna de las dos tintas del kit (`#04121f` o blanco) llegue a
|
|
528
|
-
4.5:1 encima; en los tonos medios no llega ninguna, y entonces se mueve al tono más
|
|
529
|
-
cercano que sí (`adjusted: true`). El texto, el gráfico y el primario oscuro son el
|
|
530
|
-
tono más cercano al relleno que llega a su mínimo en cada modo; el hover oscurece lo
|
|
531
|
-
justo para notarse sin perder la tinta, y el presionado es el hover con la capa de
|
|
532
|
-
presionado (12 %) del extremo contrario a la tinta, que la aleja en vez de acercarla.
|
|
533
|
-
|
|
534
|
-
```js
|
|
535
|
-
import { brandVariables, deriveBrand, validateBrand } from '@netzi/tokens/brand';
|
|
536
|
-
|
|
537
|
-
const marca = deriveBrand('#6c3cff'); // { color, adjusted, light, dark }
|
|
538
|
-
validateBrand(marca).ok; // true
|
|
539
|
-
brandVariables(marca.dark); // { '--netzi-primary': '#6c3cff', '--netzi-primary-text': '#9f80ff', … }
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
En CSS, el resultado para el morado de «Acme». Carga esta hoja **después** de
|
|
543
|
-
`@netzi/tokens` y no pongas `data-preset`, que redefine el primario:
|
|
544
|
-
|
|
545
|
-
<!-- ejemplo-marca -->
|
|
546
|
-
|
|
547
|
-
```css
|
|
548
|
-
/* Marca "Acme": deriveBrand('#6c3cff') de @netzi/tokens/brand */
|
|
549
|
-
[data-theme='light'],
|
|
550
|
-
:root {
|
|
551
|
-
--netzi-primary: #6c3cff;
|
|
552
|
-
--netzi-primary-hover: #5f35e0;
|
|
553
|
-
--netzi-primary-pressed: #542fc5;
|
|
554
|
-
--netzi-primary-dark: #6c3cff;
|
|
555
|
-
--netzi-primary-text: #693af7;
|
|
556
|
-
--netzi-primary-graphic: #6c3cff;
|
|
557
|
-
--netzi-on-primary: #ffffff;
|
|
558
|
-
--netzi-on-primary-dark: #ffffff;
|
|
559
155
|
}
|
|
560
156
|
|
|
561
157
|
[data-theme='dark'] {
|
|
562
|
-
--netzi-
|
|
563
|
-
--netzi-primary-hover: #5f35e0;
|
|
564
|
-
--netzi-primary-pressed: #542fc5;
|
|
565
|
-
--netzi-primary-dark: #764aff;
|
|
566
|
-
--netzi-primary-text: #9f80ff;
|
|
567
|
-
--netzi-primary-graphic: #7f55ff;
|
|
568
|
-
--netzi-on-primary: #ffffff;
|
|
569
|
-
--netzi-on-primary-dark: #ffffff;
|
|
158
|
+
--netzi-surface: #101522;
|
|
570
159
|
}
|
|
571
160
|
```
|
|
572
161
|
|
|
573
|
-
La regla clara va también en `[data-theme='light']`: el paquete vuelve a declarar ahí los
|
|
574
|
-
valores claros de las capas para una sección clara dentro de una página oscura (#237), y sin
|
|
575
|
-
ella la sección perdería la marca. Un test del paquete lee este bloque: si deja de cumplir, o
|
|
576
|
-
de ser lo que da `deriveBrand('#6c3cff')`, la suite se pone roja.
|
|
577
|
-
|
|
578
|
-
### Validar una marca hecha a mano
|
|
579
|
-
|
|
580
|
-
`validateBrand({ light, dark })` mide cada par del contrato y devuelve
|
|
581
|
-
`{ ok, checks, failures }`; cada fallo dice el modo, la tinta, el fondo, el ratio y el
|
|
582
|
-
mínimo. Lanza `TypeError` si falta un modo o un token no es `#rgb` o `#rrggbb`. Mide contra las
|
|
583
|
-
superficies del tema por defecto: si tu app redefine también las superficies, ya no
|
|
584
|
-
es este contrato, y conviene medir el resultado en la página. Sobre las capas de
|
|
585
|
-
**cristal** el texto se lee contra lo que haya detrás; el kit lo comprueba para sus
|
|
586
|
-
presets, no para una marca propia.
|
|
587
|
-
|
|
588
|
-
En Angular, `@netzi/ui` lo hace por ti: `provideNetziBrand('#6c3cff')` (o
|
|
589
|
-
`NetziThemeService.setBrand`) deriva la marca, la escribe en una hoja propia por encima
|
|
590
|
-
del preset (en claro, en cada sección clara y en cada sección oscura) y, en desarrollo, avisa en la consola si el color no cumple tal cual.
|
|
591
|
-
|
|
592
|
-
El contrato no es una copia: un test del paquete mete lo que deriva `deriveBrand` en la
|
|
593
|
-
fuente DTCG y le pasa el mismo contrato de contraste que el build, en claro, oscuro y
|
|
594
|
-
alto contraste.
|
|
595
|
-
|
|
596
162
|
## Catálogo de tokens
|
|
597
163
|
|
|
598
164
|
| Grupo | Tokens |
|
|
599
165
|
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
166
|
+
| Marca | `--netzi-blue` `--netzi-blue-dark` `--netzi-green` `--netzi-purple` `--netzi-red` `--netzi-yellow` |
|
|
600
167
|
| Estado | `--netzi-info` `--netzi-success` `--netzi-warning` `--netzi-danger` (+ su `-text`) |
|
|
601
168
|
| Superficies | `--netzi-bg` `--netzi-surface` `--netzi-surface-2` `--netzi-surface-3` |
|
|
602
169
|
| Bordes | `--netzi-border` `--netzi-border-2` |
|
|
@@ -604,21 +171,16 @@ alto contraste.
|
|
|
604
171
|
| Velo modal | `--netzi-scrim` `--netzi-scrim-filter` |
|
|
605
172
|
| Lente | `--netzi-float-lens` `--netzi-float-lens-size` (opt-in, ver abajo) |
|
|
606
173
|
| Texto | `--netzi-text` `--netzi-text-2` `--netzi-text-3` `--netzi-on-accent` |
|
|
607
|
-
|
|
|
174
|
+
| Sombras | `--netzi-shadow-sm` `--netzi-shadow` `--netzi-shadow-lg` |
|
|
608
175
|
| Acento | `--netzi-tint` `--netzi-primary-tint` `--netzi-primary-tint-strong` |
|
|
609
|
-
| Forma | `--netzi-radius
|
|
610
|
-
|
|
|
611
|
-
| Tipografía | `--netzi-font-sans` `--netzi-font-mono` `--netzi-font-scale` `--netzi-typography-*` `--netzi-measure` |
|
|
612
|
-
| Espaciado | `--netzi-space-{related,group,stack,section,page}` `--netzi-space-inset` (`-sm`, `-lg`) |
|
|
613
|
-
| Movimiento | `--netzi-duration-{instant,fast,base,slow}` `--netzi-duration-move-{fast,base,slow}` `--netzi-ease-{standard,enter,exit}` |
|
|
614
|
-
| Capas | `--netzi-layer-{content,sticky,bar,flyout,scrim,modal,dropdown,toast,tooltip,blocking,top}` |
|
|
615
|
-
|
|
616
|
-
El catálogo son los tokens **públicos**: los que puedes usar y redefinir. La lista exacta va
|
|
617
|
-
en el paquete (`public-tokens.json`, ver «Públicos e internos»).
|
|
176
|
+
| Forma | `--netzi-radius` `--netzi-radius-lg` |
|
|
177
|
+
| Tipografía | `--netzi-font-sans` `--netzi-font-mono` `--netzi-font-scale` `--netzi-font-size-{xs…3xl}` `--netzi-line-height-*` `--netzi-font-weight-*` |
|
|
618
178
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
179
|
+
Alias por **simetría**, para que el nombre que se da por hecho exista:
|
|
180
|
+
`--netzi-surface-1`, `--netzi-text-1` y `--netzi-radius-md` apuntan a
|
|
181
|
+
`--netzi-surface`, `--netzi-text` y `--netzi-radius`. Un token que **no** existe
|
|
182
|
+
no da error: la declaración entera se descarta y el elemento se queda sin fondo,
|
|
183
|
+
sin color o sin radio, sin aviso en build ni en consola.
|
|
622
184
|
|
|
623
185
|
### Un panel de cristal entra por transición, nunca por animación
|
|
624
186
|
|
|
@@ -660,18 +222,18 @@ cara, un vídeo de fondo).
|
|
|
660
222
|
|
|
661
223
|
### Estados y tintes: relleno o texto, nunca los dos
|
|
662
224
|
|
|
663
|
-
`--netzi-success` y compañía son **relleno** (un punto de estado, un fondo
|
|
664
|
-
`-text`, que es la versión que llega a 4.5:1. Con los
|
|
665
|
-
lado: `--netzi-primary-tint` (10 %) es
|
|
666
|
-
|
|
225
|
+
`--netzi-success` y compañía son **relleno** (un punto de estado, un fondo, una
|
|
226
|
+
barra). Para texto va su `-text`, que es la versión que llega a 4.5:1. Con los
|
|
227
|
+
tintes del primario pasa lo mismo por otro lado: `--netzi-primary-tint` (10 %) es
|
|
228
|
+
para superficies grandes y aguanta `--netzi-primary-text` justo; en una pieza
|
|
229
|
+
pequeña se pierde contra el fondo, y para eso está
|
|
667
230
|
`--netzi-primary-tint-strong` (22 %), cuya tinta es `--netzi-text`.
|
|
668
231
|
|
|
669
232
|
Lo mismo vale para el primario y los acentos a secas: `--netzi-primary`,
|
|
670
233
|
`--netzi-blue`, `--netzi-green`… son **relleno** y no llegan a 4.5:1 como texto
|
|
671
|
-
sobre fondo claro (`--netzi-blue` da 2.
|
|
672
|
-
`--netzi-primary-
|
|
673
|
-
|
|
674
|
-
preset. Es lo que le pasó al botón `soft` (#56).
|
|
234
|
+
sobre fondo claro (`--netzi-blue` da 2.9:1; `--netzi-primary-dark`, 4.3:1). Si se
|
|
235
|
+
lee, va `--netzi-primary-text` o el `-text` del color, que están calibrados por
|
|
236
|
+
tema y por preset. Es lo que le pasó al botón `soft` (#56).
|
|
675
237
|
|
|
676
238
|
Y un relleno del primario tiene **dos fondos oscuros** según lo que lleve encima.
|
|
677
239
|
`--netzi-primary-hover` es el del estado hover de un botón relleno: su tinta es la
|
|
@@ -680,70 +242,6 @@ misma `--netzi-on-primary` del reposo, y cada preset lo calibra para que no baje
|
|
|
680
242
|
(`--netzi-on-primary-dark`): la pista de un interruptor encendido, la marca de un
|
|
681
243
|
checkbox. Si se cruzan, la tinta oscura sobre el azul oscuro se queda en 3.9:1 (#68).
|
|
682
244
|
|
|
683
|
-
### Lo no textual que comunica: `--netzi-primary-graphic`
|
|
684
|
-
|
|
685
|
-
El relleno de una barra de progreso, un anillo de carga, una barra de navegación: no son
|
|
686
|
-
texto, pero dicen algo, y WCAG 1.4.11 les pide **3:1** frente a lo que tienen al lado. El
|
|
687
|
-
primario crudo no llega en claro con azul (2.15:1 en el peor fondo), verde (1.36), naranja
|
|
688
|
-
(1.78), rojo (2.51) ni cian (1.92). `--netzi-primary-graphic` es el tono más cercano al
|
|
689
|
-
primario que llega a 3:1 sobre cada superficie y sobre `--netzi-primary-tint` (el fondo de un
|
|
690
|
-
ítem activo), calibrado por preset y por tema; su contrato `non-text` lo comprueba el build en
|
|
691
|
-
las 24 combinaciones (#140). `--netzi-primary-text` también cumple, pero se aleja más del
|
|
692
|
-
color de marca.
|
|
693
|
-
|
|
694
|
-
Dos casos en que no basta:
|
|
695
|
-
|
|
696
|
-
- **Lo que late en opacidad.** En el valle del latido el color se mezcla con el fondo y
|
|
697
|
-
baja; con el valle de `netzi-progress` (0,75) `--netzi-primary-graphic` se queda por debajo de
|
|
698
|
-
3:1. Lo que late va con `--netzi-primary-text`, que deja margen.
|
|
699
|
-
- **Los colores de estado.** Una barra de éxito, aviso o error va con su `-text`
|
|
700
|
-
(`--netzi-success-text`…) o con su `-graphic` (abajo): el crudo da 1.43:1 (verde) o
|
|
701
|
-
1.50:1 (amarillo) en claro.
|
|
702
|
-
|
|
703
|
-
Un degradado cuenta en cada punto que se ve: si se desvanece hasta transparente, su cola
|
|
704
|
-
baja de cualquier mínimo. El del kit va de un primario que cumple a otro que cumple.
|
|
705
|
-
|
|
706
|
-
### Lo no textual de un estado: `--netzi-*-graphic` y `--netzi-*-veil`
|
|
707
|
-
|
|
708
|
-
La estrella marcada, el punto de presencia de un avatar, el borde de un campo inválido o el
|
|
709
|
-
icono de un resultado también son no textuales que comunican, y el crudo del estado no llega
|
|
710
|
-
en claro: azul 2.08:1, verde 1.33, amarillo 1.41 y rojo 2.15 en el peor fondo (#189). Cada
|
|
711
|
-
estado tiene su gráfico, el tono más cercano al crudo que llega a **3:1** sobre cada superficie
|
|
712
|
-
y sobre su propio velo. En oscuro el crudo ya cumple y es su valor.
|
|
713
|
-
|
|
714
|
-
| Token | Claro | Oscuro | Velo (14 %) |
|
|
715
|
-
| ------------------------- | --------- | --------- | ---------------------- |
|
|
716
|
-
| `--netzi-info-graphic` | `#0e84cd` | `#0ba5ff` | `--netzi-info-veil` |
|
|
717
|
-
| `--netzi-success-graphic` | `#069047` | `#0ae972` | `--netzi-success-veil` |
|
|
718
|
-
| `--netzi-warning-graphic` | `#9d7a0c` | `#f0c040` | `--netzi-warning-veil` |
|
|
719
|
-
| `--netzi-danger-graphic` | `#df464b` | `#ff6b6b` | `--netzi-danger-veil` |
|
|
720
|
-
|
|
721
|
-
Los alias de estado apuntan a los de marca (`--netzi-blue-graphic`, `--netzi-green-graphic`,
|
|
722
|
-
`--netzi-yellow-graphic`, `--netzi-red-graphic`), como los `-text`. El velo es el fondo redondo
|
|
723
|
-
de un icono de estado: el contrato `non-text` de cada gráfico lo mide compuesto sobre cada
|
|
724
|
-
superficie, en las 24 combinaciones de modo, contraste y preset. Si pones un icono sobre una
|
|
725
|
-
mezcla más opaca, ya no está medido.
|
|
726
|
-
|
|
727
|
-
### Con el dedo, objetivos de 44 px (`--netzi-touch-target`)
|
|
728
|
-
|
|
729
|
-
Con puntero táctil (`@media (pointer: coarse)`) nada de lo que se toca en un campo baja de
|
|
730
|
-
`--netzi-touch-target` (44 px, WCAG 2.5.5). Los tokens suben `--netzi-control-h-sm` y
|
|
731
|
-
`--netzi-control-h-md` a 46 px también con la densidad compacta (el borde de 1 px del
|
|
732
|
-
contenedor no le quita al input), y cada componente agranda lo suyo: filas de casillas y
|
|
733
|
-
radios, opciones, días del calendario, chips, estrellas, la franja de los sliders… Los
|
|
734
|
-
iconos pequeños (las × de los chips, la flecha de un desplegable) amplían solo su zona de toque, sin mover
|
|
735
|
-
el dibujo. Con ratón no cambia nada. Una app que ponga controles propios puede usar el
|
|
736
|
-
mismo token en su `@media (pointer: coarse)`.
|
|
737
|
-
|
|
738
|
-
Entre dos objetivos vecinos queda además `--netzi-touch-gap` (8 px, criterio A.5 de la
|
|
739
|
-
política 17), medido entre zonas de toque y no entre dibujos: botones de la paginación,
|
|
740
|
-
estrellas, pestañas, chips, celdas, días del calendario, ítems de un menú, la barra del
|
|
741
|
-
editor… Las piezas de un control segmentado se tocan a propósito y quedan fuera, como pide
|
|
742
|
-
la política. También quedan fuera, mientras la política no las recoja (#226), las piezas de
|
|
743
|
-
un campo de una línea (el input y su botón: −/+, el ojo, la flecha del desplegable) y las
|
|
744
|
-
opciones de una lista. El token es para usarlo en un `@media (pointer: coarse)` propio; con
|
|
745
|
-
ratón, cada componente conserva su hueco.
|
|
746
|
-
|
|
747
245
|
### El foco va con `--netzi-focus-ring`, no con el primario
|
|
748
246
|
|
|
749
247
|
Un indicador de foco, contorno o borde, tiene que llegar a **3:1** sobre el fondo (WCAG
|
|
@@ -754,8 +252,8 @@ en cada elemento con `data-theme` o `data-preset`, así que una sección oscura
|
|
|
754
252
|
página clara tiene su propio anillo.
|
|
755
253
|
|
|
756
254
|
Todo `:focus`, `:focus-visible` y `:focus-within` del kit lo usa como contorno o borde (los
|
|
757
|
-
halos del tinte no cuentan: dan 1.1:1). Dos guardianes de
|
|
758
|
-
al primario y quitar el contorno sin poner otro indicador (#76).
|
|
255
|
+
halos del tinte no cuentan: dan 1.1:1). Dos guardianes de `tokens-contrast.spec.ts` impiden
|
|
256
|
+
volver al primario y quitar el contorno sin poner otro indicador (#76).
|
|
759
257
|
|
|
760
258
|
Sobre una capa de **cristal** el anillo se ve contra lo que haya detrás: sobre el fondo del
|
|
761
259
|
kit cumple, pero con una imagen muy oscura (en claro) o muy clara (en oscuro) debajo puede
|
|
@@ -779,14 +277,12 @@ con significado (SC 1.4.11). Por eso `--netzi-text-3` **no vale para texto**: si
|
|
|
779
277
|
lo que pintas se lee, va `--netzi-text-2`.
|
|
780
278
|
|
|
781
279
|
Con `data-contrast='high'` cada nivel toma el valor del de encima: `text-2` sube a
|
|
782
|
-
|
|
783
|
-
|
|
280
|
+
7.1:1 y `text-3` a 4.8:1, así que el modo cumple incluso donde alguien haya usado
|
|
281
|
+
`text-3` para un rótulo.
|
|
784
282
|
|
|
785
|
-
Los ratios
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
generar `tokens.css`. Si un valor deja de cumplir, el paquete no se construye. Ver
|
|
789
|
-
«Cómo se genera» al final.
|
|
283
|
+
Los ratios están **medidos sobre este mismo `tokens.css`** por
|
|
284
|
+
`tokens-contrast.spec.ts` en `@netzi/ui`: si cambias un valor y deja de cumplir, la
|
|
285
|
+
suite se pone roja.
|
|
790
286
|
|
|
791
287
|
## Capas flotantes y superficies de cristal
|
|
792
288
|
|
|
@@ -810,8 +306,9 @@ de un botón) hereda el vidrio sin saber que está en una capa. Con cristal son
|
|
|
810
306
|
tintes translúcidos **oscuros** que se alejan de la lámina un paso, dos y tres
|
|
811
307
|
(una tarjeta es más gris que la lámina, como en opaco). En claro eso resta
|
|
812
308
|
contraste, y por eso `--netzi-text-2` con cristal baja dos niveles (el mismo
|
|
813
|
-
valor que en alto contraste, `#
|
|
814
|
-
sobre el tinte más fuerte siga por encima de
|
|
309
|
+
valor que en alto contraste, `#354049`);
|
|
310
|
+
`tokens-contrast.spec.ts` exige que sobre el tinte más fuerte siga por encima de
|
|
311
|
+
4.5:1 incluso con negro puro debajo.
|
|
815
312
|
|
|
816
313
|
Con el cristal apagado valen exactamente lo mismo que los tokens de siempre, así
|
|
817
314
|
que no cambia nada. Con `data-glass="on"` en un ancestro (lo pone
|
|
@@ -831,7 +328,7 @@ propósito: ahí el cristal solo resta legibilidad.
|
|
|
831
328
|
|
|
832
329
|
Un cristal sobre un fondo liso se ve como una placa gris: no hay nada detrás
|
|
833
330
|
que atravesar. Con `data-ambient="on"` en la raíz (`NetziThemeService.setAmbient`,
|
|
834
|
-
interruptor «Fondo
|
|
331
|
+
interruptor «Fondo ambiental» en `netzi-settings`) el layout pinta bajo
|
|
835
332
|
`--netzi-bg` unas manchas de color suaves —el primario del preset, morado y
|
|
836
333
|
verde— que se ven a través del topbar, del sidebar y de cualquier capa que pase
|
|
837
334
|
por encima. Token: `--netzi-ambient` (`none` sin el eje). Los porcentajes son
|
|
@@ -859,149 +356,14 @@ Bastan **0.44** de alfa y brillo 1.25 en claro,
|
|
|
859
356
|
**0.12** y brillo 0.56 en oscuro, 10 px de desenfoque en los dos. El precio es
|
|
860
357
|
el plano contrario puro debajo (negro en claro, blanco en oscuro): ahí el texto
|
|
861
358
|
secundario se queda en **4.1-4.2:1**, y el primario no baja de 4.5:1
|
|
862
|
-
nunca; contra el fondo del kit y contra un gris medio, ambos pasan de 6:1.
|
|
863
|
-
|
|
864
|
-
|
|
359
|
+
nunca; contra el fondo del kit y contra un gris medio, ambos pasan de 6:1. `tokens-contrast.spec.ts`
|
|
360
|
+
modela la cadena entera, no solo el alfa: tocar cualquiera de sus funciones mueve
|
|
361
|
+
el veredicto.
|
|
865
362
|
|
|
866
363
|
Degradación automática, sin JS y sin polyfill: con
|
|
867
364
|
`prefers-reduced-transparency: reduce` y donde no haya `backdrop-filter`, la
|
|
868
365
|
superficie opaca de siempre.
|
|
869
366
|
|
|
870
|
-
## Públicos e internos
|
|
871
|
-
|
|
872
|
-
`tokens.css` declara todo lo que el kit necesita, pero no todo es para las apps. Cada token de
|
|
873
|
-
la fuente dice si es **público** (el contrato: lo puedes usar y redefinir, y cambiarlo de
|
|
874
|
-
forma incompatible sigue el procedimiento de desuso) o **interno** (materia prima de la fuente
|
|
875
|
-
o pieza del kit: puede cambiar o desaparecer en cualquier versión).
|
|
876
|
-
|
|
877
|
-
- La capa **semántica** es pública entera: superficies, texto, bordes, primario, estados,
|
|
878
|
-
elevación, capas, espaciado y radios por papel, estilos de texto, familias, duraciones y
|
|
879
|
-
curvas.
|
|
880
|
-
- Las **primitivas** son internas: son la materia prima de la fuente (política 17). Los colores
|
|
881
|
-
de marca crudos (`blue`, `green`, `yellow`, `red`, `purple` y `blue-dark`) se usan por el
|
|
882
|
-
primario y los estados, que siguen al preset y al contraste alto, y `radius-full` por
|
|
883
|
-
`radius-pill`. Las escalas con nombre de paso (espacio, radios, tamaños, pesos e
|
|
884
|
-
interlineados) siguen públicas **en desuso** mientras convive su retirada (ver abajo).
|
|
885
|
-
- Las de **componente** son internas salvo las que el kit ofrece: capas flotantes, velo,
|
|
886
|
-
controles, objetivo táctil, anillo de foco, paleta de gráficas y fondo ambiental. Quedan
|
|
887
|
-
internos los pulgares de los interruptores y de las barras de desplazamiento.
|
|
888
|
-
|
|
889
|
-
La lista va en el paquete, generada por el build en el orden de la fuente:
|
|
890
|
-
|
|
891
|
-
```js
|
|
892
|
-
import publicos from '@netzi/tokens/public-tokens.json' with { type: 'json' };
|
|
893
|
-
|
|
894
|
-
// [{ name: '--netzi-primary-text', path: 'primary.text', layer: 'semantic' }, …]
|
|
895
|
-
const nombres = new Set(publicos.tokens.map((t) => t.name));
|
|
896
|
-
```
|
|
897
|
-
|
|
898
|
-
Cada entrada lleva su custom property, su ruta en la fuente (el nombre canónico), su capa
|
|
899
|
-
(`theme` si solo existe en un tema, como la lente del cristal) y, si está en desuso, el
|
|
900
|
-
aviso. La salida DTCG resuelta marca lo mismo en `$extensions["tech.netzi"].visibility`. Un
|
|
901
|
-
test del paquete falla si este README, el contrato de marca o el sustituto de un token en
|
|
902
|
-
desuso dependen de un nombre que no sea público.
|
|
903
|
-
|
|
904
|
-
## En desuso
|
|
905
|
-
|
|
906
|
-
Un token en desuso sigue saliendo en `tokens.css` con el mismo valor que su sustituto
|
|
907
|
-
(apunta a él), así que nada se rompe al actualizar; convive al menos una beta publicada y se
|
|
908
|
-
retira en un cambio incompatible propio, con su guía de migración (ADR 0012). Mientras
|
|
909
|
-
tanto lo marcan:
|
|
910
|
-
|
|
911
|
-
- `$deprecated` en la fuente DTCG y en la salida resuelta, con el sustituto y la versión;
|
|
912
|
-
- un comentario `/* deprecated: … */` encima de su declaración en `tokens.css`;
|
|
913
|
-
- el build, que los lista cada vez que corre;
|
|
914
|
-
- y esta tabla.
|
|
915
|
-
|
|
916
|
-
Cuando el paquete llega a la versión de retirada (o la pasa), el build **avisa sin fallar**:
|
|
917
|
-
«el token X debía retirarse en @netzi/tokens 0.1.0-beta.11; retíralo o mueve la versión». Es
|
|
918
|
-
el recordatorio de que el sinónimo ya ha convivido lo que tocaba; retirarlo es un cambio
|
|
919
|
-
incompatible propio, y el momento lo decide quien corta la release.
|
|
920
|
-
|
|
921
|
-
| En desuso | Usa | Deprecado en | Se retira, como pronto |
|
|
922
|
-
| ------------------- | ---------------------------- | ----------------------------- | ----------------------------- |
|
|
923
|
-
| `--netzi-surface-1` | `--netzi-surface` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
924
|
-
| `--netzi-text-1` | `--netzi-text` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
925
|
-
| `--netzi-radius-md` | `--netzi-radius-surface-sm` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
926
|
-
| `--netzi-shadow-sm` | `--netzi-elevation-raised` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
927
|
-
| `--netzi-shadow` | `--netzi-elevation-floating` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
928
|
-
| `--netzi-shadow-lg` | `--netzi-elevation-modal` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
929
|
-
|
|
930
|
-
El nombre canónico de cada papel es la raíz de su grupo (`surface`, `text`), que es el que usa
|
|
931
|
-
la política de diseño como nombre de ruta; el radio medio es el de una superficie pequeña. Para migrar basta con buscar y
|
|
932
|
-
sustituir: `var(--netzi-surface-1)` por `var(--netzi-surface)`, y lo mismo con los demás.
|
|
933
|
-
`@netzi/ui` y el playground ya solo usan los canónicos, y un guardián lo vigila.
|
|
934
|
-
|
|
935
|
-
Las sombras de antes (`shadow-sm`, `shadow`, `shadow-lg`) pasan a la escala de elevación
|
|
936
|
-
(#220): mismo valor en cada tema, con nombre de intención. Como el anillo de foco, se vuelven a
|
|
937
|
-
declarar en cada sección con su propio tema o contraste, así que siguen al tema igual que
|
|
938
|
-
antes. Lo mismo hacen los otros tres sinónimos.
|
|
939
|
-
|
|
940
|
-
### Escalas que pasan a internas
|
|
941
|
-
|
|
942
|
-
La política de diseño reserva las primitivas a la fuente: una app usa papeles. Las escalas con
|
|
943
|
-
nombre de paso eran públicas porque este README las enseñaba; desde `@netzi/tokens`
|
|
944
|
-
`0.1.0-beta.10` cada una tiene su papel y la escala está en desuso para las apps (#228). No
|
|
945
|
-
desaparecen: los papeles se apoyan en ellas, así que siguen en `tokens.css` con su valor y, al
|
|
946
|
-
retirarse, **pasan a internas** (salen de `public-tokens.json` y pueden cambiar sin aviso). Se
|
|
947
|
-
marcan igual que un sinónimo (`$deprecated`, el comentario en `tokens.css`, el build, esta
|
|
948
|
-
tabla), y el build avisa cuando el paquete llega a la versión:
|
|
949
|
-
|
|
950
|
-
| En desuso | Usa | Deprecado en | Pasa a interna, como pronto |
|
|
951
|
-
| ---------------------------- | ---------------------------------------------------------------------- | ----------------------------- | ----------------------------- |
|
|
952
|
-
| `--netzi-space-0` | `0` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
953
|
-
| `--netzi-space-1` | `--netzi-space-related` (cambia el valor: 2px no es un paso del ritmo) | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
954
|
-
| `--netzi-space-2` | `--netzi-space-related` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
955
|
-
| `--netzi-space-3` | `--netzi-space-group` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
956
|
-
| `--netzi-space-4` | `--netzi-space-stack` o `--netzi-space-inset-sm` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
957
|
-
| `--netzi-space-5` | `--netzi-space-inset` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
958
|
-
| `--netzi-space-6` | `--netzi-space-inset-lg` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
959
|
-
| `--netzi-space-7` | `--netzi-space-section` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
960
|
-
| `--netzi-space-8` | `--netzi-space-page` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
961
|
-
| `--netzi-radius-sm` | `--netzi-radius-control` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
962
|
-
| `--netzi-radius` | `--netzi-radius-surface-sm` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
963
|
-
| `--netzi-radius-lg` | `--netzi-radius-surface` | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
964
|
-
| `--netzi-font-size-{xs…3xl}` | el estilo de su papel (`caption` … `display`, arriba) | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
965
|
-
| `--netzi-font-weight-*` | el estilo de su papel (`medium` no tiene: `body` cambia el valor) | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
966
|
-
| `--netzi-line-height-*` | el estilo de su papel (`none` y `relaxed` no tienen: cambia el valor) | `@netzi/tokens 0.1.0-beta.10` | `@netzi/tokens 0.1.0-beta.11` |
|
|
967
|
-
|
|
968
|
-
Para migrar el espaciado y los radios basta con buscar y sustituir por el papel de cada uso
|
|
969
|
-
(`var(--netzi-space-3)` por `var(--netzi-space-group)`; el `4` tiene dos papeles, y el que
|
|
970
|
-
toca lo dice el sitio: aire entre grupos o relleno). Para el texto, cambia el trío
|
|
971
|
-
`font-size` + `font-weight` + `line-height` por el atajo del estilo:
|
|
972
|
-
|
|
973
|
-
```css
|
|
974
|
-
/* Antes */
|
|
975
|
-
.meta {
|
|
976
|
-
font-size: var(--netzi-font-size-xs);
|
|
977
|
-
font-weight: var(--netzi-font-weight-semibold);
|
|
978
|
-
line-height: var(--netzi-line-height-tight);
|
|
979
|
-
}
|
|
980
|
-
/* Después */
|
|
981
|
-
.meta {
|
|
982
|
-
font: var(--netzi-typography-caption);
|
|
983
|
-
letter-spacing: var(--netzi-typography-caption-letter-spacing);
|
|
984
|
-
}
|
|
985
|
-
```
|
|
986
|
-
|
|
987
|
-
Las duraciones, las curvas y las familias no cambian: ya tenían nombre de intención y pasan a
|
|
988
|
-
la capa semántica con el mismo nombre. `@netzi/ui` y el playground ya solo usan los papeles, y
|
|
989
|
-
el mismo guardián de los sinónimos lo vigila.
|
|
990
|
-
|
|
991
|
-
## Cómo se genera
|
|
992
|
-
|
|
993
|
-
`tokens.css` **no se escribe a mano**: sale de una fuente única en JSON con el formato del
|
|
994
|
-
W3C Design Tokens Community Group (DTCG 2025.10), con Style Dictionary. La fuente tiene
|
|
995
|
-
tres capas —primitivos (marca y escalas), semánticos (papeles: superficie, texto, borde,
|
|
996
|
-
primario, estado) y de componente (controles, capas flotantes, foco)— y un archivo por eje
|
|
997
|
-
de tema (modo, preset, contraste, cristal, fondo ambiental, densidad, puntero táctil y
|
|
998
|
-
movimiento reducido).
|
|
999
|
-
|
|
1000
|
-
La misma fuente sirve a quien no lee CSS: una salida DTCG ya resuelta, un archivo por
|
|
1001
|
-
combinación de modo, contraste y preset, pensada para librerías nativas (Compose,
|
|
1002
|
-
SwiftUI). En CSS, las referencias entre tokens se mantienen como `var()`, así que un
|
|
1003
|
-
override en tu scope sigue arrastrando a los tokens que se apoyan en el tuyo.
|
|
1004
|
-
|
|
1005
367
|
## Versionado
|
|
1006
368
|
|
|
1007
369
|
SemVer. Cambiar el **valor** de un token es `minor`/`patch`; **renombrar o quitar**
|