@codenhub/styles 0.6.0 → 0.8.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 (151) hide show
  1. package/NOTICE +18 -16
  2. package/README.es.md +62 -0
  3. package/README.md +28 -22
  4. package/README.pt-BR.md +62 -0
  5. package/dist/aesthetics/chunky-tile.css +1 -1
  6. package/dist/aesthetics/cyber.css +1 -1
  7. package/dist/aesthetics/glass.css +1 -1
  8. package/dist/aesthetics/index.css +2 -2
  9. package/dist/aesthetics/neobrutalism.css +1 -1
  10. package/dist/aesthetics/pixel.css +1 -1
  11. package/dist/aesthetics/sketch.css +1 -1
  12. package/dist/cli.js +189 -0
  13. package/dist/components.css +2 -2
  14. package/dist/index.css +2 -2
  15. package/dist/index.d.ts +1 -0
  16. package/dist/native.css +2 -2
  17. package/dist/palette.css +1 -1
  18. package/dist/theme.css +2 -2
  19. package/docs/accessibility.md +108 -60
  20. package/docs/changelog/0.1.1.md +1 -0
  21. package/docs/changelog/0.2.0.md +1 -0
  22. package/docs/changelog/0.3.0.md +1 -0
  23. package/docs/changelog/0.4.0.md +1 -0
  24. package/docs/changelog/0.5.0.md +8 -3
  25. package/docs/changelog/0.6.0.md +2 -1
  26. package/docs/changelog/0.7.0.md +50 -0
  27. package/docs/changelog/0.8.0.md +70 -0
  28. package/docs/changelog/index.md +2 -0
  29. package/docs/concepts.md +188 -46
  30. package/docs/es/accessibility.md +169 -0
  31. package/docs/es/concepts.md +212 -0
  32. package/docs/es/index.md +105 -0
  33. package/docs/es/integrating/astro.md +35 -0
  34. package/docs/es/integrating/index.md +75 -0
  35. package/docs/es/integrating/nextjs.md +67 -0
  36. package/docs/es/integrating/svelte.md +45 -0
  37. package/docs/es/integrating/tailwind.md +148 -0
  38. package/docs/es/integrating/vue.md +31 -0
  39. package/docs/es/integrating/without-a-bundler.md +238 -0
  40. package/docs/es/setup.md +188 -0
  41. package/docs/es/usage/aesthetics.md +282 -0
  42. package/docs/es/usage/buttons.md +135 -0
  43. package/docs/es/usage/composing.md +168 -0
  44. package/docs/es/usage/content-and-layout.md +219 -0
  45. package/docs/es/usage/customizing.md +304 -0
  46. package/docs/es/usage/feedback.md +157 -0
  47. package/docs/es/usage/forms.md +256 -0
  48. package/docs/es/usage/index.md +33 -0
  49. package/docs/es/usage/presets.md +92 -0
  50. package/docs/es/usage/solo.md +86 -0
  51. package/docs/es/usage/theming.md +309 -0
  52. package/docs/es/usage/tooltips.md +127 -0
  53. package/docs/index.md +86 -26
  54. package/docs/integrating/astro.md +3 -4
  55. package/docs/integrating/index.md +46 -13
  56. package/docs/integrating/nextjs.md +3 -4
  57. package/docs/integrating/svelte.md +5 -4
  58. package/docs/integrating/tailwind.md +89 -6
  59. package/docs/integrating/vue.md +3 -4
  60. package/docs/integrating/without-a-bundler.md +237 -0
  61. package/docs/pt-BR/accessibility.md +169 -0
  62. package/docs/pt-BR/concepts.md +212 -0
  63. package/docs/pt-BR/index.md +105 -0
  64. package/docs/pt-BR/integrating/astro.md +35 -0
  65. package/docs/pt-BR/integrating/index.md +75 -0
  66. package/docs/pt-BR/integrating/nextjs.md +67 -0
  67. package/docs/pt-BR/integrating/svelte.md +45 -0
  68. package/docs/pt-BR/integrating/tailwind.md +148 -0
  69. package/docs/pt-BR/integrating/vue.md +31 -0
  70. package/docs/pt-BR/integrating/without-a-bundler.md +238 -0
  71. package/docs/pt-BR/setup.md +188 -0
  72. package/docs/pt-BR/usage/aesthetics.md +282 -0
  73. package/docs/pt-BR/usage/buttons.md +135 -0
  74. package/docs/pt-BR/usage/composing.md +168 -0
  75. package/docs/pt-BR/usage/content-and-layout.md +219 -0
  76. package/docs/pt-BR/usage/customizing.md +304 -0
  77. package/docs/pt-BR/usage/feedback.md +157 -0
  78. package/docs/pt-BR/usage/forms.md +256 -0
  79. package/docs/pt-BR/usage/index.md +33 -0
  80. package/docs/pt-BR/usage/presets.md +92 -0
  81. package/docs/pt-BR/usage/solo.md +86 -0
  82. package/docs/pt-BR/usage/theming.md +309 -0
  83. package/docs/pt-BR/usage/tooltips.md +127 -0
  84. package/docs/setup.md +142 -91
  85. package/docs/usage/aesthetics.md +89 -73
  86. package/docs/usage/buttons.md +112 -40
  87. package/docs/usage/composing.md +109 -92
  88. package/docs/usage/content-and-layout.md +160 -125
  89. package/docs/usage/customizing.md +117 -41
  90. package/docs/usage/feedback.md +138 -71
  91. package/docs/usage/forms.md +201 -107
  92. package/docs/usage/index.md +22 -14
  93. package/docs/usage/presets.md +91 -0
  94. package/docs/usage/solo.md +85 -0
  95. package/docs/usage/theming.md +273 -118
  96. package/docs/usage/tooltips.md +90 -49
  97. package/llms-full.txt +2820 -1298
  98. package/llms.txt +24 -22
  99. package/package.json +134 -91
  100. package/{dist/tw → tw}/aesthetics/chunky-tile.css +107 -29
  101. package/{dist/tw → tw}/aesthetics/cyber.css +88 -40
  102. package/{dist/tw → tw}/aesthetics/glass.css +257 -61
  103. package/{dist/tw → tw}/aesthetics/neobrutalism.css +113 -20
  104. package/{dist/tw → tw}/aesthetics/pixel.css +93 -8
  105. package/tw/aesthetics/sketch.css +417 -0
  106. package/{dist/tw → tw}/box.css +105 -9
  107. package/tw/components/button.css +11 -0
  108. package/tw/components/button.rules.css +187 -0
  109. package/tw/components/feedback.css +11 -0
  110. package/{dist/tw/components/feedback.css → tw/components/feedback.rules.css} +136 -32
  111. package/tw/components/form.css +11 -0
  112. package/{dist/tw/components/form.css → tw/components/form.rules.css} +577 -125
  113. package/tw/components/index.css +16 -0
  114. package/tw/components/rules.css +41 -0
  115. package/tw/components/surface.css +11 -0
  116. package/tw/components/surface.rules.css +222 -0
  117. package/tw/components/tooltip.css +11 -0
  118. package/{dist/tw/components/tooltip.css → tw/components/tooltip.rules.css} +43 -27
  119. package/{dist/tw → tw}/corner.css +18 -12
  120. package/{dist/tw → tw}/elevation.css +23 -17
  121. package/{dist/tw → tw}/index.css +12 -10
  122. package/tw/index.d.ts +1 -0
  123. package/tw/intent.css +312 -0
  124. package/tw/modifiers.css +127 -0
  125. package/tw/native.css +320 -0
  126. package/tw/presentation.css +139 -0
  127. package/tw/reset.css +10 -0
  128. package/{dist/tw/reset.css → tw/reset.rules.css} +21 -22
  129. package/tw/size.css +34 -0
  130. package/tw/surface.css +9 -0
  131. package/tw/surface.rules.css +212 -0
  132. package/{dist/tw → tw}/theme.css +121 -45
  133. package/tw/typography.css +8 -0
  134. package/{dist/tw/typography.css → tw/typography.rules.css} +0 -3
  135. package/{dist/tw → tw}/utilities/content.css +212 -50
  136. package/tw/utilities/index.css +11 -0
  137. package/tw/utilities/layout.css +208 -0
  138. package/tw/utilities/rules.css +8 -0
  139. package/dist/tw/aesthetics/sketch.css +0 -333
  140. package/dist/tw/components/button.css +0 -139
  141. package/dist/tw/components/index.css +0 -36
  142. package/dist/tw/components/loader.css +0 -116
  143. package/dist/tw/components/surface.css +0 -175
  144. package/dist/tw/intent.css +0 -228
  145. package/dist/tw/native.css +0 -203
  146. package/dist/tw/palette.css +0 -460
  147. package/dist/tw/presentation.css +0 -68
  148. package/dist/tw/surface.css +0 -61
  149. package/dist/tw/utilities/index.css +0 -6
  150. package/dist/tw/utilities/layout.css +0 -130
  151. /package/{dist/tw → tw}/aesthetics/index.css +0 -0
@@ -0,0 +1,50 @@
1
+ ---
2
+ title: 0.7.0
3
+ date: 2026-11-04
4
+ description: Liquid glass buttons, solo classes that compose with presentation, intent, and elevation, the shipped loaders removed in favor of icon spinners, and fixes to layout gaps, dialog margins, tables, switches, field groups, and forced colors.
5
+ ---
6
+
7
+ # 0.7.0
8
+
9
+ A button can be a liquid glass pane, the solo classes compose with presentation, intent, and elevation the way components do, the loaders are gone in favor of a spinner from an icon set, and a round of fixes to nested layout gaps, dialog placement, table rows, right-to-left switches, field groups, and forced colors.
10
+
11
+ ## Added
12
+
13
+ - **Liquid glass buttons.** A `.btn` carrying `.glass-liquid` itself, in a glass scope, takes the blur, lens, and rim of a liquid pane, with a lens sized for a control. The fill is still the presentation's: `.solid` is an opaque plate under the rim, `.ghost` and `.soft` are clear panes. A liquid region alone still leaves its controls solid. See [Aesthetics → Liquid buttons](../usage/aesthetics.md#liquid-buttons).
14
+ - **Solo classes compose with presentation, intent, and elevation.** Fill and edge come from the element or a container, intent and elevation from the element's own class, so `.pixel-solo.edgeless` drops its ring, `.glass-solo.solid.success` is an opaque green pane, and `.neobrutalism-solo.flat` has no slab. With none of those classes a solo element paints what it did. See [Aesthetics → Solo classes](../usage/aesthetics.md#solo-classes).
15
+ - **`--font-mono` is a documented token.** It sets the font of the `kbd`, `code`, and `pre` helpers and of `<kbd>`, `<code>`, and `<pre>` under `/native`, and joins the other font tokens in [Theming → Fonts](../usage/theming.md#fonts), which also shows how to load a web font.
16
+ - **Linking without a bundler.** [Integrating → Without a bundler](../integrating/without-a-bundler.md) covers plain HTML, Rails, Django, and a CDN `<link>`, which load the compiled files by path rather than by package name.
17
+ - **A stated versioning policy.** Below 1.0 a minor release may break and a patch release never does; see [Versioning](../index.md#versioning).
18
+
19
+ ## Changed
20
+
21
+ - **A solo element inside a `.solid`, `.soft`, or `.ghost` container takes that fill and the theme's text color**, since presentation cascades to it now as it does to components. A solo element whose own background does not follow the theme -- a dark toast on a light page -- inside such a container prints the theme's text; keep it out of the container, or give it `.solid` with an intent.
22
+ - **`.tight` and `.loose` stay on their own element.** They wrote `--layout-gap`, which inherits, so a plain `.stack`, `.view`, `.cluster`, or `.auto-grid` nested inside one took its gap. A nested layout keeps the default gap now; set `--layout-gap` on a container to change the gap of every layout inside it.
23
+ - **Your margin places a component dialog.** The centring of an open `<dialog class="card">` (or `.panel`, `.surface`) overruled your margin utilities and unlayered CSS; it now sits in `utilities` at zero specificity, so `mt-8` or your own rule wins, and it still beats a `base` reset such as Preflight's. A margin reset in a cascade layer of your own, declared after the package's, now wins over the centring too, as it already does over every component property.
24
+ - **`.cyber` glows from the outline.** Its glow is the intent color at 60% with a 1px spread, up from 40% with none, so the brightest point sits on the element's outline. An edgeless button, badge, or panel read as backlit -- a shadow on a dark page -- because the glow just outside it was brighter than its own fill. `.cyber-solo` takes the same glow. In the light theme the near-black glow of a neutral component is heavier too; a hued `--cyber-ink` is still the way to make it read as light there.
25
+ - **The neutral palette values carry no hue.** `--palette-border`, `--palette-surface`, and `--palette-text` are `oklch(… 0 none)` in both themes, where they were `oklch(… 0 0)`. The colors themselves are unchanged, but a missing hue takes its partner's in polar interpolation: `color-mix(in oklch, var(--palette-text), oklch(60% 0.2 240))` now lands on hue 240, a blue, where it travelled from hue 0 and landed on a purple. To keep the old result, give the neutral its old hue: `color-mix(in oklch, oklch(from var(--palette-text) l c 0), oklch(60% 0.2 240))`. Mixing in `oklab` does not, since a hueless neutral adds no hue there and the mix stays blue.
26
+
27
+ ## Removed
28
+
29
+ - **The loaders.** `.loader`, its `.sm` and `.lg` sizes, the nine variants (`.dots-wave`, `.dots-fade`, `.dots-queue`, `.dots-rotate`, `.dots-grow`, `.dots-grow-alternate`, `.dot-bounce`, `.bars-wave`, `.pulse-ring`), `.loader-mask`, and the `@codenhub/styles/tw/loader` entrypoint are gone. Importing `/tw/loader` now fails to resolve, and `<span class="loader dots-wave">` in the complete CSS renders nothing. `.sm` and `.lg` on other components are unchanged. Use a spinner from an icon set instead, such as `@codenhub/icons`, which this package does not import: a glyph with `ic-anim-spin` (`ic-lucide-loader-circle ic-anim-spin`) or the animated `svg-spinners` family, both in `currentColor`. Under `prefers-reduced-motion: reduce` every loader showed a still ring; a glyph with `ic-anim-spin` stops there too, but `svg-spinners` artwork keeps moving, so choose the glyph where that matters. See [Feedback](../usage/feedback.md) for loading the icons.
30
+
31
+ ## Fixed
32
+
33
+ - **A focused `.solid.primary` control under `.pixel` shows its focus.** The inset focus ring is the primary color, so it vanished into the fill; a line of the page color now sits inside it. `.pixel-solo` takes the same line.
34
+ - **Controls and surfaces under `.pixel` keep an edge in forced colors.** Pixel draws its edge as an inset shadow, which forced colors remove, so buttons, fields, and cards had no boundary; forced colors now draw a solid border and drop the clip. `.pixel-solo` draws an inward outline there.
35
+ - **A `.disabled` text field holds still under the pointer.** The class spelling of disabled still darkened an `.ipt`'s line on hover, unlike `disabled`, `aria-disabled`, and `data-disabled`.
36
+ - **`.sketch-rounded` beside `.sketch-solo` stays on the solo element.** Its radius tokens inherited into the element's contents, so a `.btn` inside a rounded sketch toast drew a sketch outline on a page with no sketch in scope.
37
+ - **A checked native radio looks like a checked `.radio` in forced colors.** Under `/native` it drew a Highlight ring and dot on Canvas, where `.radio` draws a Highlight disc with a HighlightText dot, so `<input type="radio" class="radio">` changed look with the entrypoint. Both draw the disc now.
38
+ - **`/theme` declares every documented color and foundation token**, except `--focus-ring-offset`, which is computed on the focused element, and the `/tw`-only `--breakpoint-xs`. The compiled entry left out `--color-background`, `--color-foreground`, `--color-text-secondary`, and `--font-default`, because nothing in it read them, so `var(--color-background)` in your own CSS over `/theme` alone resolved to nothing.
39
+ - **A liquid region blurs what takes no liquid layers.** A bare `<table>` under `/native` or your own `@apply surface` inside a `.glass-liquid` region took its clearer ground with nothing blurred behind it; it takes liquid's lighter blur now.
40
+ - **Liquid's corners stay off a solo element's contents.** `.glass-solo.glass-liquid` no longer hands liquid's corner tokens to what it holds, so a `.btn` inside a liquid solo toast keeps the page's corners.
41
+ - **A checked `.switch` stays in its track right to left.** Under `dir="rtl"` the checked knob moved the left-to-right way, out past the track's right edge; it sits at the inline end, the left, now.
42
+ - **A table row shows its own intent.** A `<tr class="destructive">` in a `.data-table.success` kept the table's green text, rule, and hover, because the table resolved them before the row's intent applied. A row with an intent draws them in its own now; on a `.solid` table its text keeps the table's ink -- the contrast ink on a hued table, the table's own text color on a neutral one -- which that plate needs. Other rows keep the table's.
43
+ - **A button in an `.input-group` keeps its own edge.** The field's line reached every component inside the group, so a `.ghost` or `.edgeless` clear button drew a border the field's color. It rests as it does outside the group now, and the group keeps its line.
44
+ - **An `.alert` in another aesthetic nested under `.neobrutalism` casts no slab.** Neobrutalism raised the elevation of every alert below it, so one inside a `.chunky-tile`, `.glass`, `.pixel`, `.cyber`, or `.sketch` region took neobrutalism's shadow, unlike a card there. It takes the nested aesthetic's look now, and a `.neobrutalism` region nested inside that one still rests its alerts on the slab.
45
+ - **A select keeps its drop-down arrow in forced colors.** The chevron is drawn with gradients, which forced colors remove, so in Chromium and Firefox a `.select` or a native `<select>` under `/native` read as a text field. A single-row select shows the platform's arrow there now.
46
+ - **An `.input-group` holding a disabled control holds still under the pointer.** The group dimmed and showed the not-allowed cursor, but its line still darkened on hover; it no longer does.
47
+ - **A padding modifier pads only its own card or panel.** `.p-xs`, `.p-sm`, `.p-lg`, and `.flush` on a `.card` or `.panel` reached every card and panel nested inside it, so a card in a `.card.p-xs` sat at 8px instead of its 20px, and one in a `.flush` card had none. A nested surface keeps its own padding now; give it a modifier of its own to change it.
48
+ - **A long select label in an `.input-group` stops short of the chevron.** The group took the select's inline padding, so a label too long for the field ran under the drop-down arrow, at the right or, right to left, at the left. A single-row select keeps room for its chevron at the inline end now.
49
+ - **Typed text in a hued or invalid field reads at 4.5:1.** The text in `.ipt`, `.textarea`, and `.select` was the intent's base color, which fell as low as 2.5:1 against the field: a `.warning` field in the light theme, and `.success`, `.destructive`, `.info`, and `aria-invalid="true"` fields in the dark one, worst on `.soft` and `.solid`. It is the intent's strong tone now, darker in light and lighter in dark, at 4.5:1 or better for every intent and presentation in both themes. The field's line, focus ring, and fill are unchanged. Native fields under `/native` take the same text. A field with no intent class takes the neutral strong tone too, so its text is a shade different from 0.6.
50
+ - **The package's NOTICE covers the checkbox marks' Feather origin.** The checkbox check and indeterminate minus come from Lucide icons derived from Feather, and NOTICE now carries Feather's MIT notice beside Lucide's ISC one.
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: 0.8.0
3
+ date: 2026-11-10
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.
@@ -6,6 +6,8 @@ group: Changelog
6
6
 
7
7
  # Changelog
8
8
 
9
+ - [0.8.0](0.8.0.md)
10
+ - [0.7.0](0.7.0.md)
9
11
  - [0.6.0](0.6.0.md)
10
12
  - [0.5.0](0.5.0.md)
11
13
  - [0.4.0](0.4.0.md)
package/docs/concepts.md CHANGED
@@ -1,69 +1,211 @@
1
1
  ---
2
- title: Concepts
3
- description: The three-axis model, the token system, and how theme selection works.
4
- order: 2
2
+ title: Building a screen
3
+ description: Lay out the settings page, set its type, and add cards and buttons while learning intent, fill, edge, and aesthetic.
4
+ order: 3
5
5
  ---
6
6
 
7
- # Concepts
7
+ # Building a screen
8
8
 
9
- Read this before the usage guides. It explains the mental model every component, token, and class in this package shares.
9
+ This page turns the empty shell from [Setup](./setup.md) into the first real part of the settings screen: a page header, a profile card with Save and Cancel buttons, and a plan summary beside a usage card. On the way it introduces the three choices every component makes, intent, presentation, and aesthetic, at the moment the screen needs each one. Everything else in these docs builds on this model.
10
10
 
11
- ## The three axes
11
+ ## The smallest screen
12
12
 
13
- Every component separates three independent choices, so each can change without a component-specific variant:
13
+ A page header and one card with one button:
14
14
 
15
- | Axis | Question | Classes | Inheritance |
16
- | ------------ | --------------- | -------------------------------------------------------------------------------------------------------------- | ------------ |
17
- | Intent | Which color? | `.primary`, `.secondary`, `.success`, `.warning`, `.destructive`, `.info` | Element only |
18
- | Presentation | How much of it? | `.solid`, `.soft`, `.ghost`, `.edged`, `.edgeless` | Cascades |
19
- | Aesthetic | Made of what? | `.neobrutalism`, `.glass`, `.pixel`, `.chunky-tile`, `.cyber`, `.sketch` from an optional aesthetic stylesheet | Cascades |
15
+ ```html
16
+ <main class="section">
17
+ <div class="section-content narrow stack">
18
+ <h1 class="text-title">Account settings</h1>
19
+ <section class="card stack">
20
+ <h2 class="text-title-sm">Profile</h2>
21
+ <p>Your name appears on invoices and shared projects.</p>
22
+ <button class="btn primary" type="button">Save changes</button>
23
+ </section>
24
+ </div>
25
+ </main>
26
+ ```
27
+
28
+ Each class does one job:
29
+
30
+ - `.section` pads the page: a responsive gutter at the sides (1 to 2rem) and generous space above and below (4 to 7rem).
31
+ - `.section-content` centers a column with a maximum width; `.narrow` makes that 48rem instead of 80rem, a comfortable width for a form.
32
+ - `.stack` lays its children out vertically with a 1rem gap.
33
+ - `.text-title` and `.text-title-sm` set heading sizes: 1.875rem bold and 1.25rem semibold.
34
+ - `.card` is a bordered container with rounded corners and 1.25rem of padding.
35
+ - `.btn` makes a button, and `.primary` gives it the primary color.
36
+
37
+ Headings are not sized by their tag: the reset gives an `<h1>` with no type class the same size and weight as the text around it. That keeps the document structure, which heading level an element is, separate from the size you want it to look. If you want headings styled automatically, see [Setup → Classless HTML](./setup.md#classless-html).
38
+
39
+ ## Lay out the page
40
+
41
+ Three layout helpers cover most screens, and all three use the same gap, `--layout-gap` (1rem):
42
+
43
+ - `.stack` for vertical lists of blocks.
44
+ - `.cluster` for a row that wraps when it runs out of room, such as a group of buttons. Add `.between` to push the first and last items to opposite ends.
45
+ - `.auto-grid` for a grid of equal cards that adds or drops columns as the space changes. A column is never narrower than `--layout-grid-min` (16rem) unless the container itself is.
46
+
47
+ `.tight` (0.5rem) and `.loose` (1.5rem) change the gap of the layout they sit on. A layout nested inside keeps its own gap.
48
+
49
+ Add a header and put the buttons in a row:
20
50
 
21
51
  ```html
22
- <section class="soft pixel">
23
- <button class="btn primary">Soft primary pixel button</button>
24
- <button class="btn destructive ghost edged">Outlined destructive override</button>
25
- </section>
52
+ <main class="section">
53
+ <div class="section-content narrow stack loose">
54
+ <header class="stack tight">
55
+ <h1 class="text-title">Account settings</h1>
56
+ <p>Manage your profile, plan, and security.</p>
57
+ </header>
58
+
59
+ <section class="card stack" aria-labelledby="profile-title">
60
+ <h2 class="text-title-sm" id="profile-title">Profile</h2>
61
+ <p>Your name appears on invoices and shared projects.</p>
62
+ <div class="cluster">
63
+ <button class="btn primary" type="button">Save changes</button>
64
+ <button class="btn ghost" type="button">Cancel</button>
65
+ </div>
66
+ </section>
67
+ </div>
68
+ </main>
26
69
  ```
27
70
 
28
- Intent stays on the component so a semantic container cannot accidentally recolor nested controls. Presentation and aesthetic cascade from a container; putting either class directly on a component overrides the inherited choice. Components apply documented clamps when an axis would remove an essential edge or overwhelm compact geometry.
71
+ [Content and layout](./usage/content-and-layout.md) lists every layout helper, including `.view`, `.divider`, and `.visually-hidden`, and the full type scale.
72
+
73
+ ## Intent: which color
74
+
75
+ The Save button is `.primary` and the Cancel button has no intent, which makes it neutral. An intent class picks a color role:
76
+
77
+ | Class | Use it for | Default color |
78
+ | -------------- | ------------------------------------- | --------------------------------------- |
79
+ | _none_ | Anything without a meaning of its own | The page's text and border grays |
80
+ | `.primary` | The main action on a screen | Near-black on light, near-white on dark |
81
+ | `.secondary` | A second, quieter action | Mid gray |
82
+ | `.success` | Confirmation and completed states | Emerald green |
83
+ | `.warning` | Something that needs attention soon | Amber, with dark text |
84
+ | `.destructive` | Deleting, revoking, and errors | Rose red |
85
+ | `.info` | Neutral notices and help | Indigo |
86
+
87
+ Intent stays on the element that carries it. Putting `.destructive` on a `<section>` does not turn every button inside it red; you write it on each button. This is deliberate: a container that silently recolored everything inside it would turn a red danger zone's Cancel button red too.
88
+
89
+ `.neutral` names the default explicitly. You rarely need it, because no intent class already means neutral; it matters where color would otherwise come from elsewhere, such as a table row, which inherits its table's intent.
90
+
91
+ ## Presentation: how much color
92
+
93
+ The Cancel button is `.ghost`: no fill, just colored text, so it reads as less important than Save. That is the presentation axis, two independent choices:
94
+
95
+ - **Fill:** `.solid` fills the component with its intent color and switches the text to the contrasting color. `.soft` mixes in a light 12% tint and keeps the text in the intent color. `.ghost` has no fill at rest.
96
+ - **Edge:** `.edged` draws a border in the intent color; `.edgeless` draws none.
97
+
98
+ ```html
99
+ <button class="btn primary">Save changes</button>
100
+ <button class="btn primary soft">Preview</button>
101
+ <button class="btn primary ghost edged">Export data</button>
102
+ <button class="btn ghost">Cancel</button>
103
+ ```
104
+
105
+ Every component has its own default when no presentation class applies. A button is solid with no border. A card has no fill and a border. A form field has no fill and a border. [Composing](./usage/composing.md#component-defaults) lists the default of every component.
106
+
107
+ Unlike intent, presentation passes down. A `.soft` on a container makes everything inside it soft unless an element says otherwise, and a class on the element itself always beats one inherited from a container:
108
+
109
+ ```html
110
+ <div class="cluster soft">
111
+ <button class="btn primary">Soft primary</button>
112
+ <button class="btn success">Soft success</button>
113
+ <button class="btn primary solid">Solid: its own class wins</button>
114
+ </div>
115
+ ```
116
+
117
+ Some components limit what presentation can do, to protect something they need. A form field inherited into a `.solid` container fills to only 6%, so typed text stays readable. A checkbox always keeps its border, because the border is the only thing that shows an unchecked box. These limits are listed with each component and collected in [Composing](./usage/composing.md).
118
+
119
+ ## Finish the first screen
120
+
121
+ Add a plan summary next to a usage card in a grid, and give the summary a soft primary tint so it stands out as the account's current state:
122
+
123
+ ```html
124
+ <main class="section">
125
+ <div class="section-content narrow stack loose">
126
+ <header class="stack tight">
127
+ <h1 class="text-title">Account settings</h1>
128
+ <p>Manage your profile, plan, and security.</p>
129
+ </header>
130
+
131
+ <section class="card stack" aria-labelledby="profile-title">
132
+ <h2 class="text-title-sm" id="profile-title">Profile</h2>
133
+ <p>Your name appears on invoices and shared projects.</p>
134
+ <div class="cluster">
135
+ <button class="btn primary" type="button">Save changes</button>
136
+ <button class="btn ghost" type="button">Cancel</button>
137
+ </div>
138
+ </section>
139
+
140
+ <div class="auto-grid">
141
+ <section class="card soft primary stack tight" aria-labelledby="plan-title">
142
+ <h2 class="text-label" id="plan-title">Current plan</h2>
143
+ <p class="text-title-sm">Team, billed yearly</p>
144
+ <p class="text-body">Renews on 12 March 2027.</p>
145
+ </section>
146
+ <section class="card stack tight" aria-labelledby="usage-title">
147
+ <h2 class="text-label" id="usage-title">Storage</h2>
148
+ <p class="text-title-sm">48 GB of 100 GB</p>
149
+ <p class="text-body">Shared by 6 members.</p>
150
+ </section>
151
+ </div>
152
+ </div>
153
+ </main>
154
+ ```
155
+
156
+ On a wide window the two cards sit side by side; when the column is too narrow for two 16rem columns and the gap between them, they stack. The [Feedback](./usage/feedback.md) page turns the storage card's number into a usage bar.
157
+
158
+ A `.card` rests at one unit of depth, but on the base look that depth has no visible shadow; it appears when an aesthetic draws one or when you add `.raised` or `.floating`. [Composing → Elevation](./usage/composing.md#elevation) covers depth.
159
+
160
+ ## Aesthetic: what it is made of
161
+
162
+ The third axis changes the material of everything inside it: corners, border width, shadows, and sometimes the font. It needs its own import (see [Setup → Add an aesthetic](./setup.md#add-an-aesthetic-optional)):
163
+
164
+ ```html
165
+ <main class="section neobrutalism">
166
+ <!-- The same settings screen: square corners, thick dark lines, hard offset shadows -->
167
+ </main>
168
+ ```
29
169
 
30
- The maintained contract is the intersection of the combinations documented in [Usage](./usage/index.md) and demonstrated by the playground. Undocumented and undemonstrated combinations may produce CSS but are not supported behavior.
170
+ Like presentation, an aesthetic passes down, and a component inside it can carry a different one. You do not need it to build the screen; [Aesthetics](./usage/aesthetics.md) compares all six.
31
171
 
32
- - [Usage → Composing](./usage/composing.md) shows how the three axes combine on each component, with the full axis-support matrix.
33
- - [Usage → Aesthetics](./usage/aesthetics.md) covers each aesthetic and its documented exceptions in depth.
172
+ ## Words these docs use
34
173
 
35
- ## The token system
174
+ Some pages describe how a component is painted. These words have one meaning each:
36
175
 
37
- Tokens are CSS custom properties, grouped by what they control rather than where they're used:
176
+ | Word | Meaning |
177
+ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
178
+ | Fill | How much of the intent color covers the component, from 0% (`.ghost`) to 100% (`.solid`). |
179
+ | Cap | The highest fill a component allows. A form field caps an inherited fill at 6%, for example. |
180
+ | Plate | The component's painted background: the fill, mixed over the ground. |
181
+ | Ground | The color the fill is mixed over. Usually the page itself shows through; a few components set their own, such as the light intent tint under `.kbd` and `.code`. |
182
+ | Edge | The border around the component. It is separate from rules, the lines inside a table. |
183
+ | Ink | A color used to draw lines: the edge, a table's rules, a checkbox's mark. "Text ink" means the color of text printed on a plate. |
184
+ | Material | What an aesthetic changes: corner radius and shape, border width and style, shadow, and transparency. |
185
+ | Slab | A hard, unblurred shadow offset down and to one side, as `.neobrutalism` and `.chunky-tile` draw. |
186
+ | Elevation | How much of the shadow in scope an element takes: none (`.flat`), one unit (`.raised`), or two (`.floating`). |
38
187
 
39
- | Category | Controls | Reference |
40
- | ------------ | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
41
- | Color | The palette: primary, accent, success, warning, destructive, info, text, borders, surfaces. | [Usage → Theming](./usage/theming.md#color-tokens) |
42
- | Intent | Which color slot a component reads once an intent class is applied. | [Usage → Theming](./usage/theming.md#intent-tokens) |
43
- | Foundation | Layout, shape, motion, focus, depth, and layering defaults shared across components. | [Usage → Theming](./usage/theming.md#foundation-tokens) |
44
- | Presentation | How much of an intent a component shows — fill and border percentages. | [Usage → Customizing](./usage/customizing.md#presentation-tokens) |
45
- | Material | What a component is made of — radius, border width, shadow geometry, translucency. | [Usage → Customizing](./usage/customizing.md#material-tokens) |
46
- | Aesthetic | Per-aesthetic knobs such as `--pixel-unit` or `--tile-lift`. | [Usage → Customizing](./usage/customizing.md#aesthetic-tokens) |
188
+ ## Tokens behind the classes
47
189
 
48
- Color and foundation tokens are the ones most apps touch first, to match a brand palette or spacing scale. Intent, presentation, and material tokens are lower-level: components read them, and only presentation classes, aesthetic classes, or a consumer override should set them.
190
+ Every class reads CSS custom properties, called tokens, so you can change the result without rewriting a class:
49
191
 
50
- ## Theme selection
192
+ | Kind | Controls | Where it is listed |
193
+ | ------------ | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
194
+ | Color | The palette: intent colors, text, borders, and backgrounds, for light and dark. | [Theming → Color tokens](./usage/theming.md#color-tokens) |
195
+ | Foundation | Layout widths and gaps, corner radii, control height, focus, motion. | [Theming → Foundation tokens](./usage/theming.md#foundation-tokens) |
196
+ | Intent | The color slots a component reads after an intent class picks a role. | [Theming → Intent tokens](./usage/theming.md#intent-tokens) |
197
+ | Presentation | The fill and border percentages the presentation classes set. | [Customizing → Presentation tokens](./usage/customizing.md#presentation-tokens) |
198
+ | Material | Radius, border width, shadow geometry, and transparency. | [Customizing → Material tokens](./usage/customizing.md#material-tokens) |
199
+ | Aesthetic | One knob per aesthetic, such as `--pixel-unit` or `--tile-lift`. | [Customizing → Aesthetic tokens](./usage/customizing.md#aesthetic-tokens) |
51
200
 
52
- The root follows the operating-system `color-scheme` preference until an explicit selector overrides it.
201
+ Color and foundation tokens are what most apps change first, to match a brand. The rest are lower level: components read them, and the presentation and aesthetic classes set them for you.
53
202
 
54
- | Theme | Equivalent selectors |
55
- | ----- | ------------------------------------------------ |
56
- | Light | `.light`, `.theme-light`, `[data-theme="light"]` |
57
- | Dark | `.dark`, `.theme-dark`, `[data-theme="dark"]` |
203
+ ## Limits to know now
58
204
 
59
- - Theme selectors set `color-scheme` and nothing else. Because `color-scheme` inherits, a selector themes its entire subtree.
60
- - With no explicit selector, `:root` uses `color-scheme: light dark`, so the system preference decides.
61
- - A theme selector on `:root` overrides the system preference in either direction.
62
- - A nested explicit selector overrides an inherited theme, so the nearest themed ancestor controls that subtree at any depth.
63
- - If conflicting light and dark selectors are placed on the same element, the dark declaration wins because it appears later with equal specificity. Do not rely on this conflict behavior; apply one theme per element.
64
- - Component colors resolve from tokens or `currentColor`, so they follow the theme without separate dark-variant rules, with no exception: every glyph the package draws is a `currentColor` mask. Icon artwork a consumer brings is theirs to theme.
65
- - The Tailwind source entrypoints' `dark:` variant tracks this rule for the explicit-selector-versus-system-preference choice: it fires under an explicit dark selector, or under the system preference when the subtree carries no explicit selector at all. It does not track the previous rule the same way: that one holds because `color-scheme` inherits, so the nearest declaration always wins regardless of depth, while `dark:` matches by selector -- `.dark *` matches every descendant of a `.dark` element, with no way to stop at a nearer `.light` in between. A `.light` subtree nested inside `.dark` themes its tokens correctly but still matches `dark:`'s explicit arm. See [Setup → Dark variant](./setup.md#dark-variant).
205
+ - **Intent does not pass down.** Write it on each element that shows it. The only exception is table rows.
206
+ - **Classes are styling only.** `<div class="btn">` looks like a button but cannot be focused or pressed with a keyboard. Use `<button>` or `<a href>`, and see [Accessibility](./accessibility.md).
207
+ - **A combination the docs do not describe is not supported.** It may render, but it can change in any release; see [Introduction → What counts as supported](./index.md#what-counts-as-supported).
66
208
 
67
- Setting `color-scheme` yourself on an element also re-themes the tokens below it, because that is the only signal the palette reads. This also themes native UI such as scrollbars and form-control internals to match.
209
+ ## Next
68
210
 
69
- This mechanism works from Chrome 123, Safari 17.5, and Firefox 120; the package overall requires Firefox 128, for `@property` and `:has()` (see [Setup](./setup.md#requirements)).
211
+ The screen has one primary action and one quiet one. [Buttons](./usage/buttons.md) adds the rest: a destructive action for the danger zone, icon buttons, sizes, and disabled states.