@eduardoalvarez/arrecife 0.5.1 → 0.7.0

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.
Files changed (78) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/README.md +868 -467
  3. package/dist/brand/index.cjs +112 -95
  4. package/dist/brand/index.d.cts +40 -39
  5. package/dist/brand/index.d.ts +40 -39
  6. package/dist/brand/index.js +5 -4
  7. package/dist/catalog-D13txprv.d.cts +78 -0
  8. package/dist/catalog-D13txprv.d.ts +78 -0
  9. package/dist/chart/index.cjs +100 -83
  10. package/dist/chart/index.d.cts +66 -66
  11. package/dist/chart/index.d.ts +66 -66
  12. package/dist/chart/index.js +14 -12
  13. package/dist/chunk-2WPWEIMD.js +27 -0
  14. package/dist/chunk-45HVCTB7.js +70 -0
  15. package/dist/{chunk-ZEOQKRQ7.js → chunk-727HCBD4.js} +1 -1
  16. package/dist/chunk-CKRSQPTX.js +36 -0
  17. package/dist/chunk-E6KFUSKB.js +144 -0
  18. package/dist/chunk-GCRII2KQ.js +86 -0
  19. package/dist/{chunk-YZ2SDOVZ.js → chunk-JN3IS5OS.js} +30 -30
  20. package/dist/chunk-ODBFN44D.js +45 -0
  21. package/dist/chunk-OMKSESQB.js +300 -0
  22. package/dist/{chunk-VPT32GPG.js → chunk-TA7TLWW4.js} +2 -2
  23. package/dist/chunk-WGNIRIN7.js +42 -0
  24. package/dist/doctor.mjs +166 -0
  25. package/dist/form/index.cjs +109 -92
  26. package/dist/form/index.d.cts +43 -42
  27. package/dist/form/index.d.ts +43 -42
  28. package/dist/form/index.js +25 -23
  29. package/dist/icons/index.cjs +149 -0
  30. package/dist/icons/index.d.cts +94 -0
  31. package/dist/icons/index.d.ts +94 -0
  32. package/dist/icons/index.js +28 -0
  33. package/dist/index-DlAO2JZs.d.cts +47 -0
  34. package/dist/index-DlAO2JZs.d.ts +47 -0
  35. package/dist/index.cjs +1292 -983
  36. package/dist/index.d.cts +927 -806
  37. package/dist/index.d.ts +927 -806
  38. package/dist/index.js +809 -778
  39. package/dist/{label-DuTvJGxD.d.ts → label-MgHFKnFy.d.cts} +3 -3
  40. package/dist/{label-DuTvJGxD.d.cts → label-MgHFKnFy.d.ts} +3 -3
  41. package/dist/og/index.cjs +133 -132
  42. package/dist/og/index.d.cts +93 -89
  43. package/dist/og/index.d.ts +93 -89
  44. package/dist/og/index.js +106 -106
  45. package/dist/shiki/index.cjs +28 -30
  46. package/dist/shiki/index.d.cts +4 -4
  47. package/dist/shiki/index.d.ts +4 -4
  48. package/dist/shiki/index.js +12 -12
  49. package/dist/social/index.cjs +67 -0
  50. package/dist/social/index.d.cts +2 -0
  51. package/dist/social/index.d.ts +2 -0
  52. package/dist/social/index.js +2 -0
  53. package/dist/theme/index.cjs +97 -0
  54. package/dist/theme/index.d.cts +144 -0
  55. package/dist/theme/index.d.ts +144 -0
  56. package/dist/theme/index.js +2 -0
  57. package/dist/tokens/index.cjs +159 -88
  58. package/dist/tokens/index.d.cts +277 -165
  59. package/dist/tokens/index.d.ts +277 -165
  60. package/dist/tokens/index.js +2 -2
  61. package/dist/tokens/theme.css +165 -100
  62. package/dist/variants/index.cjs +195 -0
  63. package/dist/variants/index.d.cts +195 -0
  64. package/dist/variants/index.d.ts +195 -0
  65. package/dist/variants/index.js +3 -0
  66. package/llms.txt +1145 -746
  67. package/package.json +42 -11
  68. package/dist/catalogo-Du5ID-Hi.d.cts +0 -77
  69. package/dist/catalogo-Du5ID-Hi.d.ts +0 -77
  70. package/dist/chunk-E3OMP2DL.js +0 -36
  71. package/dist/chunk-KPZNNMV5.js +0 -83
  72. package/dist/chunk-NHS7ETKJ.js +0 -27
  73. package/dist/chunk-TSPJOM6K.js +0 -229
  74. package/dist/chunk-UOWIDFCB.js +0 -81
  75. package/dist/tema/index.cjs +0 -94
  76. package/dist/tema/index.d.cts +0 -110
  77. package/dist/tema/index.d.ts +0 -110
  78. package/dist/tema/index.js +0 -2
@@ -1,3 +1,3 @@
1
- export { tokens } from '../chunk-VPT32GPG.js';
2
- export { brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, series, shadow, sintaxis, size, spacing, tagline, typeScale } from '../chunk-TSPJOM6K.js';
1
+ export { tokens } from '../chunk-TA7TLWW4.js';
2
+ export { brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, series, shadow, size, spacing, syntax, tagline, typeScale } from '../chunk-OMKSESQB.js';
3
3
  import '../chunk-MLKGABMK.js';
@@ -1,25 +1,25 @@
1
1
  /*
2
- * GENERADO por scripts/build-tokens.mjs desde src/tokens/tokens.ts.
3
- * No lo edites a mano: se regenera en cada build.
2
+ * GENERATED by scripts/build-tokens.mjs from src/tokens/tokens.ts.
3
+ * Do not edit by hand: it is regenerated on every build.
4
4
  *
5
- * Uso en un proyecto Tailwind v4:
5
+ * Usage in a Tailwind v4 project:
6
6
  * @import "tailwindcss";
7
7
  * @import "@eduardoalvarez/arrecife/tokens/theme.css";
8
8
  *
9
- * El modo oscuro es el primario y es el default. Un proyecto en modo claro
10
- * declara data-theme="light" en <html>.
9
+ * Dark is the primary mode and the default. A project in light mode
10
+ * declares data-theme="light" on <html>.
11
11
  *
12
- * Las familias tipográficas se declaran por nombre: el proyecto carga
13
- * Bricolage Grotesque, Geist y JetBrains Mono como prefiera.
12
+ * Font families are declared by name: the project loads Bricolage
13
+ * Grotesque, Geist and JetBrains Mono however it prefers.
14
14
  */
15
15
 
16
- /* El modo se elige con data-theme. El oscuro es el primario, así que es el
17
- default: un proyecto claro declara data-theme="light" en <html>. */
16
+ /* The mode is chosen with data-theme. Dark is primary, so it is the default:
17
+ a light project declares data-theme="light" on <html>. */
18
18
  @custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
19
19
  @custom-variant light (&:where([data-theme="light"], [data-theme="light"] *));
20
20
 
21
21
  @theme {
22
- /* --- color · modo oscuro (default) ------------------------------------ */
22
+ /* --- color · dark mode (default) ------------------------------------- */
23
23
  --color-background: #091319;
24
24
  --color-surface: #10202B;
25
25
  --color-surface-raised: #17303E;
@@ -38,19 +38,22 @@
38
38
  --color-success: #4FB477;
39
39
  --color-warning: #E8A33D;
40
40
  --color-error: #E15757;
41
+ --color-danger: #F4736B;
42
+ --color-danger-hover: #F78D86;
43
+ --color-danger-on: #2B0A08;
41
44
 
42
- /* --- marca · iguales en los dos modos ---------------------------------- */
45
+ /* --- brand · identical in both modes ----------------------------------- */
43
46
  --color-brand-body: #3E7CB1;
44
47
  --color-brand-spots: #C2D7E7;
45
48
  --color-brand-hull: #0B1524;
46
49
 
47
- /* --- series de gráfica · modo oscuro (default) --------------------------- */
48
- --color-serie-1: #35D6C0;
49
- --color-serie-2: #F2A65A;
50
- --color-serie-3: #3E7CB1;
51
- --color-serie-4: #71919C;
50
+ /* --- chart series · dark mode (default) -------------------------------- */
51
+ --color-series-1: #35D6C0;
52
+ --color-series-2: #F2A65A;
53
+ --color-series-3: #3E7CB1;
54
+ --color-series-4: #71919C;
52
55
 
53
- /* --- tipografía --------------------------------------------------------- */
56
+ /* --- typography --------------------------------------------------------- */
54
57
  --font-display: "Bricolage Grotesque", ui-sans-serif, system-ui, sans-serif;
55
58
  --font-sans: "Geist", ui-sans-serif, system-ui, sans-serif;
56
59
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
@@ -99,7 +102,7 @@
99
102
  --text-eyebrow: 12px;
100
103
  --text-eyebrow--letter-spacing: 0.12em;
101
104
 
102
- /* --- forma y ritmo ------------------------------------------------------ */
105
+ /* --- shape and rhythm --------------------------------------------------- */
103
106
  --radius-chip: 6px;
104
107
  --radius-control: 10px;
105
108
  --radius-card: 14px;
@@ -117,8 +120,12 @@
117
120
  --spacing-control-md: 22px;
118
121
  --spacing-control-lg: 30px;
119
122
  --spacing-control-icon: 42px;
123
+ --spacing-control-icon-sm: 32px;
120
124
 
121
125
  --spacing-nav: 64px;
126
+ --spacing-nav-compact: 56px;
127
+ --spacing-sidebar: 256px;
128
+ --spacing-sidebar-rail: 56px;
122
129
  --container-content: 760px;
123
130
  --container-wide: 1180px;
124
131
  --container-measure: 68ch;
@@ -128,17 +135,17 @@
128
135
  --duration-standard: 150ms;
129
136
  --ease-standard: ease-out;
130
137
 
131
- /* --- degradados · modo oscuro (default) --------------------------------- */
138
+ /* --- gradients · dark mode (default) ----------------------------------- */
132
139
  --gradient-hero: linear-gradient(160deg, #091319 60%, #0D2129 100%);
133
- --gradient-seccion: linear-gradient(150deg, #10202B 0%, #0D2129 100%);
140
+ --gradient-section: linear-gradient(150deg, #10202B 0%, #0D2129 100%);
134
141
  --gradient-og: linear-gradient(145deg, #091319 55%, #0D2129 100%);
135
142
  }
136
143
 
137
- /* --- color por modo, anidable ---------------------------------------------
138
- Los dos modos se emiten como bloques propios, no solo el claro. Así un
139
- subárbol puede declarar el modo contrario al de la página y todo lo de dentro
140
- lo respeta: es lo que necesita un bloque de código, que va sobre casco en los
141
- dos temas y por tanto siempre lleva tinta clara encima. */
144
+ /* --- color per mode, nestable ----------------------------------------------
145
+ Both modes are emitted as their own blocks, not just light. That way a subtree
146
+ can declare the opposite mode to the page and everything inside honours it:
147
+ which is what a code block needs, since it sits on hull in both themes and
148
+ therefore always carries light ink on top. */
142
149
  [data-theme='dark'] {
143
150
  --color-background: #091319;
144
151
  --color-surface: #10202B;
@@ -158,14 +165,17 @@
158
165
  --color-success: #4FB477;
159
166
  --color-warning: #E8A33D;
160
167
  --color-error: #E15757;
168
+ --color-danger: #F4736B;
169
+ --color-danger-hover: #F78D86;
170
+ --color-danger-on: #2B0A08;
161
171
 
162
- --color-serie-1: #35D6C0;
163
- --color-serie-2: #F2A65A;
164
- --color-serie-3: #3E7CB1;
165
- --color-serie-4: #71919C;
172
+ --color-series-1: #35D6C0;
173
+ --color-series-2: #F2A65A;
174
+ --color-series-3: #3E7CB1;
175
+ --color-series-4: #71919C;
166
176
 
167
177
  --gradient-hero: linear-gradient(160deg, #091319 60%, #0D2129 100%);
168
- --gradient-seccion: linear-gradient(150deg, #10202B 0%, #0D2129 100%);
178
+ --gradient-section: linear-gradient(150deg, #10202B 0%, #0D2129 100%);
169
179
  --gradient-og: linear-gradient(145deg, #091319 55%, #0D2129 100%);
170
180
  }
171
181
 
@@ -188,34 +198,39 @@
188
198
  --color-success: #0F6B52;
189
199
  --color-warning: #8D6111;
190
200
  --color-error: #C0392B;
201
+ --color-danger: #C0392B;
202
+ --color-danger-hover: #A32F22;
203
+ --color-danger-on: #FFF6F4;
191
204
 
192
- --color-serie-1: #0D7C6F;
193
- --color-serie-2: #A65B27;
194
- --color-serie-3: #3E7CB1;
195
- --color-serie-4: #626A75;
205
+ --color-series-1: #0D7C6F;
206
+ --color-series-2: #A65B27;
207
+ --color-series-3: #3E7CB1;
208
+ --color-series-4: #626A75;
196
209
 
197
- --gradient-hero: linear-gradient(160deg, #F6F2EA 60%, #EFE9DE 100%);
198
- --gradient-seccion: linear-gradient(150deg, #FFFFFF 0%, #EFE9DE 100%);
199
- --gradient-og: linear-gradient(145deg, #F6F2EA 55%, #EFE9DE 100%);
210
+ --gradient-hero: linear-gradient(160deg, #F6F2EA 60%, #FFFFFF 100%);
211
+ --gradient-section: linear-gradient(150deg, #FFFFFF 0%, #F6F2EA 100%);
212
+ --gradient-og: linear-gradient(145deg, #F6F2EA 55%, #FFFFFF 100%);
200
213
  }
201
214
 
202
- /* --- los dos degradados del sistema, como utilidad --------------------------
203
- Son los dos únicos bloques con degradado: el hero y el panel de sección. Que
204
- sean utilidades y no clases arbitrarias es lo que impide que cada proyecto
205
- escriba su propio ángulo. Siguen el modo porque leen la custom property. */
206
- @utility degradado-hero {
215
+ /* --- the system's two gradients, as utilities -------------------------------
216
+ They are the only two blocks with a gradient: the hero and the section panel.
217
+ Making them utilities rather than arbitrary classes is what stops each project
218
+ from writing its own angle. They follow the mode because they read the custom
219
+ property. */
220
+ @utility gradient-hero {
207
221
  background-image: var(--gradient-hero);
208
222
  }
209
- @utility degradado-seccion {
210
- background-image: var(--gradient-seccion);
223
+ @utility gradient-section {
224
+ background-image: var(--gradient-section);
211
225
  }
212
226
 
213
- /* --- la tercera excepción de movimiento: el shimmer del skeleton ------------
214
- El sistema no anima, y esta es la tercera y última salvedad, junto al spinner
215
- del botón y el panel lateral. Todas son realimentación de PROGRESO, no de
216
- estado: un bloque quieto y un bloque que nunca va a cargar se ven igual.
227
+ /* --- the third motion exception: the skeleton shimmer -----------------------
228
+ The system does not animate, and this is the third exception, alongside the
229
+ button spinner and the side panel. All of them are feedback about PROGRESS,
230
+ not about state: a block that is still and a block that will never load look
231
+ identical.
217
232
 
218
- 1.4s lineal, del documento. Va detrás de motion-safe en el componente. */
233
+ 1.4s linear, from the document. It sits behind motion-safe in the component. */
219
234
  @keyframes arrecife-shimmer {
220
235
  from { background-position: 200% 0; }
221
236
  to { background-position: -200% 0; }
@@ -232,76 +247,126 @@
232
247
  animation: arrecife-shimmer 1.4s linear infinite;
233
248
  }
234
249
 
235
- /* --- la excepción del plegable ----------------------------------------------
236
- La cuarta y, como las otras tres, no es «queda mejor»: un plegable que revela
237
- contenido sin transición hace SALTAR todo lo que tiene debajo, y quien acaba
238
- de pulsar pierde el sitio en la página. Es la misma categoría que el panel
239
- lateral —un panel que entra desde un borde se desliza por definición— y no la
240
- de una animación de entrada, que es lo que el sistema no admite: aquí no
241
- aparece nada nuevo en pantalla, se abre un hueco.
242
-
243
- La altura la publica Radix en --radix-accordion-content-height. Dura lo que
244
- dura todo lo demás y usa la misma curva, así que no estrena un tiempo. En el
245
- componente va detrás de motion-safe. */
246
- @keyframes arrecife-despliega {
250
+ /* --- the fifth exception: the caret of the CLI signature --------------------
251
+ A terminal prompt with a caret that does not blink is a terminal that has
252
+ hung. The caret is the one piece of the footer that says the signature is a
253
+ prompt and not a decorative string, and a still block reads as a typo.
254
+
255
+ step-end and not a fade: a real caret is on or off, and easing it turns a
256
+ terminal into a pulsing dot. 1.06s is the cadence of a VT100 and of the site
257
+ this comes from.
258
+
259
+ It is the only exception that is not feedback about progress, and it earns its
260
+ place on the other half of the criterion the other four share: it is not
261
+ decoration, it is what makes the piece legible as what it is. Behind
262
+ motion-safe, where the caret stays solid — which is a caret at rest, not a
263
+ missing one. See docs/decisions.md § 23. */
264
+ @keyframes arrecife-caret {
265
+ 0%, 50% { opacity: 1; }
266
+ 50.01%, 100% { opacity: 0; }
267
+ }
268
+
269
+ @utility caret {
270
+ animation: arrecife-caret 1.06s step-end infinite;
271
+ }
272
+
273
+ /* --- the accordion exception -----------------------------------------------
274
+ The fourth one and, like the other three, it is not «it looks better»: a
275
+ disclosure that reveals content with no transition makes everything below it
276
+ JUMP, and whoever just clicked loses their place on the page. It is the same
277
+ category as the side panel — a panel entering from an edge slides by
278
+ definition — and not an entrance animation, which is what the system rejects:
279
+ nothing new appears on screen here, a gap opens.
280
+
281
+ Radix publishes the height as --radix-accordion-content-height. It lasts as
282
+ long as everything else and uses the same curve, so it introduces no new
283
+ timing. In the component it sits behind motion-safe. */
284
+ @keyframes arrecife-expand {
247
285
  from { height: 0; }
248
286
  to { height: var(--radix-accordion-content-height); }
249
287
  }
250
- @keyframes arrecife-repliega {
288
+ @keyframes arrecife-collapse {
251
289
  from { height: var(--radix-accordion-content-height); }
252
290
  to { height: 0; }
253
291
  }
254
292
 
255
- @utility desplegar {
256
- animation: arrecife-despliega var(--duration-standard) var(--ease-standard);
293
+ @utility expand {
294
+ animation: arrecife-expand var(--duration-standard) var(--ease-standard);
257
295
  }
258
- @utility replegar {
259
- animation: arrecife-repliega var(--duration-standard) var(--ease-standard);
296
+ @utility collapse {
297
+ animation: arrecife-collapse var(--duration-standard) var(--ease-standard);
260
298
  }
261
299
 
262
- /* --- la excepción del panel lateral -----------------------------------------
263
- Un panel que entra desde un borde se desliza por definición: quieto sería un
264
- modal descentrado. Es la segunda y última excepción a "nada de
265
- desplazamiento", y se aprobó a sabiendas.
266
-
267
- Dura lo que dura todo lo demás y usa la misma curva, así que no introduce un
268
- tiempo nuevo. En el componente va detrás de motion-safe. */
269
- @keyframes arrecife-entra-derecha { from { translate: 100% 0; } }
270
- @keyframes arrecife-sale-derecha { to { translate: 100% 0; } }
271
- @keyframes arrecife-entra-izquierda { from { translate: -100% 0; } }
272
- @keyframes arrecife-sale-izquierda { to { translate: -100% 0; } }
273
- @keyframes arrecife-entra-arriba { from { translate: 0 -100%; } }
274
- @keyframes arrecife-sale-arriba { to { translate: 0 -100%; } }
275
- @keyframes arrecife-entra-abajo { from { translate: 0 100%; } }
276
- @keyframes arrecife-sale-abajo { to { translate: 0 100%; } }
277
-
278
- @utility deslizar-entra-derecha {
279
- animation: arrecife-entra-derecha var(--duration-standard) var(--ease-standard);
300
+ /* --- the side panel exception ----------------------------------------------
301
+ A panel entering from an edge slides by definition: held still it would be an
302
+ off-centre modal. It is the second exception to "no displacement", and it was
303
+ approved knowingly.
304
+
305
+ It lasts as long as everything else and uses the same curve, so it introduces
306
+ no new timing. In the component it sits behind motion-safe. */
307
+ @keyframes arrecife-slide-in-right { from { translate: 100% 0; } }
308
+ @keyframes arrecife-slide-out-right { to { translate: 100% 0; } }
309
+ @keyframes arrecife-slide-in-left { from { translate: -100% 0; } }
310
+ @keyframes arrecife-slide-out-left { to { translate: -100% 0; } }
311
+ @keyframes arrecife-slide-in-top { from { translate: 0 -100%; } }
312
+ @keyframes arrecife-slide-out-top { to { translate: 0 -100%; } }
313
+ @keyframes arrecife-slide-in-bottom { from { translate: 0 100%; } }
314
+ @keyframes arrecife-slide-out-bottom { to { translate: 0 100%; } }
315
+
316
+ @utility slide-in-right {
317
+ animation: arrecife-slide-in-right var(--duration-standard) var(--ease-standard);
318
+ }
319
+ @utility slide-out-right {
320
+ animation: arrecife-slide-out-right var(--duration-standard) var(--ease-standard);
321
+ }
322
+ @utility slide-in-left {
323
+ animation: arrecife-slide-in-left var(--duration-standard) var(--ease-standard);
280
324
  }
281
- @utility deslizar-sale-derecha {
282
- animation: arrecife-sale-derecha var(--duration-standard) var(--ease-standard);
325
+ @utility slide-out-left {
326
+ animation: arrecife-slide-out-left var(--duration-standard) var(--ease-standard);
283
327
  }
284
- @utility deslizar-entra-izquierda {
285
- animation: arrecife-entra-izquierda var(--duration-standard) var(--ease-standard);
328
+ @utility slide-in-top {
329
+ animation: arrecife-slide-in-top var(--duration-standard) var(--ease-standard);
286
330
  }
287
- @utility deslizar-sale-izquierda {
288
- animation: arrecife-sale-izquierda var(--duration-standard) var(--ease-standard);
331
+ @utility slide-out-top {
332
+ animation: arrecife-slide-out-top var(--duration-standard) var(--ease-standard);
289
333
  }
290
- @utility deslizar-entra-arriba {
291
- animation: arrecife-entra-arriba var(--duration-standard) var(--ease-standard);
334
+ @utility slide-in-bottom {
335
+ animation: arrecife-slide-in-bottom var(--duration-standard) var(--ease-standard);
292
336
  }
293
- @utility deslizar-sale-arriba {
294
- animation: arrecife-sale-arriba var(--duration-standard) var(--ease-standard);
337
+ @utility slide-out-bottom {
338
+ animation: arrecife-slide-out-bottom var(--duration-standard) var(--ease-standard);
295
339
  }
296
- @utility deslizar-entra-abajo {
297
- animation: arrecife-entra-abajo var(--duration-standard) var(--ease-standard);
340
+
341
+ /* --- the focus ring ---------------------------------------------------------
342
+ The document gives it once, on the primary button: «focus ring 2px #35D6C0 +
343
+ offset 3px». The code had it as three classes copied to twenty-nine call
344
+ sites in twenty-four files, all of them at offset 2, and three audits in a row
345
+ said so — the value was never argued down to 2, it was copied from the first
346
+ component and inherited by the next twenty-eight.
347
+
348
+ It is one utility for the reason § 15 gives: a list kept in sync by hand with
349
+ another list ends up out of sync. Twenty-nine copies is twenty-nine chances to
350
+ write the next one at offset 2 again, and nothing was checking.
351
+
352
+ focus-ring-warm exists for the ONE control the ring cannot be biolume on:
353
+ the conversion button is the system's only sand fill, and a biolume ring
354
+ around it puts both of the brand's accents in the same three pixels. It sets
355
+ only the color, so the width and the offset stay in one place. */
356
+ @utility focus-ring {
357
+ &:focus-visible {
358
+ outline: 2px solid var(--color-accent);
359
+ outline-offset: 3px;
360
+ }
298
361
  }
299
- @utility deslizar-sale-abajo {
300
- animation: arrecife-sale-abajo var(--duration-standard) var(--ease-standard);
362
+ @utility focus-ring-warm {
363
+ &:focus-visible {
364
+ outline-color: var(--color-warm);
365
+ }
301
366
  }
302
367
 
303
- /* La única transición del sistema, como utilidad. Los estados se comunican con
304
- borde y color, no con movimiento: esta clase no puede animar otra cosa. */
368
+ /* The system's only transition, as a utility. States are communicated with
369
+ border and color, not with movement: this class cannot animate anything else. */
305
370
  @utility transition-standard {
306
371
  transition-property: color, background-color, border-color, fill, stroke;
307
372
  transition-duration: var(--duration-standard);
@@ -0,0 +1,195 @@
1
+ 'use strict';
2
+
3
+ var classVarianceAuthority = require('class-variance-authority');
4
+
5
+ // src/variants/button.ts
6
+ var button = classVarianceAuthority.cva(
7
+ [
8
+ "inline-flex cursor-pointer items-center justify-center gap-step-xs whitespace-nowrap select-none",
9
+ "rounded-control font-sans font-medium",
10
+ "transition-standard",
11
+ "focus-ring",
12
+ "disabled:pointer-events-none disabled:opacity-50",
13
+ "[&_svg]:shrink-0"
14
+ ],
15
+ {
16
+ variants: {
17
+ variant: {
18
+ primary: [
19
+ "bg-accent text-accent-on hover:bg-accent-hover",
20
+ "light:bg-brand-hull light:text-accent-on light:hover:bg-text-secondary"
21
+ ],
22
+ // The one control whose focus ring is not biolume. It is the system's
23
+ // only sand fill, and a biolume ring three pixels off a sand button puts
24
+ // both of the brand's accents in the same glance. See `decisions.md` § 37.
25
+ conversion: "bg-warm text-warm-on hover:bg-warm-hover focus-ring-warm",
26
+ secondary: [
27
+ "border-hairline-hover border bg-transparent text-text-primary",
28
+ "hover:border-accent hover:text-accent"
29
+ ],
30
+ tertiary: [
31
+ "bg-transparent font-mono font-normal text-text-secondary",
32
+ "hover:text-accent hover:underline hover:underline-offset-4"
33
+ ],
34
+ /** Irreversible only. Never for «cancel» on a form. */
35
+ destructive: "bg-danger text-danger-on hover:bg-danger-hover",
36
+ destructiveOutline: [
37
+ "border-danger text-danger border bg-transparent",
38
+ "hover:bg-danger hover:text-danger-on"
39
+ ]
40
+ },
41
+ size: {
42
+ sm: "h-8 px-control-sm text-label",
43
+ md: "h-10 px-control-md text-ui",
44
+ lg: "h-12 px-control-lg text-lead",
45
+ /** A 42×42 square, no text. `aria-label` is mandatory on it. */
46
+ icon: "size-control-icon p-0",
47
+ /** 32×32, for a table row. Same height as `sm`, and same mandatory `aria-label`. */
48
+ "icon-sm": "size-control-icon-sm p-0"
49
+ }
50
+ },
51
+ compoundVariants: [
52
+ /**
53
+ * The tertiary has no box: neither horizontal padding nor control height.
54
+ * It goes here rather than as `px-0` on the variant so it beats the size's
55
+ * `px-*` without depending on the order cva concatenates classes in.
56
+ */
57
+ { variant: "tertiary", size: ["sm", "md", "lg"], class: "h-auto px-0" }
58
+ ],
59
+ defaultVariants: { variant: "primary", size: "md" }
60
+ }
61
+ );
62
+ var badge = classVarianceAuthority.cva(
63
+ ["inline-flex items-center gap-step-xs", "rounded-chip px-step-xs py-0.5", "font-sans text-tag", "transition-standard"],
64
+ {
65
+ variants: {
66
+ variant: {
67
+ neutral: "bg-surface-raised text-text-secondary",
68
+ accent: "bg-accent/8 text-text-primary",
69
+ warm: "bg-warm/8 text-text-primary",
70
+ success: "bg-success/8 text-text-primary",
71
+ warning: "bg-warning/8 text-text-primary",
72
+ error: "bg-error/8 text-text-primary"
73
+ }
74
+ },
75
+ defaultVariants: { variant: "neutral" }
76
+ }
77
+ );
78
+ var category = classVarianceAuthority.cva(
79
+ [
80
+ "inline-flex items-center gap-step-xs",
81
+ "rounded-pill px-step-sm py-0.5",
82
+ "font-mono text-chip",
83
+ "border transition-standard"
84
+ ],
85
+ {
86
+ variants: {
87
+ active: {
88
+ false: "border-warm/28 bg-transparent text-warm",
89
+ true: "border-warm bg-warm text-warm-on"
90
+ }
91
+ },
92
+ defaultVariants: { active: false }
93
+ }
94
+ );
95
+ var metric = ["inline-flex items-center gap-step-xs", "rounded-pill", "font-mono text-chip text-text-muted"];
96
+ var text = classVarianceAuthority.cva("", {
97
+ variants: {
98
+ variant: {
99
+ display: "text-display font-display",
100
+ // Large metrics: 46px of display. It is the only scale designed for a
101
+ // number, which is why its line height is 1.
102
+ stat: "text-stat font-display",
103
+ h1: "text-h1 font-display",
104
+ h2: "text-h2 font-display",
105
+ h3: "text-h3 font-display",
106
+ body: "text-body font-sans",
107
+ // 17px: the deck on interior pages and the large button.
108
+ lead: "text-lead font-sans",
109
+ ui: "text-ui font-sans",
110
+ label: "text-label font-sans",
111
+ // The two badge scales. `tag` is status (sans 12.5/500) and `chip` is
112
+ // category and metric (mono 11.5). Neither transforms the text.
113
+ tag: "text-tag font-sans",
114
+ chip: "text-chip font-mono",
115
+ // Mono with NO transform: dates, paths, versions, file names and the
116
+ // footer signature. It is the step that was missing, and the reason every
117
+ // call site ended up writing `variant="eyebrow" className="normal-case"`.
118
+ meta: "text-meta font-mono",
119
+ // `uppercase` does not fit in a size token: text-transform is not a
120
+ // modifier of --text-*. Which is why the variant sets it, not theme.css.
121
+ eyebrow: "text-eyebrow font-mono uppercase"
122
+ },
123
+ tone: {
124
+ primary: "text-text-primary",
125
+ secondary: "text-text-secondary",
126
+ muted: "text-text-muted",
127
+ accent: "text-accent",
128
+ warm: "text-warm",
129
+ success: "text-success",
130
+ warning: "text-warning",
131
+ error: "text-error"
132
+ }
133
+ },
134
+ defaultVariants: { variant: "body", tone: "primary" }
135
+ });
136
+ var alert = classVarianceAuthority.cva("w-full rounded-card border p-step-md font-sans text-ui", {
137
+ variants: {
138
+ variant: {
139
+ accent: "text-text-secondary",
140
+ success: "text-text-secondary",
141
+ warning: "text-text-secondary",
142
+ error: "text-text-secondary"
143
+ },
144
+ emphasis: {
145
+ subtle: "",
146
+ strong: ""
147
+ }
148
+ },
149
+ compoundVariants: [
150
+ { variant: "accent", emphasis: "subtle", class: "border-accent/22 bg-accent/8" },
151
+ { variant: "success", emphasis: "subtle", class: "border-success/22 bg-success/8" },
152
+ { variant: "warning", emphasis: "subtle", class: "border-warning/22 bg-warning/8" },
153
+ { variant: "error", emphasis: "subtle", class: "border-error/22 bg-error/8" },
154
+ { variant: "accent", emphasis: "strong", class: "border-accent bg-accent/10" },
155
+ { variant: "success", emphasis: "strong", class: "border-success bg-success/10" },
156
+ { variant: "warning", emphasis: "strong", class: "border-warning bg-warning/10" },
157
+ { variant: "error", emphasis: "strong", class: "border-error bg-error/10" }
158
+ ],
159
+ defaultVariants: { variant: "accent", emphasis: "subtle" }
160
+ });
161
+ var avatar = classVarianceAuthority.cva(
162
+ "relative flex shrink-0 overflow-hidden rounded-pill bg-surface-raised border border-hairline",
163
+ {
164
+ variants: {
165
+ size: {
166
+ sm: "size-8",
167
+ md: "size-10",
168
+ lg: "size-14",
169
+ xl: "size-24"
170
+ }
171
+ },
172
+ defaultVariants: { size: "md" }
173
+ }
174
+ );
175
+
176
+ // src/variants/card.ts
177
+ var CARD_SURFACE = "rounded-card border-hairline bg-surface border";
178
+ var CARD_HOVER = "transition-standard hover:border-hairline-hover";
179
+ var CARD = [
180
+ "group block cursor-pointer",
181
+ CARD_SURFACE,
182
+ CARD_HOVER,
183
+ "focus-ring"
184
+ ];
185
+
186
+ exports.CARD = CARD;
187
+ exports.CARD_HOVER = CARD_HOVER;
188
+ exports.CARD_SURFACE = CARD_SURFACE;
189
+ exports.alertVariants = alert;
190
+ exports.avatarVariants = avatar;
191
+ exports.badgeVariants = badge;
192
+ exports.buttonVariants = button;
193
+ exports.categoryBadgeVariants = category;
194
+ exports.metricBadgeVariants = metric;
195
+ exports.textVariants = text;