@codenhub/styles 0.5.0 → 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 (119) hide show
  1. package/NOTICE +18 -16
  2. package/README.es.md +61 -0
  3. package/README.md +27 -22
  4. package/README.pt-BR.md +61 -0
  5. package/dist/aesthetics/chunky-tile.css +1 -1
  6. package/dist/aesthetics/cyber.css +1 -1
  7. package/dist/aesthetics/glass.css +1 -1
  8. package/dist/aesthetics/index.css +2 -2
  9. package/dist/aesthetics/neobrutalism.css +1 -1
  10. package/dist/aesthetics/pixel.css +1 -1
  11. package/dist/aesthetics/sketch.css +1 -1
  12. package/dist/components.css +2 -2
  13. package/dist/index.css +2 -2
  14. package/dist/native.css +2 -2
  15. package/dist/palette.css +1 -1
  16. package/dist/theme.css +2 -2
  17. package/dist/tw/aesthetics/chunky-tile.css +120 -62
  18. package/dist/tw/aesthetics/cyber.css +102 -40
  19. package/dist/tw/aesthetics/glass.css +371 -19
  20. package/dist/tw/aesthetics/index.css +2 -1
  21. package/dist/tw/aesthetics/neobrutalism.css +121 -33
  22. package/dist/tw/aesthetics/pixel.css +111 -16
  23. package/dist/tw/aesthetics/sketch.css +100 -28
  24. package/dist/tw/box.css +69 -28
  25. package/dist/tw/components/button.css +35 -14
  26. package/dist/tw/components/feedback.css +61 -58
  27. package/dist/tw/components/form.css +255 -142
  28. package/dist/tw/components/index.css +4 -9
  29. package/dist/tw/components/surface.css +80 -68
  30. package/dist/tw/components/tooltip.css +75 -41
  31. package/dist/tw/elevation.css +14 -22
  32. package/dist/tw/index.css +15 -19
  33. package/dist/tw/intent.css +35 -27
  34. package/dist/tw/native.css +22 -12
  35. package/dist/tw/palette.css +14 -11
  36. package/dist/tw/presentation.css +16 -30
  37. package/dist/tw/reset.css +36 -43
  38. package/dist/tw/surface.css +11 -12
  39. package/dist/tw/theme.css +87 -103
  40. package/dist/tw/utilities/content.css +311 -200
  41. package/dist/tw/utilities/layout.css +41 -37
  42. package/docs/accessibility.md +104 -58
  43. package/docs/changelog/0.1.1.md +1 -0
  44. package/docs/changelog/0.2.0.md +1 -0
  45. package/docs/changelog/0.3.0.md +1 -0
  46. package/docs/changelog/0.4.0.md +1 -0
  47. package/docs/changelog/0.5.0.md +8 -3
  48. package/docs/changelog/0.6.0.md +53 -0
  49. package/docs/changelog/0.7.0.md +50 -0
  50. package/docs/changelog/index.md +2 -0
  51. package/docs/concepts.md +188 -46
  52. package/docs/es/accessibility.md +150 -0
  53. package/docs/es/concepts.md +212 -0
  54. package/docs/es/index.md +104 -0
  55. package/docs/es/integrating/astro.md +35 -0
  56. package/docs/es/integrating/index.md +47 -0
  57. package/docs/es/integrating/nextjs.md +67 -0
  58. package/docs/es/integrating/svelte.md +45 -0
  59. package/docs/es/integrating/tailwind.md +78 -0
  60. package/docs/es/integrating/vue.md +31 -0
  61. package/docs/es/integrating/without-a-bundler.md +115 -0
  62. package/docs/es/setup.md +180 -0
  63. package/docs/es/usage/aesthetics.md +276 -0
  64. package/docs/es/usage/buttons.md +131 -0
  65. package/docs/es/usage/composing.md +164 -0
  66. package/docs/es/usage/content-and-layout.md +215 -0
  67. package/docs/es/usage/customizing.md +298 -0
  68. package/docs/es/usage/feedback.md +153 -0
  69. package/docs/es/usage/forms.md +231 -0
  70. package/docs/es/usage/index.md +29 -0
  71. package/docs/es/usage/solo.md +84 -0
  72. package/docs/es/usage/theming.md +296 -0
  73. package/docs/es/usage/tooltips.md +127 -0
  74. package/docs/index.md +89 -21
  75. package/docs/integrating/astro.md +3 -4
  76. package/docs/integrating/index.md +18 -13
  77. package/docs/integrating/nextjs.md +4 -5
  78. package/docs/integrating/svelte.md +5 -4
  79. package/docs/integrating/tailwind.md +29 -8
  80. package/docs/integrating/vue.md +3 -4
  81. package/docs/integrating/without-a-bundler.md +114 -0
  82. package/docs/pt-BR/accessibility.md +150 -0
  83. package/docs/pt-BR/concepts.md +212 -0
  84. package/docs/pt-BR/index.md +104 -0
  85. package/docs/pt-BR/integrating/astro.md +35 -0
  86. package/docs/pt-BR/integrating/index.md +47 -0
  87. package/docs/pt-BR/integrating/nextjs.md +67 -0
  88. package/docs/pt-BR/integrating/svelte.md +45 -0
  89. package/docs/pt-BR/integrating/tailwind.md +78 -0
  90. package/docs/pt-BR/integrating/vue.md +31 -0
  91. package/docs/pt-BR/integrating/without-a-bundler.md +115 -0
  92. package/docs/pt-BR/setup.md +180 -0
  93. package/docs/pt-BR/usage/aesthetics.md +276 -0
  94. package/docs/pt-BR/usage/buttons.md +131 -0
  95. package/docs/pt-BR/usage/composing.md +164 -0
  96. package/docs/pt-BR/usage/content-and-layout.md +215 -0
  97. package/docs/pt-BR/usage/customizing.md +298 -0
  98. package/docs/pt-BR/usage/feedback.md +153 -0
  99. package/docs/pt-BR/usage/forms.md +231 -0
  100. package/docs/pt-BR/usage/index.md +29 -0
  101. package/docs/pt-BR/usage/solo.md +84 -0
  102. package/docs/pt-BR/usage/theming.md +296 -0
  103. package/docs/pt-BR/usage/tooltips.md +127 -0
  104. package/docs/setup.md +134 -91
  105. package/docs/usage/aesthetics.md +102 -65
  106. package/docs/usage/buttons.md +108 -40
  107. package/docs/usage/composing.md +105 -92
  108. package/docs/usage/content-and-layout.md +159 -127
  109. package/docs/usage/customizing.md +112 -43
  110. package/docs/usage/feedback.md +135 -70
  111. package/docs/usage/forms.md +184 -99
  112. package/docs/usage/index.md +18 -14
  113. package/docs/usage/solo.md +83 -0
  114. package/docs/usage/theming.md +260 -119
  115. package/docs/usage/tooltips.md +103 -42
  116. package/llms-full.txt +2465 -1272
  117. package/llms.txt +25 -17
  118. package/package.json +28 -35
  119. package/dist/tw/components/loader.css +0 -117
@@ -0,0 +1,298 @@
1
+ ---
2
+ title: Personalización
3
+ description: Consulta de los tokens de presentación y de material, los controles de las estéticas, las seis variables públicas de componente, la paleta generada y los helpers para construir tus propios componentes.
4
+ order: 9
5
+ source: aa87391c5599ddfda913abcce9d17d9686345906
6
+ ---
7
+
8
+ # Personalización
9
+
10
+ Esta es una página de consulta para cambiar el paquete más allá de sus clases. [Temas](./theming.md) cubre los colores y los tokens base; esta página cubre el resto:
11
+
12
+ - [Tokens de presentación](#tokens-de-presentación): cuánto de una intención muestra un componente.
13
+ - [Tokens de material](#tokens-de-material): de qué está hecho un componente.
14
+ - [Tokens de estética](#tokens-de-estética): los controles que expone cada estética.
15
+ - [Variables de componente](#variables-de-componente): las seis variables que lee un único componente.
16
+ - [Paleta generada](#paleta-generada): valores de color fijos para el código que no puede cargar el paquete.
17
+ - [Helpers de composición](#helpers-de-composición): las clases con las que construir un componente propio.
18
+
19
+ ## Tokens de presentación
20
+
21
+ Los tokens de presentación describen _cuánto_ de una intención muestra un componente, nunca _qué_ intención muestra. Son números y porcentajes sin unidad, así que no llevan color y se heredan sin riesgo: un contenedor los define una vez y cada componente de debajo los resuelve con su propia intención.
22
+
23
+ | Token | Propósito | Valor por defecto |
24
+ | ----------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
25
+ | `--ui-fill` | Porcentaje del color de la intención mezclado en el fondo. | El valor por defecto del componente; consulta más abajo. |
26
+ | `--ui-fg-on-fill` | Porcentaje de mezcla desde el tono strong de la intención hacia su color de contraste. | El valor por defecto del componente. |
27
+ | `--ui-border` | Porcentaje del color de borde de la intención en el borde. | El valor por defecto del componente. |
28
+ | `--hover-step` | Se suma al relleno en reposo bajo el puntero, en `--intent-hover`. Defínelo en `:root` o en cualquier elemento. | `14%` |
29
+
30
+ Sin definir, cada componente usa su propio valor por defecto, que aparece en [Composición → Valores por defecto de los componentes](./composing.md#valores-por-defecto-de-los-componentes). Las clases de presentación definen los tres primeros con los valores de [Composición → Presentación](./composing.md#presentación). No hay tokens de hover por presentación: el hover es siempre el relleno en reposo más `--hover-step`, hasta el 100%.
31
+
32
+ Ninguna clase de relleno escribe `--ui-border` y ninguna clase de borde escribe `--ui-fill`. Una caja rellena sin línea es `.solid.edgeless`, y `.solid.edged` renderiza la misma caja: la línea se desvanece a medida que el relleno se completa, así que incluso un relleno neutro, limitado y translúcido, se ve a través de su propio borde como una sola capa.
33
+
34
+ ```css
35
+ background: color-mix(in oklab, var(--color-primary) var(--ui-fill, 100%), transparent);
36
+ ```
37
+
38
+ Ahí hay dos decisiones deliberadas. Mezclar hacia `transparent` en lugar de hacia un token de fondo permite que una superficie teñida se adapte a lo que tenga debajo. Mezclar en `oklab` conserva intacta la paleta de tokens de gama amplia y mezcla de forma perceptual, mientras que `srgb` la recortaría.
39
+
40
+ Por eso un color calculado llega a la página como un resultado de `color-mix` resuelto y no con la sintaxis `oklch` del propio token. Es el mismo color; el código que compara cadenas de colores calculados debería comparar colores.
41
+
42
+ > **Contrato de los tokens de presentación**: solo las clases de presentación y las sobrescrituras del consumidor definen estos tokens; los componentes solo los leen. Definir un valor que ninguna clase de presentación produce está soportado, pero no validado. Consulta [Composición](./composing.md) para ver las clases que incluyen estos valores.
43
+
44
+ ## Tokens de material
45
+
46
+ Los tokens de material describen de qué está _hecho_ un componente, no qué intención muestra ni con cuánta intensidad. Controlan la forma, los bordes, las sombras, la translucidez, los filtros y las transformaciones.
47
+
48
+ Los componentes leen cada uno con un valor de respaldo, así que dejarlos sin definir da el aspecto por defecto. Definidos en un contenedor, cambian el estilo de todo lo que contiene. La única excepción es `--ui-elevation`, que no se hereda, así que solo llega al elemento en el que se define; consulta [Composición → Elevación](./composing.md#elevación).
49
+
50
+ La geometría de la sombra se divide en partes sin color, así que se heredan sin riesgo. Los tokens que reciben un color, como `--ui-ink` y `--ui-surface-shadow`, pueden incluir el suyo.
51
+
52
+ | Token | Propósito | Respaldo |
53
+ | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
54
+ | `--ui-corner` | Esquina de control en el tamaño por defecto; se escala con el escalón de tamaño. | `--radius-control` |
55
+ | `--ui-corner-surface` | Esquina de superficie con el relleno interior por defecto; se escala con el escalón de tamaño. | `--radius-surface` |
56
+ | `--ui-corner-tl` | `0` o `1`: si la esquina superior izquierda toma la esquina. `-tr`, `-br` y `-bl` para las demás. | `1` |
57
+ | `--ui-radius` | Un radio de control completo, usado tal cual: sobrescribe la esquina, el escalón y el patrón. | Calculado a partir de la esquina |
58
+ | `--ui-radius-surface` | Un radio de superficie completo, usado tal cual. | Calculado a partir de la esquina |
59
+ | `--ui-scale` | Sobrescribe el escalón de tamaño que definen las clases de tamaño y de relleno interior. | El escalón |
60
+ | `--ui-corner-shape` | Lo que dibuja cada esquina: `round`, `bevel` para un corte recto o `squircle` para una curva continua. Hoy solo en Chromium. | `round` |
61
+ | `--ui-radius-pill` | Esquina de lo que es completamente redondo por defecto: badges, switches, progreso, el icono del tooltip; `.btn.pill` y `.radio` lo leen sin otro respaldo que el redondo completo. | `--ui-radius`, `--ui-corner` y después redondo completo |
62
+ | `--ui-radius-tight` | Radio completo para los chips, como un checkbox, `.kbd` o `.code`, cuando está definido. Sin definir, un pequeño valor por defecto calculado. | `min(--ui-radius o --ui-corner, pequeño)` |
63
+ | `--ui-line-style` | Estilo de cada línea que dibuja un componente: `solid`, `dashed`, `dotted` o `double` (de 3px de ancho o más). | `solid` |
64
+ | `--ui-border-width` | Grosor del borde. | `--border-width` |
65
+ | `--ui-border-max` | Tope del grosor de borde calculado. | `100px` |
66
+ | `--ui-ink` | Color de línea neutro cuando no hay intención. | `--color-border` |
67
+ | `--ui-control-ink` | Color de línea neutro de campos, selects, checkboxes, radios y switches cuando no hay intención. | `--ui-ink` y después `--color-control-border` |
68
+ | `--ui-rule-ink` | Color de línea neutro del marco y las líneas divisorias de una tabla cuando no hay intención. | `--ui-ink` y después `--color-border` |
69
+ | `--ui-rule` | Líneas dentro de una tabla. Sin definir dibuja solo los límites del encabezado y del pie; `0%` no dibuja ninguna; `100%` separa cada fila. | sin definir |
70
+ | `--ui-shadow-x` | Desplazamiento horizontal de la sombra. | `0px` |
71
+ | `--ui-shadow-y` | Desplazamiento vertical de la sombra. | `0px` |
72
+ | `--ui-shadow-blur` | Radio de desenfoque de la sombra. | `0px` |
73
+ | `--ui-shadow-spread` | Radio de extensión de la sombra. | `0px` |
74
+ | `--ui-shadow-inset` | La palabra clave `inset` para un anillo interior. | Vacío |
75
+ | `--ui-hover-shadow-x` | Desplazamiento horizontal de la sombra con hover. | `--ui-shadow-x` |
76
+ | `--ui-hover-shadow-y` | Desplazamiento vertical de la sombra con hover. | `--ui-shadow-y` |
77
+ | `--ui-active-shadow-x` | Desplazamiento horizontal de la sombra al pulsar. | `--ui-shadow-x` |
78
+ | `--ui-active-shadow-y` | Desplazamiento vertical de la sombra al pulsar. | `--ui-shadow-y` |
79
+ | `--ui-active-transform` | Transformación al pulsar. `none` con `prefers-reduced-motion`. | `scale(0.97)` |
80
+ | `--ui-active-translate-x` | Distancia que recorre una pulsación hacia la profundidad del elemento; `-y` a su lado. Se escala como la sombra. | `0px` |
81
+ | `--ui-shadow-ink` | Porcentaje del color de la sombra tomado de la tinta de la intención. | `0%` |
82
+ | `--ui-halo-blur` | Desenfoque de un halo alrededor del elemento; `--ui-halo-spread` a su lado. La elevación no lo escala. | `0px` |
83
+ | `--ui-halo-ink` | La proporción del color de la intención en el halo, sobre nada. Sin definir, no hay halo. | Sin definir |
84
+ | `--ui-shadow-edge` | Se declara, aunque esté vacío, cuando la sombra es el borde del elemento y no su profundidad. Se lee por su presencia. | Sin definir |
85
+ | `--ui-elevation` | Multiplicador sin unidad sobre la geometría de la sombra. No se hereda. | `1` |
86
+ | `--ui-surface-shadow` | Sombra completa de varias capas, aceptada solo por las superficies. | Sin definir |
87
+ | `--ui-surface-ground` | Fondo sobre el que se apoya una superficie, o una tabla por defecto o `.soft`. | `--color-background` |
88
+ | `--ui-bg-alpha` | Multiplicador sobre cada relleno, incluido `.solid`. Ninguna estética incluida lo define. | `1` |
89
+ | `--ui-backdrop` | Filtro de fondo aceptado solo por las superficies y por una tabla por defecto o `.soft`. | `none` |
90
+ | `--ui-surface-image` | Una capa pintada sobre la placa de una superficie: cualquier valor de `background-image`. Solo superficies. | `none` |
91
+ | `--ui-hover-transform` | Transformación mientras un elemento interactivo tiene hover. | `none` |
92
+ | `--ui-clip` | Silueta estructural del componente. | `none` |
93
+ | `--ui-clip-tight` | Silueta compacta del componente. | `--ui-clip` |
94
+ | `--ui-focus-inset` | Grosor de la capa de foco interior. | Sin definir |
95
+ | `--ui-label-weight` | Grosor de la etiqueta de `.btn` (y, con `/native`, de un `<button>` sin clase) y de `.badge`. | Semibold en un botón, bold en un badge |
96
+ | `--ui-label-tracking` | Espaciado entre letras de la etiqueta. Sin definir, la etiqueta lo hereda. | Sin definir |
97
+ | `--ui-label-case` | `text-transform` de la etiqueta. | `none` en un botón; heredado en un badge |
98
+ | `--ui-label-shadow` | `text-shadow` de la etiqueta, escrito sin color para que tome el de la propia etiqueta. | `none` en un botón; heredado en un badge |
99
+
100
+ ```html
101
+ <section style="--ui-corner: 0; --ui-border-width: 3px">
102
+ <button class="btn primary">Square and heavy</button>
103
+ <input class="ipt" placeholder="Matches" />
104
+ </section>
105
+ ```
106
+
107
+ > **Contrato de los tokens de material**: los componentes los leen; las clases de estética y las sobrescrituras del consumidor los definen.
108
+
109
+ ### Tamaño y patrón de las esquinas
110
+
111
+ La esquina escala con el elemento. `.p-xs` define un escalón de tamaño de `0.5`, `.sm` y `.p-sm` de `0.75`, y `.lg` y `.p-lg` de `1.25`. Cuando una clase de tamaño y una de relleno interior están en un mismo elemento, gana el escalón menor, así que `.lg.p-xs` es pequeño. `box` multiplica `--ui-corner` por el escalón, así que un botón pequeño toma una esquina pequeña y un bisel sigue siendo de 45 grados exactos. La profundidad sigue al escalón hacia abajo pero no hacia arriba: un botón `.p-xs` se apoya sobre la mitad de la sombra de su estética, y uno `.lg` sobre la sombra entera. Una pulsación que se mete en esa profundidad, indicada con `--ui-active-translate-x` y `-y`, recorre la misma distancia escalada, así que siempre termina a ras.
112
+
113
+ Qué esquinas toman la esquina es una elección aparte. `.cut-diagonal` conserva la superior izquierda y la inferior derecha y deja rectas las otras dos; `.cut-diagonal-reverse` conserva el otro par. Las dos definen `--ui-corner-tl`, `-tr`, `-br` y `-bl`, que también puedes definir tú: una hoja de dos esquinas con el aspecto por defecto, dos cortes en un control bajo `.cyber`. Una superficie bajo `.cyber` conserva la forma de superficie propia de la estética, a la que el patrón no llega, y un `--ui-radius` o `--ui-radius-surface` explícito ignora el escalón y el patrón.
114
+
115
+ ### Líneas, capas y etiquetas
116
+
117
+ `--ui-line-style` llega a cada línea que dibuja un componente: el borde de la caja, el carril de progreso y los divisores y las líneas divisorias de las tablas. `--ui-rule-style` sobrescribe opcionalmente solo los divisores y las líneas divisorias de las tablas, sin cambiar el borde de la caja; sketch lo usa para sus detalles discontinuos. Una línea discontinua o punteada conserva su color, así que conserva su contraste. Una línea `double` necesita un grosor de 3px o más para dibujar dos líneas.
118
+
119
+ `--ui-halo-*` es luz y no profundidad: un resplandor en el propio color de intención del elemento. La elevación no lo escala, y `.flat` no lo quita. Solo aparece cuando su tinta está definida.
120
+
121
+ `--ui-surface-image` pone cualquier `background-image` sobre la placa de una superficie: tarjetas, paneles, alertas y tooltips, no controles. Quien lo define es responsable del contraste del texto que queda encima, y tu propio `background-image` en una superficie sigue ganando.
122
+
123
+ `--ui-label-*` trata la etiqueta de un botón o de un badge: grosor, espaciado entre letras, mayúsculas y una sombra de texto. Escribe la sombra sin color, como `0 0 6px`, para que tome el color de la propia etiqueta y no pueda reducir su contraste. Tus propias utilidades `font-*`, `tracking-*` y de mayúsculas siguen ganando.
124
+
125
+ Con colores forzados, cada uno de estos dibuja su versión simple: una línea continua, sin halo, sin capa pintada y sin sombra de etiqueta. La silueta y el anillo de abajo también desaparecen. Los colores forzados eliminan todas las sombras de caja, así que `--ui-clip`, `--ui-clip-tight`, `--ui-border-max` y `--ui-shadow-edge` se anulan y un componente dibuja su borde real con `--ui-border-width`.
126
+
127
+ ### Composición de forma y anillo
128
+
129
+ El recorte elimina los bordes, los outlines y las sombras exteriores. Una estética que usa un recorte puede reemplazar el borde con una sombra interior definiendo `--ui-shadow-inset` y las cuatro partes de la geometría de la sombra. Define `--ui-border-max: 0px` cuando ese anillo reemplaza el borde del componente. Los componentes que pueden recibir el foco recuperan el outline de foco recortado mediante `--ui-focus-inset`: una capa interior de ese grosor en `--focus-ring`, con una línea de 2px de `--color-background` dentro, para que el foco se siga viendo en un componente relleno con el propio color del anillo.
130
+
131
+ Un recorte no es la única forma de cortar una esquina. `--ui-corner-shape: bevel` dibuja la esquina que define el radio como un corte recto en lugar de un arco, y el borde, la sombra exterior, el outline de foco y el fondo desenfocado la siguen. Por eso un elemento biselado conserva su resplandor y su línea, mientras que uno recortado pierde los dos. `.cyber` lo usa. Los motores sin `corner-shape` lo ignoran y dibujan el radio redondo, así que una estética que bisela debería dejar recto su radio bajo `@supports not (corner-shape: bevel)`. Un bisel sobre un radio completo corta en puntas: un radio, un `.btn.pill` y todo lo que lea `--ui-radius-pill` se convierten en rombos o hexágonos con puntas.
132
+
133
+ `--ui-radius` acepta cualquier valor de `border-radius` y se usa tal cual, así que puede colocar la esquina por lado: `10px 0` corta solo la superior izquierda y la inferior derecha. Las esquinas pill y de chip son tokens aparte. Una esquina de chip sin definir calcula un pequeño valor por defecto a partir de `--ui-radius`, y después de `--ui-corner`, con `--radius-small` como tope; un `--ui-radius-tight` explícito se usa tal cual, incluso para un valor por esquina o elíptico. Por eso las sobrescrituras de las estéticas y del consumidor pueden dar a un chip una forma mayor o más irregular. `.btn.pill` toma `--ui-radius-pill` antes que los demás radios; bajo sketch toma un contorno de píldora irregular dibujado a mano cuyos extremos mantienen el mismo tamaño. Un `--ui-radius-pill` explícito en ese botón sigue ganando.
134
+
135
+ Declara `--ui-shadow-edge` cuando ese anillo _es_ el borde. Entonces el anillo toma el color del borde del elemento, que lleva el eje de borde como su alfa, así que `.edged` lo dibuja y `.edgeless` no: la misma respuesta que da un borde real. Sin él, el anillo se pinta en cada componente al que llega la estética y las clases de borde no tienen efecto. Usa en su lugar `--ui-shadow-ink` cuando la sombra es profundidad proyectada en la propia tinta de la intención, como una losa dura desplazada, que un elemento `.edgeless` sigue recibiendo.
136
+
137
+ El token se lee por su presencia, no por su valor: decláralo vacío para activar el anillo, e `initial` para volver a desactivarlo en una estética anidada dentro de otra que lo declara.
138
+
139
+ ```css
140
+ .stepped {
141
+ --ui-clip: polygon(/* silueta estructural */);
142
+ --ui-clip-tight: none;
143
+ --ui-border-max: 0px;
144
+ --ui-shadow-inset: inset;
145
+ --ui-shadow-edge: ;
146
+ --ui-shadow-x: 0px;
147
+ --ui-shadow-y: 0px;
148
+ --ui-shadow-blur: 0px;
149
+ --ui-shadow-spread: 4px;
150
+ --ui-focus-inset: var(--focus-ring-width);
151
+ }
152
+ ```
153
+
154
+ Las variables con el prefijo `--_` son salidas internas de la composición: `--_bg`, `--_fg`, `--_edge`, `--_fill`, `--_shadow` y los huecos de reposo `--_d-*` que un componente declara para que los lea `box`. No las definas ni las leas; solo las entradas `--ui-*` de arriba son públicas.
155
+
156
+ ## Tokens de estética
157
+
158
+ Las [clases de estética](./aesthetics.md) incluidas definen los tokens de material por ti. Solo las estéticas con un token en la lista de abajo exponen un token propio. Ajusta el resto del comportamiento mediante los tokens de material compartidos de arriba. Los tokens de la lista solo están disponibles donde se importa la hoja de estilos de esa estética.
159
+
160
+ | Token | Estética | Propósito | Valor por defecto |
161
+ | --------------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
162
+ | `--neo-offset` | `.neobrutalism` | Desplazamiento de la sombra dura y distancia que recorre la pulsación. | `4px` |
163
+ | `--glass-radius` | `.glass`, `.glass-liquid` | Radio de la esquina de control. `1rem` con `.glass-liquid`. | `0.75rem` |
164
+ | `--glass-radius-surface` | `.glass`, `.glass-liquid` | Radio de la esquina de superficie. `1.5rem` con `.glass-liquid`. | `1rem` |
165
+ | `--pixel-unit` | `.pixel` | Un píxel de la cuadrícula. El corte de la esquina y el anillo miden uno. | `4px` |
166
+ | `--font-pixel` | `.pixel` | Pila de fuentes pixeladas que aporta el consumidor. | Recurre a la pila monoespaciada |
167
+ | `--tile-radius` | `.chunky-tile` | Radio de la esquina, igual en controles y superficies. | `0.75rem` |
168
+ | `--tile-lift` | `.chunky-tile` | Profundidad de la barra de apoyo y distancia que recorre una pulsación. | `4px` |
169
+ | `--font-rounded` | `.chunky-tile` | Pila de fuentes redondeadas que aporta el consumidor. | Recurre a la pila de la página |
170
+ | `--cyber-cut` | `.cyber` | El corte en el tamaño por defecto, igual en controles y superficies; los controles lo escalan con el escalón. | `0.625rem` |
171
+ | `--cyber-shape` | `.cyber` | Dónde toman el corte los controles: cualquier valor de `border-radius`. | `<cut> 0` (superior izquierda, inferior derecha) |
172
+ | `--cyber-shape-surface` | `.cyber` | Dónde toman el corte las superficies: cualquier valor de `border-radius`. | `0 <cut>` (superior derecha, inferior izquierda) |
173
+ | `--cyber-glow` | `.cyber` | Desenfoque del resplandor. | `8px` |
174
+ | `--cyber-ink` | `.cyber` | Color neutro de la línea y del resplandor, donde ninguna intención define uno. | Tinta del tema (casi negro, casi blanco) |
175
+ | `--font-cyber` | `.cyber` | Pila de fuentes técnicas que aporta el consumidor. | Recurre a la pila monoespaciada |
176
+ | `--sketch-radius` | `.sketch` | Radio del contorno de los controles: cualquier valor de `border-radius`. | Contorno de caja irregular con variación entre hermanos |
177
+ | `--sketch-radius-surface` | `.sketch` | Radio del contorno de los contenedores de superficie: cualquier valor de `border-radius`. | Contorno cuadrado, irregular y marcado, con variación entre hermanos |
178
+ | `--sketch-radius-rounded` | `.sketch`, `.sketch-rounded` | Radio del contorno redondeado de los controles: un contorno elíptico expresivo con variación entre hermanos. | `26px 10px 24px 11px / 12px 23px 11px 20px` con variación entre hermanos |
179
+ | `--sketch-radius-surface-rounded` | `.sketch`, `.sketch-rounded` | Radio del contorno redondeado de los contenedores de superficie: un contorno elíptico expresivo con variación entre hermanos. | `38px 16px 36px 17px / 16px 34px 17px 32px` con variación entre hermanos |
180
+ | `--sketch-radius-pill` | `.sketch` | Radio del contorno de un botón pill: una píldora irregular dibujada a mano cuyos extremos mantienen el mismo tamaño. | `24px 16px 23px 17px / 17px 21px 16px 20px` con variación entre hermanos |
181
+ | `--font-sketch` | `.sketch` | Pila de fuentes manuscritas que aporta el consumidor. | Recurre a `cursive` |
182
+
183
+ Los controles de todas las estéticas llegan de la misma forma: cada control se _lee_ con su valor por defecto como respaldo de `var()` en lugar de declararse, así que se resuelve una sola vez en una variable privada en la propia clase de la estética (`--_pixel-unit`, `--_neo-offset`, `--_tile-radius`, `--_tile-lift`, etc.). Define un control en el elemento que lleva la clase de estética, o en cualquier ancestro, incluido `:root`:
184
+
185
+ ```html
186
+ <section class="pixel" style="--pixel-unit: 6px">
187
+ <button class="btn primary">Chunkier</button>
188
+ </section>
189
+ ```
190
+
191
+ ```html
192
+ <html class="pixel" style="--pixel-unit: 6px">
193
+ <body>
194
+ <button class="btn primary">Also chunkier, set from the root</button>
195
+ </body>
196
+ </html>
197
+ ```
198
+
199
+ Los controles y los tokens de material llegan en direcciones opuestas. Un control se lee una vez, en el elemento con la clase de estética, y el resultado se hereda. Así que define un control en ese elemento o en uno por encima; definido en un elemento dentro de la estética, no cambia nada, porque el valor ya se ha leído.
200
+
201
+ Cada componente lee `--ui-radius` y los demás tokens de material al dibujarse. Funcionan en el elemento en el que se definen y en todo lo que contiene, que es como redondeas una tarjeta de forma distinta a sus vecinas sin tocar el control.
202
+
203
+ Las estéticas incluidas definen los tokens de material compartidos de arriba. Todas las estéticas incluidas definen `--ui-ink` para su línea neutra. Todas definen también `--ui-control-ink`: `.glass` y `.chunky-tile` con una línea propia, más intensa que la de sus superficies, y las demás con `--color-control-border`, ya que su tinta es casi negra o casi blanca y un checkbox en reposo con ese contorno parecería marcado. `.glass` define además `--ui-rule-ink`, para que las líneas de una tabla se lean sobre su placa; las demás lo anulan. Las clases de intención siguen sobrescribiendo los huecos de intención de cada componente.
204
+
205
+ Los mismos controles ajustan la [clase solo](./solo.md) de cada estética, que los lee en su propio elemento.
206
+
207
+ ## Paleta generada
208
+
209
+ `@codenhub/styles/palette` es una hoja de estilos generada de colores fijos: para cada intención y presentación, el color de fondo, de texto y de borde que dibujaría un componente, como custom properties `--palette-*` planas. Es para el código que no puede cargar la hoja de estilos de este paquete pero quiere coincidir con ella, como una librería que tiene `@codenhub/styles` como peer opcional. Donde puedas cargar la hoja de estilos, usa los componentes.
210
+
211
+ **Los valores son una instantánea de los colores incluidos.** Se calcularon a partir del tema por defecto del paquete al hacer el build, y no cambian cuando sobrescribes un token. Si defines `--color-primary` con el color de tu marca, `--palette-primary-solid-bg` sigue siendo el casi negro incluido. El código que deba seguir a tu tema tiene que leer los tokens `--color-*`, lo que implica cargar `@codenhub/styles/theme`.
212
+
213
+ ```css
214
+ @import "@codenhub/styles/palette";
215
+ ```
216
+
217
+ ```css
218
+ .my-badge {
219
+ background: var(--palette-success-soft-page-bg);
220
+ color: var(--palette-success-soft-fg);
221
+ border-color: var(--palette-success-soft-page-edge);
222
+ }
223
+ ```
224
+
225
+ Cada valor es un color final, nunca una referencia a otra variable, así que el archivo no necesita que se cargue nada más.
226
+
227
+ Nombres: `--palette-<intent>-<presentation>-<slot>`, donde `<intent>` es una de las siete intenciones publicadas (`neutral`, `primary`, `secondary`, `success`, `warning`, `destructive`, `info`) y `<presentation>` es `solid`, `soft` o `ghost`. `<slot>` es `bg`, `fg` o `edge`. Dos calificadores se añaden solo donde aplican:
228
+
229
+ - Un calificador de fondo, `page` o `subtle`, antes del hueco. Solo aparece en el `bg` y el `edge` de `.soft` y `.ghost`, porque un relleno `.solid` cubre su fondo y el color del texto nunca depende de él.
230
+ - Sin calificador es el fondo transparente de `.badge` y `.btn`: `--palette-success-soft-bg`.
231
+ - `page` es el fondo de `.alert`, `--color-background`: `--palette-success-soft-page-bg`.
232
+ - `subtle` es el fondo de `.pre`, `.code`, `.kbd` y `.tooltip-bubble`, el propio `--intent-subtle` de la intención: `--palette-success-soft-subtle-bg`.
233
+ - Un sufijo `-hover`, solo en `bg` y `edge`, porque el color del texto no cambia con hover: `--palette-success-soft-page-bg-hover`.
234
+
235
+ Los valores claros se definen en `:root`. Los oscuros se aplican bajo `.dark`, `.theme-dark` o `[data-theme="dark"]` en el elemento o en uno por encima, los mismos selectores que usa el tema del paquete. Los valores claros también se aplican bajo `.light`, `.theme-light` y `[data-theme="light"]`, así que gana el tema explícito más cercano: una zona clara dentro de una oscura lee los valores claros.
236
+
237
+ El archivo no sigue `prefers-color-scheme`. El código que usa la paleta por sí sola ya cambia de tema por su cuenta, así que define una de esas clases o atributos.
238
+
239
+ Otros tres tokens no tienen intención, presentación, fondo ni hover: `--palette-border`, `--palette-surface` y `--palette-text`, valores fijos de `--color-border`, `--color-surface` y `--color-text`. Son para lo que no tiene color de intención, como el borde de un contenedor, el fondo de un diálogo y su texto.
240
+
241
+ ## Variables de componente
242
+
243
+ Seis variables las lee un único componente y son entradas soportadas. Cualquier otra variable que declare un componente, como `--surface-padding`, `--field-gap`, `--switch-*`, `--table-*` o `--quote-*`, es interna y puede cambiar en cualquier versión.
244
+
245
+ | Variable | Elemento | Valor | Valor por defecto | Efecto | Dónde definirla |
246
+ | -------------------- | -------------- | ------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
247
+ | `--progress-value` | `.progress` | Un porcentaje, de `0%` a `100%` | `0%` | Ancho de la parte rellena. No se limita; un valor sin `%` no es válido y se muestra vacío. | En la barra o en cualquier elemento que la rodee. |
248
+ | `--progress-color` | `.progress` | Un color | El color de la intención | Color de la parte rellena y del brillo de `.active`. | En la barra o en cualquier elemento que la rodee. |
249
+ | `--progress-surface` | `.progress` | Un color | El color de la intención con el relleno de la presentación: 12% por defecto | Color del carril. | En la barra o en cualquier elemento que la rodee. |
250
+ | `--progress-edge` | `.progress` | Un color | El color de borde de la intención con el borde de la presentación: ninguno por defecto | Color del borde del carril. Solo se ve donde el carril tiene grosor de borde, como con `.edged`. | En la barra o en cualquier elemento que la rodee. |
251
+ | `--input-group-gap` | `.input-group` | Una longitud | `0.5rem` | Espacio entre el control y su icono o texto. | En el propio `.input-group`. El grupo declara el valor por defecto, así que un valor en un padre se ignora. |
252
+ | `--tooltip-linger` | `.tooltip` | Un tiempo | `300ms` | Cuánto tiempo se queda la burbuja después de que el puntero sale del disparador. | En el propio `.tooltip`. El contenedor declara el valor por defecto, así que un valor en un padre se ignora. |
253
+
254
+ ```html
255
+ <div class="progress" role="meter" aria-label="Storage used" aria-valuemin="0" aria-valuemax="100" aria-valuenow="92" style="--progress-value: 92%; --progress-color: var(--color-warning)"></div>
256
+
257
+ <div class="input-group" style="--input-group-gap: 0">
258
+ <span>app.example.com/u/</span>
259
+ <input class="ipt" id="profile-url" aria-label="Profile address" />
260
+ </div>
261
+ ```
262
+
263
+ Los ejemplos en contexto están en [Feedback → Mostrar el progreso](./feedback.md#mostrar-el-progreso), [Formularios → Añadir un icono o un prefijo fijo](./forms.md#añadir-un-icono-o-un-prefijo-fijo) y [Tooltips → Hover, permanencia y Escape](./tooltips.md#hover-permanencia-y-escape).
264
+
265
+ ## Helpers de composición
266
+
267
+ Para construir un componente que el paquete no incluye, como un control segmentado o un chip de filtro, compónlo con las mismas clases con las que están construidos los componentes del paquete. Con CSS compilado, escríbelas como clases; con el código fuente de Tailwind, también puedes usarlas con `@apply`.
268
+
269
+ | Clase | Lo que le da a un elemento |
270
+ | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
271
+ | `box` | La caja pintada: fondo, color de texto, borde, esquina, sombra, el material de la estética, el anillo de foco y el aspecto deshabilitado. Lee la intención, la presentación, la estética y la elevación. |
272
+ | `box-hover` | El color de hover, para algo que se pulsa y no algo en lo que se escribe. Añádelo con `box`. |
273
+ | `box-active` | La pulsación: una ligera reducción, o la pulsación propia de la estética. Añádelo con `box`. |
274
+ | `surface` | `box` con los valores por defecto de una superficie: sin relleno y con borde, la esquina de superficie y el fondo, el desenfoque y la sombra de superficie de la estética, como en una tarjeta. |
275
+ | `text-control` | `box` con los valores por defecto de un campo de texto: sin relleno y con borde, las reglas de relleno limitado y de borde, el color del placeholder, un borde que cambia con hover y con foco, y el estado no válido. |
276
+
277
+ Chips de filtro para la lista de miembros, uno pulsado y otro no:
278
+
279
+ ```html
280
+ <button class="box box-hover box-active neutral soft edgeless" type="button" aria-pressed="true" style="padding: 0.25rem 0.75rem; border-radius: 999px">Admins</button>
281
+
282
+ <button class="box box-hover box-active neutral ghost edgeless" type="button" aria-pressed="false" style="padding: 0.25rem 0.75rem; border-radius: 999px">Owners</button>
283
+ ```
284
+
285
+ `box` no lee `aria-pressed`, así que el chip pulsado parece pulsado solo porque tiene `.soft`. Cuando tu código cambie `aria-pressed`, cambia con él la clase de presentación: `.soft` cuando está pulsado, `.ghost` cuando no.
286
+
287
+ Qué darle a cada uno:
288
+
289
+ - **`box` necesita una clase de relleno y una de borde.** No tiene valores por defecto propios, así que sin `.solid`, `.soft` o `.ghost` y sin `.edged` o `.edgeless`, en el elemento o en un contenedor, no dibuja nada. `surface` y `text-control` tienen valores por defecto y funcionan solos.
290
+ - **Nombra la intención.** Un elemento `box` toma la intención del elemento más cercano a su alrededor que tenga una, a diferencia de los componentes del paquete. Ponle `.neutral` o una clase de intención.
291
+ - **El tamaño y el espaciado son cosa tuya.** Ninguno de los helpers define el relleno interior, el ancho ni el alto; `text-control` no define la altura de 2.5rem que añade `.ipt`.
292
+ - **También el comportamiento y la semántica.** Usa un `<button>`, un `<input>` o un `<a href>` reales, o añade tú el rol y el manejo del teclado, y define estados como `aria-pressed` o `aria-invalid`. `box` dibuja el aspecto deshabilitado para `disabled`, `.disabled`, `aria-disabled="true"` y `data-disabled`, pero solo el atributo `disabled` impide la interacción.
293
+
294
+ No definas ni leas las variables con el prefijo `--_` que estos helpers usan internamente; cambian entre versiones.
295
+
296
+ ## Siguiente paso
297
+
298
+ [Contenido y layout](./content-and-layout.md) enumera los helpers de layout, la escala tipográfica, las superficies, las tablas y los chips de contenido.
@@ -0,0 +1,153 @@
1
+ ---
2
+ title: Feedback
3
+ description: Un botón que indica que está guardando, alertas, badges, placeholders de carga y barras de progreso, y lo que tu código debe mantener sincronizado con ellos.
4
+ order: 3
5
+ source: e2a4c2af517dd286e22e762e4ba1997ebdb3c8c6
6
+ ---
7
+
8
+ # Feedback
9
+
10
+ El formulario de perfil se puede enviar, pero nada le dice al usuario qué ha pasado. Esta página añade el feedback de la pantalla: un botón Guardar que muestra que está trabajando, una alerta cuando el guardado sale bien, un badge en la tarjeta del plan, un placeholder mientras carga el perfil y barras para el uso de almacenamiento y para una exportación de datos. El paquete dibuja cada uno de ellos; tu código decide cuándo aparecen, actualiza sus valores y se asegura de que los lectores de pantalla se enteren.
11
+
12
+ ## Mostrar que el formulario se está guardando
13
+
14
+ No hay una clase de carga. Un botón que está guardando es un botón deshabilitado con un icono que gira:
15
+
16
+ ```html
17
+ <button class="btn primary" type="submit" disabled>
18
+ <i class="ic-lucide-loader-circle ic-anim-spin" aria-hidden="true"></i>
19
+ Saving…
20
+ </button>
21
+ ```
22
+
23
+ El spinner viene de `@codenhub/icons`, que este paquete no carga. Cárgalo una vez, como muestra [Botones → Cargar los iconos](./buttons.md#cargar-los-iconos); con CSS compilado es así:
24
+
25
+ ```css
26
+ @import "@codenhub/icons";
27
+ @import "@codenhub/icons/lucide";
28
+ ```
29
+
30
+ `ic-anim-spin` hace girar el icono y se detiene cuando el usuario pide al sistema movimiento reducido. La familia animada `svg-spinners` de `@codenhub/icons` es distinta: su dibujo sigue moviéndose con esa preferencia. Cualquiera de los dos iconos toma el color de texto del botón.
31
+
32
+ Deshabilitar el botón evita que un segundo clic envíe el formulario dos veces. Mantener o reemplazar el texto depende de ti; el paquete no tiene forma de ocultarlo. Un cambio en el texto de un botón no se anuncia de forma fiable, así que comunica el resultado a quienes usan lector de pantalla con un mensaje de estado, como hace la siguiente sección.
33
+
34
+ ## Confirmar el resultado con una alerta
35
+
36
+ Cuando el guardado sale bien, muestra una alerta encima del formulario:
37
+
38
+ ```html
39
+ <div class="alert success" role="status">Profile saved.</div>
40
+ ```
41
+
42
+ `role="status"` hace que los lectores de pantalla anuncien el texto de forma educada, después de lo que estén leyendo. Para un error sobre el que el usuario debe actuar, usa `role="alert"`, que interrumpe:
43
+
44
+ ```html
45
+ <div class="alert destructive" role="alert">Your changes were not saved. Check your connection and try again.</div>
46
+ ```
47
+
48
+ Los lectores de pantalla anuncian una región live cuando cambia su contenido, así que renderiza la región vacía al cargar la página y pon el mensaje dentro, en lugar de insertar un nuevo elemento de alerta que ya contenga el texto. El paquete no añade rol, temporización ni botón de cierre; eso es cosa tuya.
49
+
50
+ Una alerta es una fila con una separación de 0.75rem, así que un icono colocado antes del mensaje queda espaciado automáticamente. `.alert-icon` da a un icono un tamaño de 1.25rem y lo alinea con la primera línea de texto:
51
+
52
+ ```html
53
+ <div class="alert warning" role="status">
54
+ <i class="alert-icon ic-lucide-triangle-alert" aria-hidden="true"></i>
55
+ Your card expires next month. Update it to keep your plan.
56
+ </div>
57
+ ```
58
+
59
+ Funciona cualquier elemento de icono: una clase de un conjunto de iconos, un `<svg>` en línea o un `<img>`. `@codenhub/icons` define el tamaño de sus glifos en una regla que ninguna clase puede superar, así que `.alert-icon` también define el `--ic-size` de ese conjunto. Para cambiar el tamaño del icono de una alerta, escribe tu propia regla que defina `width`, `height` y, para `@codenhub/icons`, `--ic-size`.
60
+
61
+ ### Cómo se ven las alertas
62
+
63
+ Sin clase de presentación, una alerta es soft y con borde: un tinte claro de su intención, texto del color de la intención y un borde. Las clases de presentación lo cambian como en cualquier componente, por ejemplo `.alert.primary.solid` para un banner relleno.
64
+
65
+ Una alerta sin intención es una excepción. No tiene tinte en reposo; usa `--color-foreground`, el tono de fondo discreto un paso por encima de la página, igual que una `.card.soft` o un `.panel` neutros. Una alerta con `.primary`, `.secondary`, `.success`, `.warning`, `.destructive` o `.info` conserva su tinte. Aquí solo cuentan esas seis clases: una alerta con una clase de intención que hayas definido tú se trata como si no tuviera intención; consulta [Temas → Tu propia intención](./theming.md#tu-propia-intención).
66
+
67
+ ## Etiquetar el plan con un badge
68
+
69
+ Un badge es una pequeña píldora para un estado o un recuento:
70
+
71
+ ```html
72
+ <section class="card soft primary stack tight" aria-labelledby="plan-title">
73
+ <div class="cluster between">
74
+ <h2 class="text-label" id="plan-title">Current plan</h2>
75
+ <span class="badge success">Active</span>
76
+ </div>
77
+ <p class="text-title-sm">Team, billed yearly</p>
78
+ </section>
79
+ ```
80
+
81
+ Un badge es soft y sin borde por defecto, y acepta las mismas clases de intención y presentación que un botón: `.badge.warning` para "Pago pendiente", `.badge.info.solid` para un "Nuevo" relleno. A diferencia de una alerta, un badge sin intención conserva su tinte claro, porque no tiene borde, y sin el tinte se perdería en el texto que lo rodea.
82
+
83
+ ## Mostrar un placeholder mientras carga
84
+
85
+ Mientras la tarjeta de perfil espera los datos, muestra bloques grises donde irá el texto:
86
+
87
+ ```html
88
+ <section class="card stack" aria-busy="true" aria-labelledby="profile-title">
89
+ <h2 class="text-title-sm" id="profile-title">Profile</h2>
90
+ <p class="visually-hidden">Loading your profile…</p>
91
+ <div class="stack tight" aria-hidden="true">
92
+ <div class="skeleton" style="height: 2.5rem"></div>
93
+ <div class="skeleton" style="width: 60%"></div>
94
+ </div>
95
+ </section>
96
+ ```
97
+
98
+ Un `.skeleton` ocupa el ancho de su contenedor y mide al menos 1rem de alto. No tiene tamaño ni forma propios: usa un elemento de bloque como un `<div>`, y ajusta su ancho y su alto al contenido al que sustituye. Un elemento en línea vacío como `<span class="skeleton">` no tiene tamaño y no aparece.
99
+
100
+ Un skeleton acepta una intención pero ignora la presentación. Sin intención, es un gris claro teñido por el color del texto que lo rodea. Muestra un brillo en movimiento que se detiene cuando el usuario pide movimiento reducido.
101
+
102
+ Marca los bloques con `aria-hidden="true"`, porque no significan nada para un lector de pantalla. Indica en su lugar con texto que el contenido está cargando, como hace el párrafo visualmente oculto, y quita `aria-busy` cuando el contenido esté en su sitio.
103
+
104
+ ## Mostrar el progreso
105
+
106
+ La tarjeta de almacenamiento muestra cuánto espacio se usa, y el botón "Exportar datos antes" de la zona de peligro inicia una exportación que tarda un rato. Las dos son barras `.progress`:
107
+
108
+ ```html
109
+ <div class="progress" role="meter" aria-label="Storage used" aria-valuemin="0" aria-valuemax="100" aria-valuenow="48" aria-valuetext="48 GB of 100 GB" style="--progress-value: 48%"></div>
110
+
111
+ <div class="progress primary" role="progressbar" aria-label="Export progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="20" style="--progress-value: 20%"></div>
112
+ ```
113
+
114
+ `--progress-value` es el ancho de la parte rellena, como porcentaje del carril. Vale 0% si no se define.
115
+
116
+ - **Escríbelo con `%`.** `--progress-value: 48` sin unidad no es un ancho válido, y la barra se muestra vacía.
117
+ - **No se limita ni se comprueba nada.** Por encima del 100%, el relleno se corta al final del carril y parece lleno; un valor negativo tampoco es un ancho válido. Mantén el valor entre 0% y 100% en tu código.
118
+ - **El valor visual y el valor anunciado son independientes.** El ancho de la barra viene de `--progress-value`; lo que anuncia un lector de pantalla viene de `aria-valuenow`. El paquete no los conecta, así que actualiza los dos a la vez.
119
+
120
+ ```js
121
+ function setExportProgress(bar, percent) {
122
+ const value = Math.min(100, Math.max(0, Math.round(percent)));
123
+ bar.classList.remove("indeterminate");
124
+ bar.style.setProperty("--progress-value", `${value}%`);
125
+ bar.setAttribute("aria-valuenow", String(value));
126
+ }
127
+ ```
128
+
129
+ Cuando no sabes cuánto ha avanzado el trabajo, como mientras se prepara la exportación, usa `.indeterminate`. Una barra de aproximadamente un tercio del ancho del carril lo recorre de principio a fin una y otra vez, y `--progress-value` se ignora. Quita `aria-valuenow`, porque no hay un valor conocido que anunciar:
130
+
131
+ ```html
132
+ <div class="progress primary indeterminate" role="progressbar" aria-label="Preparing export"></div>
133
+ ```
134
+
135
+ `.active` añade un brillo sobre el carril de una barra determinada, para mostrar que el trabajo sigue en marcha entre actualizaciones. Las dos animaciones se detienen cuando el usuario pide movimiento reducido; una barra indeterminada queda entonces en reposo con su relleno al principio.
136
+
137
+ ### Cómo se ven las barras de progreso
138
+
139
+ El relleno es el color de la intención con toda su intensidad, o `currentColor` sin intención. El carril es soft y sin borde por defecto: un tinte claro sin borde.
140
+
141
+ El carril por defecto es tenue. Frente a la página mide aproximadamente de 1.1:1 a 1.3:1, por debajo del 3:1 que WCAG 1.4.11 pide a las partes de un gráfico necesarias para entenderlo. Cuando importa la extensión del carril, usa `.ghost.edged` con una clase de intención, que dibuja un contorno alrededor en el color de la intención. Sin intención, el contorno es un gris claro que mide menos de 3:1; [Accesibilidad → Contornos de progreso](../accessibility.md#contornos-de-progreso) tiene las mediciones y lo que puedes hacer con una barra neutra. `.solid` no está soportado en el carril, porque el relleno y el carril serían del mismo color. `.ghost.edgeless` se renderiza, pero deja el carril sin un marco visible.
142
+
143
+ Para cambiar los colores del relleno, del carril o de su borde sin cambiar la intención, define `--progress-color`, `--progress-surface` o `--progress-edge` en la barra o en cualquier elemento que la rodee. Estas variables y `--progress-value` aparecen en [Personalización → Variables de componente](./customizing.md#variables-de-componente).
144
+
145
+ ## Animación que no se detiene
146
+
147
+ Los skeletons, los brillos de `.active`, las barras indeterminadas y los spinners se animan mientras estén en la página. El paquete detiene sus propias animaciones cuando el usuario pide al sistema movimiento reducido, pero ese no es el único requisito. WCAG 2.2.2 pide que el movimiento que empieza automáticamente, dura más de cinco segundos y se muestra junto a otro contenido pueda ser pausado, detenido u ocultado por el usuario, salvo que el movimiento sea esencial.
148
+
149
+ Un indicador de carga que se muestra mientras el usuario no puede hacer otra cosa, y cuya ausencia lo confundiría, cuenta como esencial. Un brillo o un spinner que sigue moviéndose junto al contenido con el que el usuario está trabajando, como un brillo decorativo de "en vivo" en una tarjeta, no. Quítalos en cuanto terminen su trabajo, o dale al usuario un control que los detenga.
150
+
151
+ ## Siguiente paso
152
+
153
+ La pantalla ya informa de lo que está haciendo. [Tooltips](./tooltips.md) añade un breve texto de ayuda junto a un campo de formulario.