@codenhub/styles 0.7.0 → 0.9.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 (130) hide show
  1. package/README.es.md +9 -8
  2. package/README.md +8 -7
  3. package/README.pt-BR.md +9 -8
  4. package/dist/aesthetics/chunky-tile.css +1 -1
  5. package/dist/aesthetics/cyber.css +1 -1
  6. package/dist/aesthetics/glass.css +1 -1
  7. package/dist/aesthetics/index.css +2 -2
  8. package/dist/aesthetics/neobrutalism.css +1 -1
  9. package/dist/aesthetics/pixel.css +1 -1
  10. package/dist/aesthetics/sketch.css +1 -1
  11. package/dist/cli.js +358 -0
  12. package/dist/components.css +50 -2
  13. package/dist/index.css +50 -2
  14. package/dist/index.d.ts +1 -0
  15. package/dist/native.css +50 -2
  16. package/dist/palette.css +1 -1
  17. package/dist/purge/classes.json +1 -0
  18. package/dist/purge/index.css +50 -0
  19. package/dist/theme.css +2 -2
  20. package/docs/accessibility.md +46 -27
  21. package/docs/changelog/0.8.0.md +70 -0
  22. package/docs/changelog/0.9.0.md +40 -0
  23. package/docs/changelog/index.md +2 -0
  24. package/docs/es/accessibility.md +47 -28
  25. package/docs/es/index.md +4 -3
  26. package/docs/es/integrating/index.md +38 -10
  27. package/docs/es/integrating/tailwind.md +79 -8
  28. package/docs/es/integrating/without-a-bundler.md +157 -5
  29. package/docs/es/setup.md +43 -34
  30. package/docs/es/usage/aesthetics.md +20 -14
  31. package/docs/es/usage/buttons.md +6 -2
  32. package/docs/es/usage/composing.md +6 -2
  33. package/docs/es/usage/content-and-layout.md +10 -4
  34. package/docs/es/usage/customizing.md +46 -26
  35. package/docs/es/usage/feedback.md +5 -1
  36. package/docs/es/usage/forms.md +30 -5
  37. package/docs/es/usage/index.md +7 -3
  38. package/docs/es/usage/presets.md +92 -0
  39. package/docs/es/usage/solo.md +4 -2
  40. package/docs/es/usage/theming.md +29 -16
  41. package/docs/es/usage/tooltips.md +2 -2
  42. package/docs/index.md +3 -2
  43. package/docs/integrating/index.md +38 -10
  44. package/docs/integrating/tailwind.md +78 -7
  45. package/docs/integrating/without-a-bundler.md +156 -4
  46. package/docs/pt-BR/accessibility.md +47 -28
  47. package/docs/pt-BR/index.md +4 -3
  48. package/docs/pt-BR/integrating/index.md +38 -10
  49. package/docs/pt-BR/integrating/tailwind.md +79 -8
  50. package/docs/pt-BR/integrating/without-a-bundler.md +157 -5
  51. package/docs/pt-BR/setup.md +43 -34
  52. package/docs/pt-BR/usage/aesthetics.md +20 -14
  53. package/docs/pt-BR/usage/buttons.md +6 -2
  54. package/docs/pt-BR/usage/composing.md +6 -2
  55. package/docs/pt-BR/usage/content-and-layout.md +10 -4
  56. package/docs/pt-BR/usage/customizing.md +46 -26
  57. package/docs/pt-BR/usage/feedback.md +5 -1
  58. package/docs/pt-BR/usage/forms.md +30 -5
  59. package/docs/pt-BR/usage/index.md +7 -3
  60. package/docs/pt-BR/usage/presets.md +92 -0
  61. package/docs/pt-BR/usage/solo.md +4 -2
  62. package/docs/pt-BR/usage/theming.md +22 -9
  63. package/docs/pt-BR/usage/tooltips.md +2 -2
  64. package/docs/setup.md +31 -22
  65. package/docs/usage/aesthetics.md +19 -13
  66. package/docs/usage/buttons.md +5 -1
  67. package/docs/usage/composing.md +5 -1
  68. package/docs/usage/content-and-layout.md +9 -3
  69. package/docs/usage/customizing.md +45 -25
  70. package/docs/usage/feedback.md +4 -0
  71. package/docs/usage/forms.md +29 -4
  72. package/docs/usage/index.md +6 -2
  73. package/docs/usage/presets.md +91 -0
  74. package/docs/usage/solo.md +3 -1
  75. package/docs/usage/theming.md +21 -8
  76. package/docs/usage/tooltips.md +1 -1
  77. package/llms-full.txt +695 -134
  78. package/llms.txt +3 -2
  79. package/package.json +117 -65
  80. package/{dist/tw → tw}/aesthetics/chunky-tile.css +43 -20
  81. package/{dist/tw → tw}/aesthetics/cyber.css +19 -25
  82. package/{dist/tw → tw}/aesthetics/glass.css +110 -36
  83. package/{dist/tw → tw}/aesthetics/neobrutalism.css +41 -21
  84. package/{dist/tw → tw}/aesthetics/pixel.css +3 -0
  85. package/tw/aesthetics/sketch.css +435 -0
  86. package/{dist/tw → tw}/box.css +109 -26
  87. package/tw/components/button.css +11 -0
  88. package/tw/components/button.rules.css +187 -0
  89. package/tw/components/feedback.css +11 -0
  90. package/{dist/tw/components/feedback.css → tw/components/feedback.rules.css} +156 -33
  91. package/tw/components/form.css +11 -0
  92. package/{dist/tw/components/form.css → tw/components/form.rules.css} +584 -141
  93. package/tw/components/index.css +16 -0
  94. package/tw/components/rules.css +41 -0
  95. package/tw/components/surface.css +11 -0
  96. package/tw/components/surface.rules.css +225 -0
  97. package/tw/components/tooltip.css +11 -0
  98. package/{dist/tw/components/tooltip.css → tw/components/tooltip.rules.css} +82 -61
  99. package/{dist/tw → tw}/corner.css +18 -12
  100. package/{dist/tw → tw}/elevation.css +27 -21
  101. package/{dist/tw → tw}/index.css +11 -9
  102. package/tw/index.d.ts +1 -0
  103. package/tw/intent.css +312 -0
  104. package/tw/modifiers.css +127 -0
  105. package/tw/native.css +323 -0
  106. package/tw/presentation.css +139 -0
  107. package/tw/reset.css +10 -0
  108. package/{dist/tw/reset.css → tw/reset.rules.css} +7 -8
  109. package/tw/size.css +34 -0
  110. package/tw/surface.css +9 -0
  111. package/tw/surface.rules.css +212 -0
  112. package/{dist/tw → tw}/theme.css +93 -29
  113. package/tw/typography.css +8 -0
  114. package/{dist/tw/typography.css → tw/typography.rules.css} +0 -3
  115. package/{dist/tw → tw}/utilities/content.css +248 -108
  116. package/tw/utilities/index.css +11 -0
  117. package/tw/utilities/layout.css +210 -0
  118. package/tw/utilities/rules.css +8 -0
  119. package/dist/tw/aesthetics/sketch.css +0 -398
  120. package/dist/tw/components/button.css +0 -139
  121. package/dist/tw/components/index.css +0 -35
  122. package/dist/tw/components/surface.css +0 -184
  123. package/dist/tw/intent.css +0 -229
  124. package/dist/tw/native.css +0 -203
  125. package/dist/tw/palette.css +0 -460
  126. package/dist/tw/presentation.css +0 -68
  127. package/dist/tw/surface.css +0 -61
  128. package/dist/tw/utilities/index.css +0 -6
  129. package/dist/tw/utilities/layout.css +0 -144
  130. /package/{dist/tw → tw}/aesthetics/index.css +0 -0
package/dist/theme.css CHANGED
@@ -1,2 +1,2 @@
1
- /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
- @layer theme{:root,:host{--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-800:oklch(43.2% .095 166.913);--color-emerald-900:oklch(37.8% .077 168.94);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-800:oklch(39.8% .195 277.366);--color-indigo-900:oklch(35.9% .144 278.697);--color-rose-100:oklch(94.1% .03 12.58);--color-rose-300:oklch(81% .117 11.638);--color-rose-700:oklch(51.4% .222 16.935);--color-rose-800:oklch(45.5% .188 13.697);--color-rose-900:oklch(41% .159 10.272);--color-neutral-50:oklch(98.5% 0 none);--color-neutral-100:oklch(97% 0 none);--color-neutral-200:oklch(92.2% 0 none);--color-neutral-300:oklch(87% 0 none);--color-neutral-400:oklch(70.8% 0 none);--color-neutral-500:oklch(55.6% 0 none);--color-neutral-600:oklch(43.9% 0 none);--color-neutral-700:oklch(37.1% 0 none);--color-neutral-800:oklch(26.9% 0 none);--color-neutral-900:oklch(20.5% 0 none);--color-neutral-950:oklch(14.5% 0 none);--color-white:#fff;--font-default:"Segoe UI", system-ui, sans-serif;--color-primary:light-dark(var(--color-neutral-950),var(--color-neutral-50));--color-primary-contrast:light-dark(var(--color-neutral-50),var(--color-neutral-950));--color-primary-hover:light-dark(var(--color-neutral-700),var(--color-neutral-200));--color-primary-subtle:light-dark(var(--color-neutral-200),var(--color-neutral-900));--color-primary-strong:light-dark(var(--color-neutral-900),var(--color-neutral-100));--color-accent:light-dark(var(--color-neutral-600),var(--color-neutral-400));--color-accent-contrast:light-dark(var(--color-neutral-50),var(--color-neutral-950));--color-accent-hover:light-dark(var(--color-neutral-700),var(--color-neutral-300));--color-accent-subtle:light-dark(var(--color-neutral-100),var(--color-neutral-800));--color-accent-strong:light-dark(var(--color-neutral-800),var(--color-neutral-200));--color-border:light-dark(var(--color-neutral-400),var(--color-neutral-700));--color-border-hover:light-dark(var(--color-neutral-600),var(--color-neutral-500));--color-control-border:var(--color-neutral-500);--color-background:light-dark(var(--color-neutral-50),var(--color-neutral-950));--color-foreground:light-dark(var(--color-neutral-100),var(--color-neutral-900));--color-surface:light-dark(var(--color-neutral-200),var(--color-neutral-800));--color-text:light-dark(var(--color-neutral-950),var(--color-neutral-50));--color-text-secondary:light-dark(var(--color-neutral-700),var(--color-neutral-400));--color-text-contrast:light-dark(var(--color-neutral-50),var(--color-neutral-950));--color-text-hover:light-dark(var(--color-neutral-700),var(--color-neutral-200));--color-text-strong:light-dark(var(--color-neutral-900),var(--color-neutral-100));--color-tooltip:light-dark(var(--color-white),var(--color-neutral-700));--color-tooltip-contrast:light-dark(var(--color-neutral-900),var(--color-neutral-100));--color-success:var(--color-emerald-700);--color-success-contrast:var(--color-neutral-50);--color-success-hover:light-dark(#007552,#008e66);--color-success-subtle:light-dark(var(--color-emerald-100),var(--color-emerald-900));--color-success-strong:light-dark(var(--color-emerald-800),var(--color-emerald-300));--color-warning:var(--color-amber-600);--color-warning-contrast:var(--color-neutral-950);--color-warning-hover:light-dark(#d46700,#e78300);--color-warning-subtle:light-dark(var(--color-amber-100),var(--color-amber-900));--color-warning-strong:light-dark(var(--color-amber-800),var(--color-amber-300));--color-destructive:var(--color-rose-700);--color-destructive-contrast:var(--color-neutral-50);--color-destructive-hover:light-dark(#c00036,#d1054b);--color-destructive-subtle:light-dark(var(--color-rose-100),var(--color-rose-900));--color-destructive-strong:light-dark(var(--color-rose-800),var(--color-rose-300));--color-info:var(--color-indigo-600);--color-info-contrast:var(--color-neutral-50);--color-info-hover:light-dark(#4b36e9,#5e4ff9);--color-info-subtle:light-dark(var(--color-indigo-100),var(--color-indigo-900));--color-info-strong:light-dark(var(--color-indigo-800),var(--color-indigo-300))}:root{color-scheme:light dark;--container-narrow:48rem;--container-max:80rem;--container-wide:90rem;--layout-gutter:clamp(1rem, 4vw, 2rem);--layout-section-block:clamp(4rem, 9vw, 7rem);--layout-gap:1rem;--layout-grid-min:16rem;--radius-small:.25rem;--radius-control:.5rem;--radius-surface:.875rem;--control-height:2.5rem;--border-width:1px;--elevation-color:light-dark(#0f172a14,#0000008c);--elevation-none:none;--elevation-sm:0 1px 2px var(--elevation-color), 0 1px 3px var(--elevation-color);--elevation-md:0 4px 6px -1px var(--elevation-color), 0 2px 4px -2px var(--elevation-color);--elevation-lg:0 20px 25px -5px var(--elevation-color), 0 8px 10px -6px var(--elevation-color);--focus-ring:color-mix(in srgb, light-dark(var(--color-neutral-950),var(--color-neutral-50)) 64%, transparent)}@supports (color:color-mix(in lab, red, red)){:root{--focus-ring:color-mix(in srgb, var(--color-primary) 64%, transparent)}}:root{--focus-ring-width:3px;--motion-duration-fast:.12s;--motion-duration-normal:.2s;--motion-duration-slow:.4s;--motion-ease:cubic-bezier(.2, 0, 0, 1);--z-popover:40;--hover-step:14%;--ui-active-transform:scale(.97)}@media (prefers-reduced-motion:reduce){:root{--ui-active-transform:none}}.light,.theme-light,[data-theme=light]{color-scheme:light}.dark,.theme-dark,[data-theme=dark]{color-scheme:dark}}@layer base;@layer components{:root,.neutral{--intent-color:var(--color-text);--intent-contrast:var(--color-text-contrast);--intent-hover:var(--color-text-hover);--intent-strong:var(--color-text-strong);--intent-subtle:var(--color-surface);--intent-border:var(--ui-ink,var(--color-border));--intent-fill-max:20%}.primary{--intent-color:var(--color-primary);--intent-contrast:var(--color-primary-contrast);--intent-hover:var(--color-primary-hover);--intent-strong:var(--color-primary-strong);--intent-subtle:var(--color-primary-subtle);--intent-border:var(--color-primary);--intent-fill-max:100%}.secondary{--intent-color:var(--color-accent);--intent-contrast:var(--color-accent-contrast);--intent-hover:var(--color-accent-hover);--intent-strong:var(--color-accent-strong);--intent-subtle:var(--color-accent-subtle);--intent-border:var(--color-accent);--intent-fill-max:100%}.success{--intent-color:var(--color-success);--intent-contrast:var(--color-success-contrast);--intent-hover:var(--color-success-hover);--intent-strong:var(--color-success-strong);--intent-subtle:var(--color-success-subtle);--intent-border:var(--color-success);--intent-fill-max:100%}.warning{--intent-color:var(--color-warning);--intent-contrast:var(--color-warning-contrast);--intent-hover:var(--color-warning-hover);--intent-strong:var(--color-warning-strong);--intent-subtle:var(--color-warning-subtle);--intent-border:var(--color-warning);--intent-fill-max:100%}.destructive{--intent-color:var(--color-destructive);--intent-contrast:var(--color-destructive-contrast);--intent-hover:var(--color-destructive-hover);--intent-strong:var(--color-destructive-strong);--intent-subtle:var(--color-destructive-subtle);--intent-border:var(--color-destructive);--intent-fill-max:100%}.info{--intent-color:var(--color-info);--intent-contrast:var(--color-info-contrast);--intent-hover:var(--color-info-hover);--intent-strong:var(--color-info-strong);--intent-subtle:var(--color-info-subtle);--intent-border:var(--color-info);--intent-fill-max:100%}:where(.btn,.ipt,.text-control,.surface,.textarea,.select,.input-group,.checkbox,.radio,.switch,.card,.panel,.alert,.data-table,.pre,.quote,.tooltip-bubble,.tooltip-icon,.badge,.kbd,.code,.skeleton,.progress,.divider){--intent-color:var(--color-text);--intent-contrast:var(--color-text-contrast);--intent-hover:var(--color-text-hover);--intent-strong:var(--color-text-strong);--intent-subtle:var(--color-surface);--intent-border:var(--ui-ink,var(--color-border));--intent-fill-max:20%}:where(.text-control,.ipt,.textarea,.select,.input-group,.checkbox,.radio,.switch),:is(.text-control,.ipt,.textarea,.select,.input-group,.checkbox,.radio,.switch).neutral{--intent-border:var(--ui-control-ink,var(--ui-ink,var(--color-control-border)))}:where(.data-table),.data-table.neutral,.data-table tr.neutral{--intent-border:var(--ui-rule-ink,var(--ui-ink,var(--color-border)))}:where(.tooltip-bubble),.tooltip-bubble.neutral{--intent-color:var(--color-tooltip);--intent-contrast:var(--color-tooltip-contrast);--intent-hover:var(--color-tooltip);--intent-strong:var(--color-tooltip-contrast);--intent-subtle:var(--color-surface);--intent-border:var(--ui-ink,var(--color-border));--intent-fill-max:100%}:where(.skeleton,.progress,.divider){--intent-color:currentColor;--intent-border:currentColor}.solid{--ui-fill:100%;--ui-fg-on-fill:100%}.soft{--ui-fill:12%;--ui-fg-on-fill:0%}.ghost{--ui-fill:0%;--ui-fg-on-fill:0%}.edged{--ui-border:100%}.edgeless{--ui-border:0%}@property --ui-elevation{syntax:"*";inherits:false}@property --elevation-y{syntax:"*";inherits:false}@property --elevation-blur{syntax:"*";inherits:false}.flat{--ui-elevation:0}.raised,.floating{--elevation-y:1px;--elevation-blur:3px}.raised{--ui-elevation:1}.floating{--ui-elevation:2}.cut-diagonal{--ui-corner-tl:1;--ui-corner-tr:0;--ui-corner-br:1;--ui-corner-bl:0}.cut-diagonal-reverse{--ui-corner-tl:0;--ui-corner-tr:1;--ui-corner-br:0;--ui-corner-bl:1}}@layer utilities;@media (forced-colors:active){*{--ui-border-max:initial;--ui-clip:none;--ui-clip-tight:none;--ui-shadow-edge:initial;--ui-line-style:solid;--ui-rule-style:solid;--ui-halo-ink:initial;--ui-surface-image:none;--ui-label-shadow:none}}
1
+ /*! tailwindcss v4.3.4 | MIT License | https://tailwindcss.com */
2
+ @layer theme{:root,:host{--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-800:oklch(43.2% .095 166.913);--color-emerald-900:oklch(37.8% .077 168.94);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-800:oklch(39.8% .195 277.366);--color-indigo-900:oklch(35.9% .144 278.697);--color-rose-100:oklch(94.1% .03 12.58);--color-rose-300:oklch(81% .117 11.638);--color-rose-700:oklch(51.4% .222 16.935);--color-rose-800:oklch(45.5% .188 13.697);--color-rose-900:oklch(41% .159 10.272);--color-neutral-50:oklch(98.5% 0 none);--color-neutral-100:oklch(97% 0 none);--color-neutral-200:oklch(92.2% 0 none);--color-neutral-300:oklch(87% 0 none);--color-neutral-400:oklch(70.8% 0 none);--color-neutral-500:oklch(55.6% 0 none);--color-neutral-600:oklch(43.9% 0 none);--color-neutral-700:oklch(37.1% 0 none);--color-neutral-800:oklch(26.9% 0 none);--color-neutral-900:oklch(20.5% 0 none);--color-neutral-950:oklch(14.5% 0 none);--color-white:#fff;--font-default:"Segoe UI", system-ui, sans-serif;--color-primary:light-dark(var(--color-neutral-950),var(--color-neutral-50));--color-primary-contrast:light-dark(var(--color-neutral-50),var(--color-neutral-950));--color-primary-hover:light-dark(var(--color-neutral-700),var(--color-neutral-200));--color-primary-subtle:light-dark(var(--color-neutral-200),var(--color-neutral-900));--color-primary-strong:light-dark(var(--color-neutral-900),var(--color-neutral-100));--color-accent:light-dark(var(--color-neutral-600),var(--color-neutral-400));--color-accent-contrast:light-dark(var(--color-neutral-50),var(--color-neutral-950));--color-accent-hover:light-dark(var(--color-neutral-700),var(--color-neutral-300));--color-accent-subtle:light-dark(var(--color-neutral-100),var(--color-neutral-800));--color-accent-strong:light-dark(var(--color-neutral-800),var(--color-neutral-200));--color-border:var(--_contrast-border,light-dark(var(--color-neutral-400),var(--color-neutral-700)));--color-border-hover:light-dark(var(--color-neutral-600),var(--color-neutral-500));--color-control-border:var(--color-neutral-500);--color-background:light-dark(var(--color-neutral-50),var(--color-neutral-950));--color-foreground:light-dark(var(--color-neutral-100),var(--color-neutral-900));--color-surface:light-dark(var(--color-neutral-200),var(--color-neutral-800));--color-text:light-dark(var(--color-neutral-950),var(--color-neutral-50));--color-text-secondary:light-dark(var(--color-neutral-700),var(--color-neutral-400));--color-text-contrast:light-dark(var(--color-neutral-50),var(--color-neutral-950));--color-text-hover:light-dark(var(--color-neutral-700),var(--color-neutral-200));--color-text-strong:light-dark(var(--color-neutral-900),var(--color-neutral-100));--color-tooltip:light-dark(var(--color-white),var(--color-neutral-700));--color-tooltip-contrast:light-dark(var(--color-neutral-900),var(--color-neutral-100));--color-success:var(--color-emerald-700);--color-success-contrast:var(--color-neutral-50);--color-success-hover:light-dark(#007552,#008e66);--color-success-subtle:light-dark(var(--color-emerald-100),var(--color-emerald-900));--color-success-strong:light-dark(var(--color-emerald-800),var(--color-emerald-300));--color-warning:var(--color-amber-600);--color-warning-contrast:var(--color-neutral-950);--color-warning-hover:light-dark(#d46700,#e78300);--color-warning-subtle:light-dark(var(--color-amber-100),var(--color-amber-900));--color-warning-strong:light-dark(var(--color-amber-800),var(--color-amber-300));--color-destructive:var(--color-rose-700);--color-destructive-contrast:var(--color-neutral-50);--color-destructive-hover:light-dark(#c00036,#d1054b);--color-destructive-subtle:light-dark(var(--color-rose-100),var(--color-rose-900));--color-destructive-strong:light-dark(var(--color-rose-800),var(--color-rose-300));--color-info:var(--color-indigo-600);--color-info-contrast:var(--color-neutral-50);--color-info-hover:light-dark(#4b36e9,#5e4ff9);--color-info-subtle:light-dark(var(--color-indigo-100),var(--color-indigo-900));--color-info-strong:light-dark(var(--color-indigo-800),var(--color-indigo-300))}:root{color-scheme:light dark;--container-narrow:48rem;--container-max:80rem;--container-wide:90rem;--layout-gutter:clamp(1rem, 4vw, 2rem);--layout-section-block:clamp(4rem, 9vw, 7rem);--layout-gap:1rem;--layout-grid-min:16rem;--radius-small:.25rem;--radius-control:.5rem;--radius-surface:.875rem;--control-height:2.5rem;--border-width:1px;--elevation-color:light-dark(#0f172a14,#0000008c);--elevation-none:none;--elevation-sm:0 1px 2px var(--elevation-color), 0 1px 3px var(--elevation-color);--elevation-md:0 4px 6px -1px var(--elevation-color), 0 2px 4px -2px var(--elevation-color);--elevation-lg:0 20px 25px -5px var(--elevation-color), 0 8px 10px -6px var(--elevation-color);--focus-ring-width:3px;--motion-duration-fast:.12s;--motion-duration-normal:.2s;--motion-duration-slow:.4s;--motion-ease:cubic-bezier(.2, 0, 0, 1);--z-popover:40;--hover-step:14%;--ui-active-transform:scale(.97)}.light,.theme-light,[data-theme=light]{color-scheme:light;color:var(--color-text)}.dark,.theme-dark,[data-theme=dark]{color-scheme:dark;color:var(--color-text)}@media print{:root,.dark,.theme-dark,[data-theme=dark]{color-scheme:light}}@media (prefers-contrast:more){:root,:host{--_contrast-border:light-dark(var(--color-neutral-600),var(--color-neutral-400))}}}@layer base;@layer components{:root{--intent-color:var(--color-text);--intent-contrast:var(--color-text-contrast);--intent-hover:var(--color-text-hover);--intent-strong:var(--color-text-strong);--intent-subtle:var(--color-surface);--intent-fill-max:20%}:where(.btn,.ipt,.text-control,.surface,.textarea,.select,.input-group,.checkbox,.radio,.switch,.card,.panel,.alert,.data-table,.pre,.quote,.tooltip-bubble,.tooltip-icon,.badge,.kbd,.code,.skeleton,.progress,.divider){--intent-color:var(--color-text);--intent-contrast:var(--color-text-contrast);--intent-hover:var(--color-text-hover);--intent-strong:var(--color-text-strong);--intent-subtle:var(--color-surface);--intent-border:var(--ui-ink,var(--color-border));--intent-fill-max:20%}:where(.text-control,.ipt,.textarea,.select,.input-group,.checkbox,.radio,.switch){--intent-border:var(--ui-control-ink,var(--ui-ink,var(--color-control-border)))}:where(.data-table){--intent-border:var(--ui-rule-ink,var(--ui-ink,var(--color-border)))}:where(.tooltip-bubble){--intent-color:var(--color-tooltip);--intent-contrast:var(--color-tooltip-contrast);--intent-hover:var(--color-tooltip);--intent-strong:var(--color-tooltip-contrast);--intent-subtle:var(--color-surface);--intent-border:var(--ui-ink,var(--color-border));--intent-fill-max:100%}:where(.skeleton,.progress,.divider){--intent-color:currentColor;--intent-border:currentColor}}@layer utilities{@layer families{.destructive{--intent-color:var(--color-destructive);--intent-contrast:var(--color-destructive-contrast);--intent-hover:var(--color-destructive-hover);--intent-strong:var(--color-destructive-strong);--intent-subtle:var(--color-destructive-subtle);--intent-border:var(--color-destructive);--intent-fill-max:100%}@media (prefers-contrast:more){.destructive{--intent-border:var(--color-destructive-strong)}}.info{--intent-color:var(--color-info);--intent-contrast:var(--color-info-contrast);--intent-hover:var(--color-info-hover);--intent-strong:var(--color-info-strong);--intent-subtle:var(--color-info-subtle);--intent-border:var(--color-info);--intent-fill-max:100%}@media (prefers-contrast:more){.info{--intent-border:var(--color-info-strong)}}.primary{--intent-color:var(--color-primary);--intent-contrast:var(--color-primary-contrast);--intent-hover:var(--color-primary-hover);--intent-strong:var(--color-primary-strong);--intent-subtle:var(--color-primary-subtle);--intent-border:var(--color-primary);--intent-fill-max:100%}@media (prefers-contrast:more){.primary{--intent-border:var(--color-primary-strong)}}.secondary{--intent-color:var(--color-accent);--intent-contrast:var(--color-accent-contrast);--intent-hover:var(--color-accent-hover);--intent-strong:var(--color-accent-strong);--intent-subtle:var(--color-accent-subtle);--intent-border:var(--color-accent);--intent-fill-max:100%}@media (prefers-contrast:more){.secondary{--intent-border:var(--color-accent-strong)}}.success{--intent-color:var(--color-success);--intent-contrast:var(--color-success-contrast);--intent-hover:var(--color-success-hover);--intent-strong:var(--color-success-strong);--intent-subtle:var(--color-success-subtle);--intent-border:var(--color-success);--intent-fill-max:100%}@media (prefers-contrast:more){.success{--intent-border:var(--color-success-strong)}}.warning{--intent-color:var(--color-warning);--intent-contrast:var(--color-warning-contrast);--intent-hover:var(--color-warning-hover);--intent-strong:var(--color-warning-strong);--intent-subtle:var(--color-warning-subtle);--intent-border:var(--color-warning);--intent-fill-max:100%}@media (prefers-contrast:more){.warning{--intent-border:var(--color-warning-strong)}}.neutral{--intent-color:var(--color-text);--intent-contrast:var(--color-text-contrast);--intent-hover:var(--color-text-hover);--intent-strong:var(--color-text-strong);--intent-subtle:var(--color-surface);--intent-border:var(--ui-ink,var(--color-border));--intent-fill-max:20%}.cut-diagonal{--ui-corner-tl:1;--ui-corner-tr:0;--ui-corner-br:1;--ui-corner-bl:0}.cut-diagonal-reverse{--ui-corner-tl:0;--ui-corner-tr:1;--ui-corner-br:0;--ui-corner-bl:1}.ghost{--ui-fill:0%;--ui-fg-on-fill:0%;--_own-fill:0%;--_holds-ink:none}.soft{--ui-fill:12%;--ui-fg-on-fill:0%;--_own-fill:12%;--_holds-ink:none}.solid{--ui-fill:100%;--ui-fg-on-fill:100%;--_own-fill:100%;--_holds-ink: }.floating{--_elevation-y:1px;--_elevation-blur:3px;--ui-elevation:2}.raised{--_elevation-y:1px;--_elevation-blur:3px;--ui-elevation:1}.edged{--ui-border:100%;--_own-edge:100%}.edgeless{--ui-border:0%;--_own-edge:0%}.flat{--ui-elevation:0}.lg{--_size-lg: }.sm{--_size-sm: }}}@layer utilities.families{:is(.text-control,.ipt,.textarea,.select,.input-group,.checkbox,.radio,.switch).neutral{--intent-border:var(--ui-control-ink,var(--ui-ink,var(--color-control-border)))}:is(.data-table,.data-table tr).neutral{--intent-border:var(--ui-rule-ink,var(--ui-ink,var(--color-border)))}.neutral.tooltip-bubble{--intent-color:var(--color-tooltip);--intent-contrast:var(--color-tooltip-contrast);--intent-hover:var(--color-tooltip);--intent-strong:var(--color-tooltip-contrast);--intent-subtle:var(--color-surface);--intent-border:var(--ui-ink,var(--color-border));--intent-fill-max:100%}}@property --_held-ink{syntax:"<color>";inherits:true;initial-value:#0000}@property --_held-on{syntax:"<percentage>";inherits:true;initial-value:0%}@property --_own-hold{syntax:"<percentage>";inherits:false;initial-value:0%}@property --_own-fill{syntax:"<percentage>";inherits:false;initial-value:0%}@property --_own-edge{syntax:"<percentage>";inherits:false;initial-value:100%}@property --ui-elevation{syntax:"*";inherits:false}@property --_elevation-y{syntax:"*";inherits:false}@property --_elevation-blur{syntax:"*";inherits:false}@property --_size-sm{syntax:"*";inherits:false}@property --_size-lg{syntax:"*";inherits:false}@media (forced-colors:active){*{--ui-border-max:initial;--ui-clip:none;--ui-clip-tight:none;--ui-shadow-edge:initial;--ui-line-style:solid;--ui-rule-style:solid;--ui-halo-ink:initial;--ui-surface-image:none;--ui-label-shadow:none}}
@@ -14,14 +14,14 @@ This page lists both halves: what the CSS provides, and what your application ha
14
14
 
15
15
  ### Focus and state
16
16
 
17
- | Feature | Behavior |
18
- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19
- | `:focus-visible` | A focus outline on every element, drawn with `--focus-ring`, `--focus-ring-width`, and `--focus-ring-offset`. |
20
- | Form control focus | `.ipt`, `.textarea`, and `.select` draw the focus outline and change their border to the intent color. Typed text in a field with an intent class is in the intent's readable tone, `--intent-strong`. |
21
- | Invalid controls | `aria-invalid="true"` on a form control turns its border, focus color, and typed text destructive, the text in the destructive readable tone. |
22
- | Disabled controls | `disabled`, `aria-disabled="true"`, `data-disabled`, and `.disabled` show the disabled cursor and opacity, and a disabled control does not react to hover, including inside an `.input-group`. |
23
- | Open state | `data-state="open"` on a `.tooltip` shows its bubble without hover or focus, and `data-state="closed"` hides it while hovered or focused. No other component reads either. |
24
- | Native `<dialog>` | A `<dialog>` with `.card`, `.panel`, or `.surface` stays hidden until it is opened, and opens centered. A margin you set on the dialog, as a utility or in your own CSS, still overrides the centering. Other dialogs are left alone. Trapping focus, closing on Escape, and making the page behind it inert are up to your application. |
17
+ | Feature | Behavior |
18
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
19
+ | `:focus-visible` | A focus outline on every element, drawn with `--focus-ring`, `--focus-ring-width`, and `--focus-ring-offset`. On a component filled past half strength, such as a `.solid.primary` button, a 2px line of the page color runs inside the ring, so the ring stays visible on a fill of its own color. |
20
+ | Form control focus | `.ipt`, `.textarea`, and `.select` draw the focus outline and change their border to the intent color. Typed text in a field with an intent class is in the intent's readable tone, `--intent-strong`. |
21
+ | Invalid controls | `aria-invalid="true"` on a form control turns its border, focus color, and typed text destructive, the text in the destructive readable tone. A checkbox, radio, or switch is drawn exactly as its `.destructive` version, checked mark included. |
22
+ | Disabled controls | `disabled`, `aria-disabled="true"`, `data-disabled`, and `.disabled` show the disabled cursor and opacity, and a disabled control does not react to hover, including inside an `.input-group`. |
23
+ | Open state | `data-state="open"` on a `.tooltip` shows its bubble without hover or focus, and `data-state="closed"` hides it while hovered or focused. No other component reads either. |
24
+ | Native `<dialog>` | A `<dialog>` with `.card`, `.panel`, `.surface`, or your own class that does `@apply surface` stays hidden until it is opened, and opens centered. A margin you set on the dialog, as a utility or in your own CSS, still overrides the centering, except that a margin utility does not when your class applies `surface` in plain CSS; see [Customizing → Composition helpers](./usage/customizing.md#composition-helpers). With the [classless stylesheet](./setup.md#classless-html), a plain `<dialog>` is a `.card.floating` and behaves the same; with the other entrypoints, a dialog with none of these classes is left alone. Trapping focus, closing on Escape, and making the page behind it inert are up to your application. |
25
25
 
26
26
  ### Visually hidden content
27
27
 
@@ -33,7 +33,7 @@ WCAG 1.4.11 asks that the boundary of a control you need to see to use it measur
33
33
 
34
34
  | Feature | Behavior |
35
35
  | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
36
- | Text controls at rest | A text control's border rests lighter than its intent's full border, below 3:1 by choice, so hover and focus have a stronger tone to change to. |
36
+ | Text controls at rest | A text control's border rests lighter than its intent's full border, below 3:1 by choice, so hover and focus have a stronger tone to change to. [Increased contrast](#increased-contrast) draws it whole. |
37
37
  | Toggles | `.checkbox`, `.radio`, and `.switch` draw their full border, because the border is the only thing that shows an unchecked box. A `.switch` with its own `.edgeless` is the exception, below. |
38
38
  | `.edgeless` from a container | Ignored by every text control and toggle: a container cannot remove the border of a field or toggle inside it. |
39
39
  | `.edgeless` on the control | `.ipt`, `.textarea`, `.select`, and `.switch` drop their border and no longer meet 1.4.11 at rest. `.switch.ghost` keeps its border even then, because with no fill and no border nothing would show the track. |
@@ -58,11 +58,11 @@ With no intent class, the outline is the quiet border gray, `--color-border`. To
58
58
 
59
59
  ### Motion and transparency
60
60
 
61
- | Feature | Behavior |
62
- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63
- | Reduced motion, components | With `prefers-reduced-motion: reduce`, every component stops its own transitions and animations: the skeleton and progress shimmer, the indeterminate bar, the tooltip, the toggle marks, and the press. |
64
- | Reduced motion, whole page | The reset also shortens every other animation and transition on the page. |
65
- | Reduced transparency | With `prefers-reduced-transparency: reduce`, `.glass` and `.glass-liquid` drop their blur and lens and become opaque. |
61
+ | Feature | Behavior |
62
+ | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63
+ | Reduced motion, components | With `prefers-reduced-motion: reduce`, every component stops its own transitions and animations: the skeleton and progress shimmer, the indeterminate bar, the tooltip, the toggle marks, and the press's motion. The press itself still happens, at once, on the default look and under every aesthetic and solo class, since it is the feedback that a click landed. |
64
+ | Reduced motion, whole page | The reset also shortens every other animation and transition on the page. |
65
+ | Reduced transparency | With `prefers-reduced-transparency: reduce`, and in forced colors, `.glass`, `.glass-liquid`, and `.glass-solo` drop their blur and lens and become opaque. |
66
66
 
67
67
  Each component's reduced-motion rule ships with the component, so every entrypoint that includes it respects reduced motion without the reset, including `@codenhub/styles/components`, `@codenhub/styles/tw/components`, and each `/tw/*` component entrypoint. The complete and native entrypoints add the reset's page-wide rule.
68
68
 
@@ -84,30 +84,49 @@ The reset's rule is `!important` inside the `base` layer, and a layered `!import
84
84
 
85
85
  Respecting reduced motion is not the whole requirement. Motion that keeps going next to content, such as a shimmer left on a card after it has loaded, needs a way to stop it for every user; see [Feedback → Animation that keeps running](./usage/feedback.md#animation-that-keeps-running).
86
86
 
87
+ ### Increased contrast
88
+
89
+ With `prefers-contrast: more`, the borders the package draws below 3:1 by choice are drawn at 3:1 or more against what is next to them, in both themes. Text, solid fills, and focus rings already meet their ratios and do not change. `prefers-contrast: less` is not read.
90
+
91
+ | Feature | Behavior |
92
+ | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
93
+ | Text controls | `.ipt`, `.textarea`, `.select`, and `.input-group` rest at their full border, so hover and focus no longer change its tone. The focus ring is the same. |
94
+ | Neutral borders | `--color-border` takes a heavier gray, `neutral-600` in light and `neutral-400` in dark, so a card's border, a divider, a table's rules, and a neutral button's or badge's border meet 3:1. If you set `--color-border` yourself, your color is kept; measure it. |
95
+ | Intent borders | An intent's border takes its strong tone, `--color-<intent>-strong`, so `.edged` on a `.soft` `.alert`, `.panel`, `.badge`, `.kbd`, `.code`, or `.pre` meets 3:1 against both its fill and the page, for every intent. |
96
+ | Progress track | The track draws an outline in its border color, which meets 3:1 with or without an intent class. `.edgeless` on the bar or on a container still removes it. |
97
+ | Glass | `.glass`, `.glass-liquid`, and `.glass-solo` drop their blur and lens and become opaque, as with reduced transparency, and their white hairline becomes a gray border. |
98
+ | Chunky tile | `.chunky-tile` draws tiles and surfaces in the heavier gray its controls use. |
99
+
100
+ What you remove stays removed: `.edgeless` on a control still drops its border, and a `.panel` still has none unless you add `.edged`.
101
+
87
102
  ### Color and contrast
88
103
 
89
104
  The measurements below are for the shipped colors. Once you change a color token, measure your own pairs again; [Theming → Change the brand color](./usage/theming.md#change-the-brand-color) shows which pairs to check.
90
105
 
91
- | Feature | Behavior |
92
- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
93
- | Filled labels | Every intent's `.solid` label meets 4.5:1 (WCAG 1.4.3) as normal text, in both themes. The lowest is success, at 5.14:1. |
94
- | Warning text | `--color-warning-contrast` is near-black, not the page color, because an amber dark enough to carry white text no longer looks amber. |
95
- | Partial fills | The contrast text color appears only on fills above half strength, so a text control's capped fill keeps the intent's own text color. |
96
- | Intent color in dark | In dark mode a `.soft` or `.ghost` label uses the `-300` shade of its intent, so it keeps its hue instead of turning white. |
97
- | Toggle marks | A checked mark measures at least 3:1 against every fill its presentation can give it, in both themes. |
98
- | Soft fills with borders | `.edged` on a `.soft` `.alert`, `.panel`, `.badge`, `.kbd`, `.code`, or `.pre` draws a border that measures below 3:1 against the 12% fill for some intents, which ones depending on the theme. Measure the pair before relying on that border as a control's boundary. |
106
+ | Feature | Behavior |
107
+ | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
108
+ | Filled labels | Every intent's `.solid` label meets 4.5:1 (WCAG 1.4.3) as normal text, in both themes. The lowest is success, at 5.14:1. |
109
+ | Warning text | `--color-warning-contrast` is near-black, not the page color, because an amber dark enough to carry white text no longer looks amber. |
110
+ | Partial fills | The contrast text color appears only on fills above half strength, so a text control's capped fill keeps the intent's own text color. |
111
+ | Intent color in dark | In dark mode a `.soft` or `.ghost` label uses the `-300` shade of its intent, so it keeps its hue instead of turning white. |
112
+ | Text on a filled parent | A neutral component that is not `.solid`, such as a badge in a `.btn.primary` or a ghost button in a `.card.solid.primary`, prints in its parent's text color instead of the page's, so it keeps the parent's contrast. |
113
+ | Print | A page prints in the light theme, and filled components print their background (`print-color-adjust: exact`), so contrast text never lands on blank paper. A `dark:` utility still applies in print; see [Theming → Printing](./usage/theming.md#printing). |
114
+ | Toggle marks | A checked mark measures at least 3:1 against every fill its presentation can give it, in both themes. |
115
+ | Soft fills with borders | `.edged` on a `.soft` `.alert`, `.panel`, `.badge`, `.kbd`, `.code`, or `.pre` draws a border that measures below 3:1 against the 12% fill for some intents, which ones depending on the theme. Measure the pair before relying on that border as a control's boundary. [Increased contrast](#increased-contrast) brings every one of them to 3:1. |
99
116
 
100
117
  ### Forced colors and direction
101
118
 
102
- | Feature | Behavior |
103
- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
104
- | Forced colors | With `forced-colors: active`, borders, checked states, and a `.select`'s chevron stay visible, drawn in system colors, under every aesthetic. An aesthetic that draws its border as an inner shadow, such as `.pixel`, draws a real border instead. |
105
- | Text direction | Under `dir="rtl"`, the quote bar, the alert icon, the progress fill, the vertical divider, the switch knob, table alignment, and a select's chevron all switch sides. No class is needed. |
119
+ | Feature | Behavior |
120
+ | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
121
+ | Forced colors | With `forced-colors: active`, borders, checked states, a `.select`'s chevron, and a progress bar's value stay visible, drawn in system colors, under every aesthetic. An aesthetic that draws its border as an inner shadow, such as `.pixel`, draws a real border instead. Glass becomes opaque, because forced colors keep a background's transparency. |
122
+ | Text direction | Under `dir="rtl"`, the quote bar, the alert icon, the progress fill, the vertical divider, the switch knob, table alignment, and a select's chevron all switch sides. No class is needed. |
106
123
 
107
- In forced colors, `.text-control`, `.ipt`, `.textarea`, `.select`, and the toggles show a 2px `Highlight` focus outline. The native entrypoint gives unclassed text inputs, selects, textareas, checkboxes, and radios the same outline.
124
+ In forced colors, `.text-control`, `.ipt`, `.textarea`, `.select`, the toggles, and your own class that does `@apply text-control` show a 2px `Highlight` focus outline. Inside an `.input-group`, the group draws the field's ring and the control inside draws none, so a focused field shows one ring. The native entrypoint gives unclassed text inputs, selects, textareas, checkboxes, and radios the same outline.
108
125
 
109
126
  Checkboxes, radios, and switches use the system colors `Canvas`, `CanvasText`, `Highlight`, and `HighlightText`, so checked and unchecked stay distinct: a checked toggle is filled with `Highlight` and its mark is `HighlightText`, on the classes and in the native entrypoint alike. Shape, size, and spacing do not change.
110
127
 
128
+ A `.progress` bar does the same: its filled part is `CanvasText` on a `Canvas` track with a `CanvasText` outline, whatever its intent or presentation, so a half-full bar does not read as an empty one. The `.active` shimmer is not drawn.
129
+
111
130
  ## Required outside CSS
112
131
 
113
132
  Use the HTML element that matches what the component does, and add the behavior the CSS cannot.
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: 0.8.0
3
+ date: 2026-11-12
4
+ description: Every class, modifier, and size is a Tailwind utility on /tw, a build command for projects without a bundler, sizes for text fields, a /tw build that emits only the classes you use, smaller compiled stylesheets, and fixes to applied helpers, input groups, focus rings, nested aesthetics, and forced colors.
5
+ ---
6
+
7
+ # 0.8.0
8
+
9
+ On `/tw` every intent, presentation, elevation, corner, size, and modifier class is a Tailwind utility, so `@apply btn primary soft sm` and `md:lg` work, and a `/tw` build emits only the classes your pages use. A `codenhub-styles build` command writes that trimmed stylesheet for a project that does not run Tailwind, with a bundler or without one. Text fields take `.sm` and `.lg`. The compiled stylesheets are about half their size before compression. The release also fixes a round of bugs in applied helpers, input groups, focus rings, nested aesthetics, and forced colors.
10
+
11
+ ## Added
12
+
13
+ - **Every class is a utility on `/tw`.** The intents, the presentation (`solid`, `soft`, `ghost`, `edged`, `edgeless`), the elevation (`flat`, `raised`, `floating`), the corner patterns, and the sizes (`sm`, `lg`) are Tailwind utilities, so one class of yours can carry a whole recipe, `@utility btn-save { @apply btn primary soft sm; }`, and variants such as `hover:primary`, `md:lg`, and `dark:solid` apply a class under a condition. Before, they were plain classes: `@apply` could not name them and those variants compiled to nothing. See [Tailwind CSS v4 → Build your own components with `@apply`](../integrating/tailwind.md#build-your-own-components-with-apply).
14
+ - **Component modifiers are utilities too.** `tight`, `loose`, `vertical`, `horizontal`, `between`, `narrow`, `wide`, `p-xs`, `p-sm`, `p-lg`, `flush`, `icon`, `pill`, `active`, `indeterminate`, `ruled`, `ruleless`, `interactive`, `hoverable`, and `pressable` work in `@apply` and with variants: `@apply stack tight`, `@apply btn icon pill`, and `md:tight`. A modifier still changes only the components that read it; `.wide` or `.active` on an element of your own sets nothing visible. The disabled state is not a utility: it stays the `disabled`, `aria-disabled`, or `data-disabled` attribute, or the `.disabled` class in markup.
15
+ - **A build command for projects without a bundler.** `npx codenhub-styles build --content "app/views/**/*.erb" --output public/stylekit.css` reads your templates and writes one minified stylesheet with only the classes they use, for plain HTML, Rails, Laravel, Django, any server-rendered app, or a bundler build without Tailwind. It needs Node.js 24 or newer and `@tailwindcss/cli` and `tailwindcss` 4.3.2 or newer, below 5, installed, and stops with a one-line message naming whatever is missing. `@tailwindcss/cli` joins `tailwindcss` as an optional peer dependency, so a project that does not run the command installs nothing new. See [Without a bundler → Build only the classes you use](../integrating/without-a-bundler.md#build-only-the-classes-you-use).
16
+ - **Sizes for text fields.** `.ipt`, `.select`, `.textarea`, and `.input-group` take `.sm` and `.lg` with the button's heights, text sizes, and corner step, so a small field and a small button line up in a row. See [Forms → Sizes](../usage/forms.md#sizes).
17
+ - **`<dialog>` and `<progress>` under `/native`.** A plain `<dialog>` is a `.card.floating`, hidden until opened and centered, and a plain `<progress>` is a `.progress` filled to its `value`, or the indeterminate sweep with no `value`. See [Setup → Classless HTML](../setup.md#classless-html).
18
+ - **Pages print in the light theme.** Under `@media print` every theme resolves to its light values, a forced-dark region's included, and filled components print their background (`print-color-adjust: exact`), so a solid button's white label no longer prints on blank paper. A `dark:` utility still applies in print. See [Theming → Printing](../usage/theming.md#printing).
19
+ - **Presets.** A new guide, [Presets](../usage/presets.md), compares the three ways to set a look once: axis classes on a container, theme and material tokens, and your own component classes built with `@apply`.
20
+ - **Dropping Tailwind's palette.** [Tailwind CSS v4 → Drop Tailwind's palette](../integrating/tailwind.md#drop-tailwinds-palette) has the `@theme` block that clears the hues your design does not use, and names the six ramps the theme needs.
21
+ - **Parcel and `postcss-import`.** [Integrating → Bundlers that need a nudge](../integrating/index.md#bundlers-that-need-a-nudge) shows the one change each needs to find the stylesheet.
22
+
23
+ ## Changed
24
+
25
+ - **Breaking: the `/tw` source moved from `dist/tw/` to `tw/`.** Imports through the package's exports, such as `@import "@codenhub/styles/tw"`, are unchanged. A path that reaches into `node_modules/@codenhub/styles/dist/tw/` breaks; point it at `tw/`. `dist/` now holds only finished CSS, plus an empty `index.d.ts` for TypeScript, so Django's `ManifestStaticFilesStorage` no longer fails `collectstatic` on it.
26
+ - **Breaking: a `/tw` build emits only the classes your files name.** The `/tw` copy no longer lists every package class for Tailwind to generate, so a page using one button compiles to about 28 KB minified where it compiled to the whole 416 KB stylesheet. The intent, presentation, elevation, corner, and size classes, and the modifiers, are now generated only when they are found too, where the intent, presentation, and elevation classes used to be emitted always. A class name built at runtime, such as `` `btn ${tone}` ``, or one that comes from a CMS, has no styling until you write it out where Tailwind scans or list it with `@source inline("btn primary destructive soft")`. See [Tailwind CSS v4 → Troubleshooting](../integrating/tailwind.md#troubleshooting). The aesthetic classes are still always emitted.
27
+ - **Breaking: the class families moved to a sublayer of `utilities`.** The intent, presentation, edge, elevation, corner, and size classes sat in the `components` layer; they now sit in `utilities.families`, which loses to every other rule in `utilities`. Your utilities and unlayered CSS still beat them. A rule of yours in the `components` layer, or in a layer of your own declared before `utilities`, no longer does: `@layer components { .my-card { --ui-fill: 50%; } }` now loses to `.solid` on the same element. Move such a rule into a utility, into unlayered CSS, or into a layer declared after `utilities`. See [Setup → Cascade layers](../setup.md#cascade-layers).
28
+ - **Your utility beats a modifier and a component's inner defaults.** A modifier or size used to be a 0-2-0 rule nested in its component, so it beat a utility on the same element. Now a modifier only raises a flag its component reads at the weight of its default, so `gap-2` on a `.stack.tight`, `px-8` on a `.btn.sm`, `text-sm` on a `.label`, and `p-0 text-center` on a `.data-table` cell all apply. If you wrote such a utility and relied on the modifier winning, remove the utility.
29
+ - **`.interactive`, `.hoverable`, and `.pressable` work on any element `box` paints, not only `.card`.** A `.badge`, a `.panel`, or your own `@apply box` element takes the hover and the press, and `.interactive` and `.pressable` set the pointer cursor on any element that carries them. If your own markup already uses one of these class names for something else, the element now takes the pointer cursor and the press; rename your class. A disabled `.interactive` or `.pressable` card shows the not-allowed cursor now, where it kept the pointer.
30
+ - **`.ruled` and `.ruleless` on a container reach every table inside it.** They reached only the `.data-table` carrying them; a `.ruleless` wrapper now drops the body rules of every table it holds.
31
+ - **The compiled stylesheets are about half their size before compression.** Each composed rule repeated its declarations once for every file that referenced it; they are stated once now. The compiled files also drop the fallbacks Tailwind writes for browsers without `color-mix()` or `@property`, which no supported browser needs. Minified, the complete stylesheet is about 198 KB, down from 416 KB, `/native` about 295 KB from 582 KB, and `/components` about 159 KB from 324 KB. With gzip they are about 17 KB, down from 20 KB, 22 KB from 26 KB, and 13 KB from 15 KB.
32
+ - **Under `.pixel`, cards, panels, and alerts take no cut.** A surface keeps the inset ring and square corners but no longer clips, because the clip cut everything inside it: a tooltip in a card was never painted, and a child's shadow and focus outline were trimmed. Buttons, fields, and code blocks keep their stepped corners. See [Aesthetics → Pixel](../usage/aesthetics.md#pixel).
33
+ - **A neutral component on a filled parent prints in the parent's text color.** A neutral badge in a `.btn.primary` read at 1.11:1, and a `.ghost` Cancel button in a `.card.solid.primary` printed the page's text on the card's fill. A neutral component that is not `.solid`, a text field included, now takes its label and its line from the filled component around it. A component with an intent keeps its own color. See [Buttons → Choose a fill and an edge](../usage/buttons.md#choose-a-fill-and-an-edge).
34
+ - **A filled component's focus ring carries a line of the page color inside it.** On a component filled past half, such as `.solid.primary`, the outline sat over a fill of its own color and part of it vanished. A 2px line of `--color-background` now runs inside the ring, as it already did under `.pixel`; a focused `.input-group` takes the same line.
35
+ - **A container's tracking no longer reaches its buttons and badges.** `.btn` and `.badge` fall back to `normal` letter spacing, and text fields set `normal`, so body copy's tracking under `/native` no longer widens every control. To track a region's buttons, set `--ui-label-tracking` on the container.
36
+ - **`/native` sets body text on `body`, not on `p` and `li`.** Paragraphs and list items inherit their type from what they sit in, so a container that sets its own size, weight, or tracking applies it to the Markdown inside it; a paragraph in a bold 20px container is no longer 14px regular.
37
+ - **Every press happens under reduced motion.** The default look, glass, cyber, sketch, and `.cyber-solo` dropped their press under `prefers-reduced-motion: reduce`, so a click gave no feedback. The press now lands at once, as the slab presses of neobrutalism and chunky tile already did.
38
+ - **Glass and neobrutalism regions set the theme's font.** They set `font-family` from `--font-default` on the region, so a glass or neobrutalist region nested in pixel, cyber, sketch, or chunky tile no longer takes that aesthetic's face. A font set only with `font-family` on `body` or a container stops at these regions; set `--font-default` too, as [Theming → Fonts](../usage/theming.md#fonts) describes.
39
+ - **`--focus-ring` is no longer declared at `:root`.** It resolved `--color-primary` there and inherited, so a region with its own `--color-primary` ringed its buttons in the page's color. Each focused element now falls back to its own primary at 64%, and a `--focus-ring` you set on an ancestor still inherits. `var(--focus-ring)` in your own CSS with nothing set now resolves to nothing; write the fallback, `var(--focus-ring, color-mix(in srgb, var(--color-primary) 64%, transparent))`.
40
+ - **Eight neutral palette values changed.** `/palette`'s neutral soft `page` and `subtle` cells are now read from the components that draw them, `.alert` and `.kbd`, so they match what those components render; `--palette-neutral-soft-page-bg` is lighter in the light theme and darker in the dark one. Every other palette value is unchanged.
41
+ - **The package declares its types.** Every stylesheet export leads with a `types` condition naming an empty declaration, and the top-level `types` field names `dist/index.d.ts`, so `import "@codenhub/styles";` typechecks under TypeScript 6's `noUncheckedSideEffectImports`, where it failed with TS2882. `tw/` holds its own `index.d.ts`.
42
+ - **`prefers-contrast: more` is honored.** Nothing read it before. With it, text fields rest at their full border, neutral borders take a heavier gray, an intent's border takes its strong tone, a progress track is outlined, and glass turns opaque with a gray border, so each of those lines measures at least 3:1 in both themes. Readers who have not asked for more contrast see no change. [Accessibility → Increased contrast](../accessibility.md#increased-contrast) lists each one.
43
+
44
+ ## Removed
45
+
46
+ - **`--surface-padding`.** The variable `.card` and `.panel` read their padding from, and that `.p-xs`, `.p-sm`, `.p-lg`, and `.flush` wrote, is gone; the padding modifiers now set the padding through their own flags. It was documented as internal wiring, but CSS that set `--surface-padding` on a card to change its padding no longer does anything; use a padding modifier, or set `padding` in your own unlayered CSS.
47
+
48
+ ## Fixed
49
+
50
+ - **`@apply text-control` and `@apply surface` behave like the classes.** An applied field missed the rules that named `.text-control` from outside it: it drew the faint surface line instead of the 3:1 control line, took the intent of any container around it, ignored the `.soft`, `.solid`, and `.edgeless` limits and `aria-invalid`, and kept the plain focus ring in forced colors. An applied surface missed the neutral reset, so inside a `.card.success` it drew the card's green line, and a `<dialog>` with your own `@apply surface` class rendered while closed and pinned to the top-left once open. All of that now travels with the utility. See [Customizing → Composition helpers](../usage/customizing.md#composition-helpers).
51
+ - **`@apply progress` draws its border.** An applied progress bar read an undefined border color and drew no track edge.
52
+ - **Liquid glass layers reach your own surfaces.** A `@apply surface` element in a `.glass-liquid` region took the backdrop but no lens or rim.
53
+ - **A neutral edged ghost button or badge under glass shows its edge.** Glass's white hairline needs a plate to be seen on, and on a light page it measured 1.01:1; an unfilled neutral button or badge draws glass's control line instead.
54
+ - **An input group is the height of the controls beside it.** The control inside kept its own height within the group's border, so a group was 42px beside 40px fields and buttons.
55
+ - **An input group draws one focus ring.** A focused field drew its own Highlight ring inside the group's in forced colors, and a focused button drew its ring inside the group's; the button keeps its ring and the group drops its own.
56
+ - **A disabled control in an input group dims once.** The group and the control both dimmed, so the value showed at about a third of its opacity.
57
+ - **A `.success` or invalid input group prints its typed text in that intent.** The control inside reset to neutral text while the group drew its line in the intent.
58
+ - **An invalid checkbox is drawn as a destructive one.** A checked invalid checkbox in the dark theme drew the neutral near-black mark on red, at 3.28:1.
59
+ - **Every intent hint is readable.** `.hint.destructive` printed a fill color at 3.28:1 on the dark page, and the other intents were not wired; each built-in intent now prints its strong tone, 4.5:1 or better in both themes.
60
+ - **A themed region re-resolves its text color.** `<aside class="dark">` on a light page kept the near-black text it inherited and printed it on its dark ground; the theme selectors now set `color` too.
61
+ - **A progress bar shows its value in forced colors.** The value was repainted as Canvas on a Canvas track, so a half-full bar read as empty.
62
+ - **Glass is opaque in forced colors.** `.glass`, `.glass-liquid`, and `.glass-solo` stayed translucent and showed the page through the pane; they now take the opaque ground of the reduced-transparency fallback.
63
+ - **A container's fill reaches a card, panel, or alert.** A `.card` inside a `.soft` container drew the grey slab of a `.card.soft`, and a container's `.ghost` or `.solid` landed a panel or alert on its quiet plate; they now draw the fill they resolve.
64
+ - **A box with no intent draws in the aesthetic's ink.** A bare `box` under `.neobrutalism` drew the theme's grey line and slab beside a `.neutral` sibling's black ink.
65
+ - **A `.raised` button keeps its shadow while pressed.** With no aesthetic it dropped from `0 1px 3px` to `0 0 3px` while held down.
66
+ - **Code in a native `pre` draws no chip.** `pre code` cleared only the chip's fill and padding, so `.cyber` drew a glowing box inside the block, neobrutalism's border indented the first line, and `.pixel` drew an inset ring.
67
+ - **A solo element keeps its own transition and transform.** A solo class replaced an element's `transition` list, so a toast stopped animating its fade and height; only actions take the press's transition now, and the press moves through `translate` or `scale`, leaving `transform` alone.
68
+ - **Nested aesthetics take the nearest region's look.** A liquid region inside another aesthetic nested in a liquid one lost its layers, and a sketch region in the same position lost its rotation and dashed accents.
69
+ - **`.alert.neobrutalism` sits on the slab.** An alert carrying the class itself rested flat, unlike one inside a `.neobrutalism` region and unlike `.card.neobrutalism`.
70
+ - **Native elements under `.sketch` take the dashed accents.** Under `/native`, a plain `<hr>`, `<table>`, and checkbox draw the dashes `.divider`, `.data-table`, and `.checkbox` do.
@@ -0,0 +1,40 @@
1
+ ---
2
+ title: 0.9.0
3
+ date: 2026-11-12
4
+ description: The build command is chs and builds without Tailwind, twelve component variables a parent can set, and fixes to printing, bare native controls, disabled solo actions, forced colors, sketch knobs, and the licence notice in compiled CSS.
5
+ ---
6
+
7
+ # 0.9.0
8
+
9
+ The build command is renamed `chs` and no longer runs Tailwind: it trims a stylesheet the package ships, so the package is the whole install. Twelve component variables, such as `--field-gap` and `--table-cell-padding`, are public and take effect when set on any ancestor. The release also fixes printing, bare native controls, disabled solo actions, forced colors, and sketch knobs, and adds the licence notice of the checkbox marks to every compiled file that carries them.
10
+
11
+ ## Added
12
+
13
+ - **Twelve component variables.** `--tooltip-gap`, `--field-gap`, `--input-group-padding`, `--switch-height`, `--switch-width`, `--divider-color`, `--divider-width`, `--skeleton-base`, `--skeleton-sheen`, `--quote-width`, `--table-cell-padding`, and `--table-hover` join `--input-group-gap` and `--tooltip-linger` as public variables. Each one works on the component or on any element around it, so `.settings { --field-gap: 0.5rem; }` spaces every field in the region. `--table-hover` also works on a `tbody` or a row, for that part of the table only. See [Customizing → Component variables](../usage/customizing.md#component-variables).
14
+
15
+ ## Changed
16
+
17
+ - **Breaking: the build command is `chs`.** `codenhub-styles build` is gone, with no alias; run `chs build` from a `package.json` script, or `npx @codenhub/styles build` from a shell. Do not type `npx chs`: an unrelated package on npm has that name, and npx would download and run it. See [Without a bundler → Build only the classes you use](../integrating/without-a-bundler.md#build-only-the-classes-you-use).
18
+ - **Breaking: the command builds without Tailwind.** It reads the classes your files name and keeps their rules from a complete stylesheet the package ships in `dist/purge/`, so it needs Node.js 24 or newer and nothing else installed, and its output no longer changes with your Tailwind version. Three things it did through Tailwind are gone. It emits no Tailwind utilities, so `flex` or `mt-4` in your templates adds nothing. Variants are a fixed set of ten: `sm:`, `md:`, `lg:`, `xl:`, `2xl:`, `hover:`, `focus:`, `focus-visible:`, `active:`, and `dark:`. Variants do not stack, so `md:hover:primary` is not found. A project that needs any of those runs Tailwind and imports `/tw`, which still gives all three. See [Without a bundler → What it does not do](../integrating/without-a-bundler.md#what-it-does-not-do).
19
+ - **Breaking: `@codenhub/styles` no longer has a peer dependency on `@tailwindcss/cli`.** Only the command used it. Remove it from your dependencies if nothing else uses it. `tailwindcss` stays an optional peer for `/tw`.
20
+ - **`--input-group-gap` and `--tooltip-linger` work from a parent.** They took effect only when set on the `.input-group` or the `.tooltip` itself. A value set on an ancestor now reaches them.
21
+ - **Sketch knobs reach every position.** `--sketch-radius`, `--sketch-radius-rounded`, `--sketch-radius-surface`, and `--sketch-radius-surface-rounded` set on a `.sketch` region, or on any element inside it, now shape every control and surface that rotates through the four outlines, such as `.btn`, `.ipt`, and `.card`. They skipped one element in four. A component that does not rotate, such as `.skeleton` or a bare control under `/native`, still takes only a knob set on the region. See [Aesthetics → Sketch](../usage/aesthetics.md#sketch).
22
+ - **Small buttons and fields read the theme's line height.** `.btn.sm` and the small text fields took their leading from a variable private to Tailwind, which can change between Tailwind releases. They now read `--text-sm--line-height`. A `leading-*` utility on them still wins.
23
+ - **Internal variables renamed.** The custom properties that switches, tooltips, quotes, tables, and elevation derive internally now start with `--_`, as the other internal ones do, such as `--_tooltip-top` and `--_table-rule`. They were documented as internal. CSS that set one of the old names, such as `--table-rule`, no longer does anything. Use a public variable or a utility instead.
24
+ - **The homepage is the package's page on codenhub.dev.**
25
+
26
+ ## Fixed
27
+
28
+ - **A tap leaves no hover tint.** On a touch screen a tapped button, interactive card, table row, checkbox, switch, select, or input group kept its hover color until something else was tapped. Hover now applies only where the pointer can hover, as Tailwind's `hover:` variant does.
29
+ - **A bare `<progress>` takes the color it sits in.** Under `/native`, in a filled container, it drew the page's ink over the container's color.
30
+ - **A bare quiet checkbox or radio keeps its checked plate.** Under `/native`, a checked `.ghost` or `.soft` checkbox or radio showed its resting plate, and a mixed one also kept the neutral 20% cap.
31
+ - **A filled quotation prints with its plate.** A `.quote.solid` printed white text on white paper.
32
+ - **A solid solo element prints with its plate.** The `-solo` classes left their fill off paper, as the quotation did.
33
+ - **A solo action disabled by class or data attribute does not press.** The neobrutalism, chunky tile, and cyber solos guarded their press with `:disabled` and `aria-disabled` only. A link or `role="button"` marked `.disabled` or `data-disabled` still sank when clicked.
34
+ - **`@apply progress` and `@apply select` keep their forced colors.** The applied bar's value was repainted as Canvas, and the applied drop-down drew no arrow.
35
+ - **Compiled CSS carries the licence of the checkbox marks.** The marks come from Lucide (ISC, itself from Feather, MIT). Each compiled file that inlines them now carries their copyright and permission notices in a `/*!` comment after Tailwind's banner, and `chs build` keeps it in its output.
36
+
37
+ ## Documentation
38
+
39
+ - [Customizing → Generated palette](../usage/customizing.md#generated-palette) says the palette's `-edge` values do not follow `prefers-contrast: more`.
40
+ - [Tailwind CSS v4](../integrating/tailwind.md) warns against clearing the `--text-*`, `--font-*`, and `--spacing` themes, which the package reads.
@@ -6,6 +6,8 @@ group: Changelog
6
6
 
7
7
  # Changelog
8
8
 
9
+ - [0.9.0](0.9.0.md)
10
+ - [0.8.0](0.8.0.md)
9
11
  - [0.7.0](0.7.0.md)
10
12
  - [0.6.0](0.6.0.md)
11
13
  - [0.5.0](0.5.0.md)
@@ -2,7 +2,7 @@
2
2
  title: Accesibilidad
3
3
  description: Lo que hace el CSS con el foco, los estados, el movimiento, el contraste, los colores forzados y el texto de derecha a izquierda, y lo que tu aplicación todavía les debe a sus usuarios.
4
4
  order: 5
5
- source: dc1a745e9e6853a31ca4a8cf7a334031bab1ec7d
5
+ source: 88ce6c4707ee04ac76cdb5e6b31dcca399a5327e
6
6
  ---
7
7
 
8
8
  # Accesibilidad
@@ -15,14 +15,14 @@ Esta página enumera las dos mitades: lo que aporta el CSS y lo que tu aplicaci
15
15
 
16
16
  ### Foco y estado
17
17
 
18
- | Característica | Comportamiento |
19
- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
20
- | `:focus-visible` | Un contorno de foco en cada elemento, dibujado con `--focus-ring`, `--focus-ring-width` y `--focus-ring-offset`. |
21
- | Foco en controles de formulario | `.ipt`, `.textarea` y `.select` dibujan el contorno de foco y cambian su borde al color de la intención. El texto escrito en un campo con una clase de intención usa el tono legible de esa intención, `--intent-strong`. |
22
- | Controles inválidos | `aria-invalid="true"` en un control de formulario vuelve destructivos su borde, su color de foco y el texto escrito, este último en el tono legible destructivo. |
23
- | Controles deshabilitados | `disabled`, `aria-disabled="true"`, `data-disabled` y `.disabled` muestran el cursor y la opacidad de deshabilitado, y un control deshabilitado no reacciona al hover, tampoco dentro de un `.input-group`. |
24
- | Estado abierto | `data-state="open"` en un `.tooltip` muestra su burbuja sin hover ni foco, y `data-state="closed"` la oculta aunque tenga hover o foco. Ningún otro componente lee ninguno de los dos. |
25
- | `<dialog>` nativo | Un `<dialog>` con `.card`, `.panel` o `.surface` permanece oculto hasta que se abre, y se abre centrado. Un margen que pongas en el diálogo, como utilidad o en tu propio CSS, sigue sobrescribiendo el centrado. Los demás diálogos no se tocan. Atrapar el foco, cerrar con Escape y dejar inerte la página de detrás es cosa de tu aplicación. |
18
+ | Característica | Comportamiento |
19
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
20
+ | `:focus-visible` | Un contorno de foco en cada elemento, dibujado con `--focus-ring`, `--focus-ring-width` y `--focus-ring-offset`. En un componente con un relleno de más de la mitad de intensidad, como un botón `.solid.primary`, una línea de 2px del color de la página recorre el interior del anillo, así que el anillo sigue visible sobre un relleno de su mismo color. |
21
+ | Foco en controles de formulario | `.ipt`, `.textarea` y `.select` dibujan el contorno de foco y cambian su borde al color de la intención. El texto escrito en un campo con una clase de intención usa el tono legible de esa intención, `--intent-strong`. |
22
+ | Controles inválidos | `aria-invalid="true"` en un control de formulario vuelve destructivos su borde, su color de foco y el texto escrito, este último en el tono legible destructivo. Un checkbox, un radio o un switch se dibuja exactamente igual que su versión `.destructive`, marca de activado incluida. |
23
+ | Controles deshabilitados | `disabled`, `aria-disabled="true"`, `data-disabled` y `.disabled` muestran el cursor y la opacidad de deshabilitado, y un control deshabilitado no reacciona al hover, tampoco dentro de un `.input-group`. |
24
+ | Estado abierto | `data-state="open"` en un `.tooltip` muestra su burbuja sin hover ni foco, y `data-state="closed"` la oculta aunque tenga hover o foco. Ningún otro componente lee ninguno de los dos. |
25
+ | `<dialog>` nativo | Un `<dialog>` con `.card`, `.panel`, `.surface` o una clase propia que hace `@apply surface` permanece oculto hasta que se abre, y se abre centrado. Un margen que pongas en el diálogo, como utilidad o en tu propio CSS, sigue sobrescribiendo el centrado, salvo que una utilidad de margen no lo hace cuando tu clase aplica `surface` en CSS plano; consulta [Personalización → Helpers de composición](./usage/customizing.md#helpers-de-composición). Con la [hoja de estilos sin clases](./setup.md#html-sin-clases), un `<dialog>` simple es una `.card.floating` y se comporta igual; con los demás puntos de entrada, un diálogo sin ninguna de estas clases no se toca. Atrapar el foco, cerrar con Escape y dejar inerte la página de detrás es cosa de tu aplicación. |
26
26
 
27
27
  ### Contenido visualmente oculto
28
28
 
@@ -34,7 +34,7 @@ WCAG 1.4.11 pide que el límite de un control que necesitas ver para usarlo teng
34
34
 
35
35
  | Característica | Comportamiento |
36
36
  | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
37
- | Controles de texto en reposo | El borde de un control de texto reposa más claro que el borde completo de su intención, por debajo de 3:1 a propósito, para que el hover y el foco tengan un tono más intenso al que cambiar. |
37
+ | Controles de texto en reposo | El borde de un control de texto reposa más claro que el borde completo de su intención, por debajo de 3:1 a propósito, para que el hover y el foco tengan un tono más intenso al que cambiar. [Contraste aumentado](#contraste-aumentado) lo dibuja completo. |
38
38
  | Toggles | `.checkbox`, `.radio` y `.switch` dibujan su borde completo, porque el borde es lo único que muestra una casilla sin marcar. Un `.switch` con su propio `.edgeless` es la excepción, más abajo. |
39
39
  | `.edgeless` desde un contenedor | Lo ignoran todos los controles de texto y toggles: un contenedor no puede quitar el borde de un campo o toggle que contiene. |
40
40
  | `.edgeless` en el control | `.ipt`, `.textarea`, `.select` y `.switch` pierden su borde y dejan de cumplir 1.4.11 en reposo. `.switch.ghost` conserva su borde incluso entonces, porque sin relleno y sin borde nada mostraría el carril. |
@@ -59,11 +59,11 @@ Sin clase de intención, el contorno es el gris discreto de los bordes, `--color
59
59
 
60
60
  ### Movimiento y transparencia
61
61
 
62
- | Característica | Comportamiento |
63
- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
64
- | Movimiento reducido, componentes | Con `prefers-reduced-motion: reduce`, cada componente detiene sus propias transiciones y animaciones: el brillo del skeleton y del progreso, la barra indeterminada, el tooltip, las marcas de los toggles y la pulsación. |
65
- | Movimiento reducido, toda la página | El reset también acorta todas las demás animaciones y transiciones de la página. |
66
- | Transparencia reducida | Con `prefers-reduced-transparency: reduce`, `.glass` y `.glass-liquid` pierden su desenfoque y su lente y se vuelven opacos. |
62
+ | Característica | Comportamiento |
63
+ | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
64
+ | Movimiento reducido, componentes | Con `prefers-reduced-motion: reduce`, cada componente detiene sus propias transiciones y animaciones: el brillo del skeleton y del progreso, la barra indeterminada, el tooltip, las marcas de los toggles y el movimiento de la pulsación. La pulsación en sí sigue ocurriendo, al instante, con el aspecto por defecto y con cada estética y clase solo, porque es la señal de que un clic se registró. |
65
+ | Movimiento reducido, toda la página | El reset también acorta todas las demás animaciones y transiciones de la página. |
66
+ | Transparencia reducida | Con `prefers-reduced-transparency: reduce`, y con colores forzados, `.glass`, `.glass-liquid` y `.glass-solo` pierden su desenfoque y su lente y se vuelven opacos. |
67
67
 
68
68
  La regla de movimiento reducido de cada componente viene con el componente, así que cada punto de entrada que lo incluye respeta el movimiento reducido sin el reset, incluidos `@codenhub/styles/components`, `@codenhub/styles/tw/components` y cada punto de entrada de componente `/tw/*`. Los puntos de entrada completo y native añaden la regla del reset para toda la página.
69
69
 
@@ -85,30 +85,49 @@ La regla del reset es `!important` dentro de la capa `base`, y un `!important` c
85
85
 
86
86
  Respetar el movimiento reducido no es todo lo que se pide. El movimiento que sigue en marcha junto al contenido, como un brillo que queda en una tarjeta después de que ha cargado, necesita una forma de detenerlo para todos los usuarios; consulta [Feedback → Animación que no se detiene](./usage/feedback.md#animación-que-no-se-detiene).
87
87
 
88
+ ### Contraste aumentado
89
+
90
+ Con `prefers-contrast: more`, los bordes que el paquete dibuja por debajo de 3:1 a propósito se dibujan a 3:1 o más frente a lo que tienen al lado, en ambos temas. El texto, los rellenos sólidos y los anillos de foco ya cumplen sus proporciones y no cambian. `prefers-contrast: less` no se lee.
91
+
92
+ | Característica | Comportamiento |
93
+ | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
94
+ | Controles de texto | `.ipt`, `.textarea`, `.select` e `.input-group` reposan con su borde completo, así que el hover y el foco ya no cambian su tono. El anillo de foco es el mismo. |
95
+ | Bordes neutros | `--color-border` toma un gris más intenso, `neutral-600` en claro y `neutral-400` en oscuro, así que el borde de una tarjeta, un divisor, las líneas de una tabla y el borde de un botón o badge neutro cumplen 3:1. Si defines `--color-border` tú mismo, tu color se conserva; mídelo. |
96
+ | Bordes de intención | El borde de una intención toma su tono fuerte, `--color-<intent>-strong`, así que `.edged` en un `.alert`, `.panel`, `.badge`, `.kbd`, `.code` o `.pre` `.soft` cumple 3:1 tanto frente a su relleno como frente a la página, en todas las intenciones. |
97
+ | Carril de progreso | El carril dibuja un contorno en su color de borde, que cumple 3:1 con o sin clase de intención. `.edgeless` en la barra o en un contenedor lo sigue quitando. |
98
+ | Glass | `.glass`, `.glass-liquid` y `.glass-solo` pierden su desenfoque y su lente y se vuelven opacos, como con la transparencia reducida, y su línea blanca pasa a ser un borde gris. |
99
+ | Chunky tile | `.chunky-tile` dibuja las piezas y las superficies con el gris más intenso que usan sus controles. |
100
+
101
+ Lo que quitas sigue quitado: `.edgeless` en un control sigue eliminando su borde, y un `.panel` sigue sin tenerlo salvo que añadas `.edged`.
102
+
88
103
  ### Color y contraste
89
104
 
90
105
  Las mediciones de abajo corresponden a los colores incluidos. En cuanto cambies un token de color, vuelve a medir tus propios pares; [Temas → Cambiar el color de marca](./usage/theming.md#cambiar-el-color-de-marca) muestra qué pares comprobar.
91
106
 
92
- | Característica | Comportamiento |
93
- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
94
- | Etiquetas rellenas | La etiqueta `.solid` de cada intención cumple 4.5:1 (WCAG 1.4.3) como texto normal, en ambos temas. La más baja es success, con 5.14:1. |
95
- | Texto de warning | `--color-warning-contrast` es casi negro, no el color de la página, porque un ámbar lo bastante oscuro para llevar texto blanco ya no parece ámbar. |
96
- | Rellenos parciales | El color de texto de contraste solo aparece en rellenos por encima de la mitad de intensidad, así que el relleno limitado de un control de texto conserva el color de texto propio de la intención. |
97
- | Color de intención en oscuro | En modo oscuro, una etiqueta `.soft` o `.ghost` usa el tono `-300` de su intención, así que conserva su matiz en lugar de volverse blanca. |
98
- | Marcas de los toggles | Una marca activada mide al menos 3:1 frente a cada relleno que su presentación pueda darle, en ambos temas. |
99
- | Rellenos soft con borde | `.edged` en un `.alert`, `.panel`, `.badge`, `.kbd`, `.code` o `.pre` `.soft` dibuja un borde que mide menos de 3:1 frente al relleno del 12% en algunas intenciones, cuáles depende del tema. Mide el par antes de confiar en ese borde como límite de un control. |
107
+ | Característica | Comportamiento |
108
+ | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
109
+ | Etiquetas rellenas | La etiqueta `.solid` de cada intención cumple 4.5:1 (WCAG 1.4.3) como texto normal, en ambos temas. La más baja es success, con 5.14:1. |
110
+ | Texto de warning | `--color-warning-contrast` es casi negro, no el color de la página, porque un ámbar lo bastante oscuro para llevar texto blanco ya no parece ámbar. |
111
+ | Rellenos parciales | El color de texto de contraste solo aparece en rellenos por encima de la mitad de intensidad, así que el relleno limitado de un control de texto conserva el color de texto propio de la intención. |
112
+ | Color de intención en oscuro | En modo oscuro, una etiqueta `.soft` o `.ghost` usa el tono `-300` de su intención, así que conserva su matiz en lugar de volverse blanca. |
113
+ | Texto sobre un padre con relleno | Un componente neutro que no es `.solid`, como un badge en un `.btn.primary` o un botón ghost en una `.card.solid.primary`, imprime en el color de texto de su padre en lugar del de la página, así que conserva el contraste del padre. |
114
+ | Impresión | Una página se imprime con el tema claro, y los componentes con relleno imprimen su fondo (`print-color-adjust: exact`), así que el texto de contraste nunca cae sobre papel en blanco. Una utilidad `dark:` se sigue aplicando al imprimir; consulta [Temas → Impresión](./usage/theming.md#impresión). |
115
+ | Marcas de los toggles | Una marca activada mide al menos 3:1 frente a cada relleno que su presentación pueda darle, en ambos temas. |
116
+ | Rellenos soft con borde | `.edged` en un `.alert`, `.panel`, `.badge`, `.kbd`, `.code` o `.pre` `.soft` dibuja un borde que mide menos de 3:1 frente al relleno del 12% en algunas intenciones, cuáles depende del tema. Mide el par antes de confiar en ese borde como límite de un control. [Contraste aumentado](#contraste-aumentado) lleva todos ellos a 3:1. |
100
117
 
101
118
  ### Colores forzados y dirección
102
119
 
103
- | Característica | Comportamiento |
104
- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
105
- | Colores forzados | Con `forced-colors: active`, los bordes, los estados activados y el chevron de un `.select` siguen visibles, dibujados con colores del sistema, bajo cualquier estética. Una estética que dibuja su borde como una sombra interior, como `.pixel`, dibuja en su lugar un borde real. |
106
- | Dirección del texto | Con `dir="rtl"`, la barra de las citas, el icono de la alerta, el relleno del progreso, el divisor vertical, la perilla del switch, la alineación de las tablas y el chevron de un select cambian de lado. No hace falta ninguna clase. |
120
+ | Característica | Comportamiento |
121
+ | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
122
+ | Colores forzados | Con `forced-colors: active`, los bordes, los estados activados, el chevron de un `.select` y el valor de una barra de progreso siguen visibles, dibujados con colores del sistema, bajo cualquier estética. Una estética que dibuja su borde como una sombra interior, como `.pixel`, dibuja en su lugar un borde real. El cristal se vuelve opaco, porque los colores forzados conservan la transparencia de un fondo. |
123
+ | Dirección del texto | Con `dir="rtl"`, la barra de las citas, el icono de la alerta, el relleno del progreso, el divisor vertical, la perilla del switch, la alineación de las tablas y el chevron de un select cambian de lado. No hace falta ninguna clase. |
107
124
 
108
- Con colores forzados, `.text-control`, `.ipt`, `.textarea`, `.select` y los toggles muestran un contorno de foco `Highlight` de 2px. El punto de entrada native da el mismo contorno a los inputs de texto, selects, textareas, checkboxes y radios sin clase.
125
+ Con colores forzados, `.text-control`, `.ipt`, `.textarea`, `.select`, los toggles y tu propia clase que hace `@apply text-control` muestran un contorno de foco `Highlight` de 2px. Dentro de un `.input-group`, el grupo dibuja el anillo del campo y el control interior no dibuja ninguno, así que un campo con foco muestra un solo anillo. El punto de entrada native da el mismo contorno a los inputs de texto, selects, textareas, checkboxes y radios sin clase.
109
126
 
110
127
  Los checkboxes, radios y switches usan los colores del sistema `Canvas`, `CanvasText`, `Highlight` y `HighlightText`, así que activado y desactivado siguen siendo distinguibles: un toggle activado se rellena con `Highlight` y su marca es `HighlightText`, tanto en las clases como en el punto de entrada native. La forma, el tamaño y el espaciado no cambian.
111
128
 
129
+ Una barra `.progress` hace lo mismo: su parte rellena es `CanvasText` sobre un carril `Canvas` con un contorno `CanvasText`, sea cual sea su intención o su presentación, así que una barra a medio llenar no se confunde con una vacía. El brillo de `.active` no se dibuja.
130
+
112
131
  ## Lo que hace falta fuera del CSS
113
132
 
114
133
  Usa el elemento HTML que corresponde a lo que hace el componente, y añade el comportamiento que el CSS no puede dar.
package/docs/es/index.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Introducción
3
3
  description: Para qué sirve @codenhub/styles, qué cuesta y en qué orden leer esta documentación.
4
- source: 238cac2f0ca6132818c99d938219a6c537bc837a
4
+ source: 4226ac998f12fb17bed33172417919586cb6c930
5
5
  ---
6
6
 
7
7
  # @codenhub/styles
@@ -61,7 +61,7 @@ El paquete ofrece las mismas clases de dos formas:
61
61
  Conoce estos costes antes de adoptarlo:
62
62
 
63
63
  - **Los nombres de clase son cortos y no llevan prefijo.** `.primary`, `.success`, `.dark`, `.label`, `.field`, `.section`, `.stack`, `.flat` y `.ghost` son nombres globales. Otra hoja de estilos en la misma página que los use choca con esta. El paquete está en [capas de cascada](./setup.md#capas-de-cascada), así que tu propio CSS sin capa gana en caso de choque, pero las reglas de una librería de terceros para el mismo nombre se siguen aplicando junto a las del paquete.
64
- - **Las hojas de estilos completas son grandes antes de comprimir.** En el momento de escribir esto, minificada, la hoja de estilos completa ocupa unos 410 KB, `/native` unos 575 KB y `/components` unos 320 KB. Servidas con gzip ocupan unos 19 KB, 25 KB y 15 KB. Los archivos específicos son mucho más pequeños: `/theme` ocupa unos 10 KB (2 KB con gzip) y una estética, de 4 a 21 KB (de 1 a 2 KB con gzip). La mayor parte del tamaño es composición que cada componente repite, y por eso la compresión elimina tanto. Importa el punto de entrada más reducido que cubra una página; consulta [Configuración inicial → Todos los puntos de entrada](./setup.md#todos-los-puntos-de-entrada).
64
+ - **Las hojas de estilos completas son grandes antes de comprimir.** En el momento de escribir esto, minificada, la hoja de estilos completa ocupa unos 198 KB, `/native` unos 295 KB y `/components` unos 159 KB. Servidas con gzip ocupan unos 17 KB, 22 KB y 13 KB. Los archivos específicos son mucho más pequeños: `/theme` ocupa unos 12 KB (3 KB con gzip) y una estética, de 4 a 14 KB (de 1 a 2 KB con gzip). La mayor parte del tamaño es composición que cada componente repite, y por eso la compresión elimina tanto. Un archivo compilado incluye todas las clases, las use una página o no. Para incluir solo las clases que usan tus páginas, compila el paquete en tu propio build: con [Tailwind CSS v4](./integrating/tailwind.md) cuando el proyecto lo usa, o con el [comando `build`](./integrating/without-a-bundler.md#generar-solo-las-clases-que-usas) del paquete en cualquier otro proyecto. Así, una página con un botón recibe de 26 a 28 KB minificados, y unos 6 KB con gzip. Si no, importa el punto de entrada más reducido que cubra una página; consulta [Configuración inicial → Todos los puntos de entrada](./setup.md#todos-los-puntos-de-entrada).
65
65
  - **`--color-foreground` es un fondo, no un color de texto.** Es el tono un paso por encima de la página sobre el que se apoya una tarjeta o un panel discreto. El color de texto es `--color-text`.
66
66
  - **Cuatro colores de hover son valores fijos.** `--color-success-hover`, `--color-warning-hover`, `--color-destructive-hover` y `--color-info-hover` están precalculados, porque mezclarlos en vivo hacía fallar WebKit. Si sobrescribes solo `--color-success`, su hover conserva el tono anterior, así que reemplaza la familia completa; consulta [Temas → Tokens de color](./usage/theming.md#tokens-de-color).
67
67
  - **Solo navegadores modernos.** Chrome 123, Safari 17.5 o Firefox 128 y posteriores. No hay una capa de respaldo para navegadores antiguos.
@@ -79,7 +79,7 @@ El paquete está por debajo de 1.0 y sigue la [regla del versionado semántico p
79
79
  - Una versión menor, como de 0.7.0 a 0.8.0, puede romper la compatibilidad. Puede renombrar o eliminar una clase o un token, o cambiar un valor por defecto. Cada cambio incompatible aparece en **Changed** o **Removed** en la página del [changelog](../changelog/index.md) de esa versión, con lo que debes usar en su lugar.
80
80
  - Una versión de parche, como de 0.7.0 a 0.7.1, nunca rompe la compatibilidad.
81
81
 
82
- El rango por defecto de npm para una nueva dependencia, `^0.7.0`, ya acepta solo parches, porque por debajo de 1.0 un rango con caret no pasa a la siguiente versión menor. Lee el changelog antes de subirlo. Cuando enlaces un archivo desde un CDN, pon la versión exacta en la URL; consulta [Sin bundler](./integrating/without-a-bundler.md).
82
+ El rango por defecto de npm para una nueva dependencia, `^0.9.0`, ya acepta solo parches, porque por debajo de 1.0 un rango con caret no pasa a la siguiente versión menor. Lee el changelog antes de subirlo. Cuando enlaces un archivo desde un CDN, pon la versión exacta en la URL; consulta [Sin bundler](./integrating/without-a-bundler.md).
83
83
 
84
84
  Los cambios incompatibles no se suavizan con alias porque el modelo todavía se está asentando, y mantener cada nombre antiguo junto a su reemplazo haría crecer la superficie en cada versión. Un cambio de nombre o una eliminación suele costar un buscar y reemplazar al actualizar; un valor por defecto que cambia puede requerir que reajustes tu propio CSS.
85
85
 
@@ -99,6 +99,7 @@ La primera vez, léelas en orden. Cada página añade algo a la pantalla de ajus
99
99
  - [Estéticas](./usage/aesthetics.md): cambia el estilo de toda la pantalla con una sola clase.
100
100
  - [Clases solo](./usage/solo.md): pinta una estética sobre un componente al que este paquete no da estilo.
101
101
  - [Composición](./usage/composing.md), [Personalización](./usage/customizing.md) y [Contenido y layout](./usage/content-and-layout.md): páginas de consulta con cada regla de eje, token, valor por defecto y clase helper.
102
+ - [Preajustes](./usage/presets.md): define un aspecto una sola vez, para una región, un tema o tu propia clase de componente, en lugar de repetirlo en cada elemento.
102
103
  5. [Accesibilidad](./accessibility.md): lo que el CSS resuelve por ti y lo que tu aplicación todavía debe hacer.
103
104
 
104
105
  El [changelog](../changelog/index.md) enumera cada versión y lo que cambió en ella.