stillwind 0.0.0 → 0.1.0-rc.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 (305) hide show
  1. package/AGENTS_TEMPLATE.md +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +166 -0
  4. package/TAILWINDCSS-MIT-LICENSE +21 -0
  5. package/css/builtin-metadata/sw-motion-properties.css +186 -0
  6. package/css/builtin-metadata/tw-legacy-metadata.css +36 -0
  7. package/css/builtin-metadata/tw-properties.css +944 -0
  8. package/css/builtin-metadata/tw-registry-metadata.css +52 -0
  9. package/css/builtin-metadata/tw-relationship-metadata.css +10 -0
  10. package/css/builtin-utilities/sw-motion-contexts.css +1043 -0
  11. package/css/builtin-utilities/tw-backgrounds.css +606 -0
  12. package/css/builtin-utilities/tw-borders.css +954 -0
  13. package/css/builtin-utilities/tw-effects.css +1209 -0
  14. package/css/builtin-utilities/tw-flex-grid.css +749 -0
  15. package/css/builtin-utilities/tw-interactivity.css +680 -0
  16. package/css/builtin-utilities/tw-layout.css +943 -0
  17. package/css/builtin-utilities/tw-masks.css +1268 -0
  18. package/css/builtin-utilities/tw-motion.css +142 -0
  19. package/css/builtin-utilities/tw-spacing-sizing.css +621 -0
  20. package/css/builtin-utilities/tw-svg.css +50 -0
  21. package/css/builtin-utilities/tw-transforms.css +652 -0
  22. package/css/builtin-utilities/tw-typography.css +720 -0
  23. package/css/builtin-variants/sw-conditional.css +5 -0
  24. package/css/builtin-variants/sw-document.css +13 -0
  25. package/css/builtin-variants/tw-conditional.css +187 -0
  26. package/css/builtin-variants/tw-dynamic-selector.css +49 -0
  27. package/css/builtin-variants/tw-relationship.css +41 -0
  28. package/css/builtin-variants/tw-state.css +159 -0
  29. package/css/builtin-variants/tw-structural.css +121 -0
  30. package/css/builtins.css +111 -0
  31. package/css/preflight.css +401 -0
  32. package/css/templates.css +40 -0
  33. package/css/theme.css +546 -0
  34. package/css/utilities.css +9 -0
  35. package/dist/class-object-D24FFYqO.js +6 -0
  36. package/dist/class-object-D24FFYqO.js.map +1 -0
  37. package/dist/class-object-D7ZGJOf_.d.ts +9 -0
  38. package/dist/class-string-CQHnc9GN.d.ts +9 -0
  39. package/dist/class-string-Db8-oI4q.js +6 -0
  40. package/dist/class-string-Db8-oI4q.js.map +1 -0
  41. package/dist/config.d.ts +1 -0
  42. package/dist/config.js +2 -0
  43. package/dist/css.d.ts +100 -0
  44. package/dist/css.js +143 -0
  45. package/dist/css.js.map +1 -0
  46. package/dist/cva-BwX07CFw.js +204 -0
  47. package/dist/cva-BwX07CFw.js.map +1 -0
  48. package/dist/cva-DSpDNBYi.d.ts +9 -0
  49. package/dist/development-DttPQc71.d.ts +27 -0
  50. package/dist/development-J-JCSIm0.js +111 -0
  51. package/dist/development-J-JCSIm0.js.map +1 -0
  52. package/dist/frameworks/alpine.d.ts +20 -0
  53. package/dist/frameworks/alpine.js +18 -0
  54. package/dist/frameworks/alpine.js.map +1 -0
  55. package/dist/frameworks/astro.d.ts +3 -0
  56. package/dist/frameworks/astro.js +1 -0
  57. package/dist/frameworks/lit.d.ts +21 -0
  58. package/dist/frameworks/lit.js +38 -0
  59. package/dist/frameworks/lit.js.map +1 -0
  60. package/dist/frameworks/preact.d.ts +3 -0
  61. package/dist/frameworks/preact.js +1 -0
  62. package/dist/frameworks/qwik.d.ts +3 -0
  63. package/dist/frameworks/qwik.js +1 -0
  64. package/dist/frameworks/react.d.ts +10 -0
  65. package/dist/frameworks/react.js +6 -0
  66. package/dist/frameworks/react.js.map +1 -0
  67. package/dist/frameworks/solid.d.ts +3 -0
  68. package/dist/frameworks/solid.js +1 -0
  69. package/dist/frameworks/svelte.d.ts +3 -0
  70. package/dist/frameworks/svelte.js +1 -0
  71. package/dist/frameworks/vanilla.d.ts +27 -0
  72. package/dist/frameworks/vanilla.js +3 -0
  73. package/dist/frameworks/vue.d.ts +3 -0
  74. package/dist/frameworks/vue.js +1 -0
  75. package/dist/index-RwVFpxhE.d.ts +815 -0
  76. package/dist/macro/index.d.ts +2 -0
  77. package/dist/macro/index.js +1 -0
  78. package/dist/module-css.d.ts +30 -0
  79. package/dist/module-css.js +23 -0
  80. package/dist/module-css.js.map +1 -0
  81. package/dist/runtime/class-name-object-development.d.ts +10 -0
  82. package/dist/runtime/class-name-object-development.js +18 -0
  83. package/dist/runtime/class-name-object-development.js.map +1 -0
  84. package/dist/runtime/class-name-object.d.ts +16 -0
  85. package/dist/runtime/class-name-object.js +31 -0
  86. package/dist/runtime/class-name-object.js.map +1 -0
  87. package/dist/runtime/class-object-development.d.ts +10 -0
  88. package/dist/runtime/class-object-development.js +18 -0
  89. package/dist/runtime/class-object-development.js.map +1 -0
  90. package/dist/runtime/class-object.d.ts +16 -0
  91. package/dist/runtime/class-object.js +31 -0
  92. package/dist/runtime/class-object.js.map +1 -0
  93. package/dist/runtime/class-string-development.d.ts +10 -0
  94. package/dist/runtime/class-string-development.js +18 -0
  95. package/dist/runtime/class-string-development.js.map +1 -0
  96. package/dist/runtime/class-string.d.ts +16 -0
  97. package/dist/runtime/class-string.js +31 -0
  98. package/dist/runtime/class-string.js.map +1 -0
  99. package/dist/shared-B9IQXU6P.d.ts +32 -0
  100. package/dist/style-BV4ctkni.js +78 -0
  101. package/dist/style-BV4ctkni.js.map +1 -0
  102. package/dist/style-fTQbsVWZ.js +41 -0
  103. package/dist/style-fTQbsVWZ.js.map +1 -0
  104. package/docs/agents.md +76 -0
  105. package/docs/at-rules/apply.md +93 -0
  106. package/docs/at-rules/custom-variant.md +127 -0
  107. package/docs/at-rules/index.md +75 -0
  108. package/docs/at-rules/plugin.md +71 -0
  109. package/docs/at-rules/registry-directives.md +181 -0
  110. package/docs/at-rules/slot.md +58 -0
  111. package/docs/at-rules/stillwind-css-template.md +126 -0
  112. package/docs/at-rules/stillwind-property.md +133 -0
  113. package/docs/at-rules/stillwind-registry.md +115 -0
  114. package/docs/at-rules/stillwind-require-properties.md +91 -0
  115. package/docs/at-rules/stillwind-slot.md +85 -0
  116. package/docs/at-rules/stillwind-undef-arbitrary-property.md +75 -0
  117. package/docs/at-rules/stillwind-undef-utility.md +87 -0
  118. package/docs/at-rules/stillwind-undef-variant.md +55 -0
  119. package/docs/at-rules/theme.md +304 -0
  120. package/docs/at-rules/utility.md +286 -0
  121. package/docs/at-rules/variant.md +91 -0
  122. package/docs/concepts/css-ordering.md +245 -0
  123. package/docs/concepts/how-styles-compile.md +132 -0
  124. package/docs/configuration.md +298 -0
  125. package/docs/errors/SW01001.md +51 -0
  126. package/docs/errors/SW01002.md +52 -0
  127. package/docs/errors/SW01003.md +69 -0
  128. package/docs/errors/SW02001.md +23 -0
  129. package/docs/errors/SW02002.md +51 -0
  130. package/docs/errors/SW03001.md +71 -0
  131. package/docs/errors/SW03002.md +79 -0
  132. package/docs/errors/SW03003.md +36 -0
  133. package/docs/errors/SW10001.md +34 -0
  134. package/docs/errors/SW10002.md +36 -0
  135. package/docs/errors/SW10003.md +30 -0
  136. package/docs/errors/SW10004.md +39 -0
  137. package/docs/errors/SW10005.md +35 -0
  138. package/docs/errors/SW11001.md +37 -0
  139. package/docs/errors/SW11002.md +65 -0
  140. package/docs/errors/SW11003.md +20 -0
  141. package/docs/errors/SW12001.md +43 -0
  142. package/docs/errors/SW12002.md +42 -0
  143. package/docs/errors/SW13001.md +35 -0
  144. package/docs/errors/SW13002.md +33 -0
  145. package/docs/errors/SW13003.md +18 -0
  146. package/docs/errors/SW13004.md +45 -0
  147. package/docs/errors/SW14001.md +44 -0
  148. package/docs/errors/SW14002.md +47 -0
  149. package/docs/errors/SW14003.md +38 -0
  150. package/docs/errors/SW14004.md +48 -0
  151. package/docs/errors/SW14005.md +51 -0
  152. package/docs/errors/SW14006.md +19 -0
  153. package/docs/errors/SW14007.md +35 -0
  154. package/docs/errors/SW14008.md +41 -0
  155. package/docs/errors/SW15001.md +18 -0
  156. package/docs/errors/SW15002.md +19 -0
  157. package/docs/errors/SW15003.md +16 -0
  158. package/docs/errors/SW30001.md +21 -0
  159. package/docs/errors/SW30002.md +18 -0
  160. package/docs/errors/SW30003.md +17 -0
  161. package/docs/errors/SW30004.md +18 -0
  162. package/docs/errors/SW31001.md +20 -0
  163. package/docs/errors/SW31002.md +17 -0
  164. package/docs/errors/SW31003.md +18 -0
  165. package/docs/errors/SW31004.md +20 -0
  166. package/docs/errors/SW31005.md +18 -0
  167. package/docs/errors/SW31006.md +17 -0
  168. package/docs/errors/SW31007.md +18 -0
  169. package/docs/errors/SW31008.md +16 -0
  170. package/docs/errors/SW31009.md +18 -0
  171. package/docs/errors/SW31010.md +16 -0
  172. package/docs/errors/SW31011.md +17 -0
  173. package/docs/errors/SW32001.md +18 -0
  174. package/docs/errors/SW32002.md +45 -0
  175. package/docs/errors/SW32003.md +43 -0
  176. package/docs/errors/SW32004.md +17 -0
  177. package/docs/errors/SW32005.md +40 -0
  178. package/docs/errors/SW32006.md +18 -0
  179. package/docs/errors/SW32007.md +20 -0
  180. package/docs/errors/SW33001.md +17 -0
  181. package/docs/errors/SW33002.md +17 -0
  182. package/docs/errors/SW33003.md +17 -0
  183. package/docs/errors/SW33004.md +17 -0
  184. package/docs/errors/SW33005.md +20 -0
  185. package/docs/errors/SW34001.md +18 -0
  186. package/docs/errors/SW34002.md +17 -0
  187. package/docs/errors/SW34003.md +18 -0
  188. package/docs/errors/SW90001.md +17 -0
  189. package/docs/errors/SW90002.md +18 -0
  190. package/docs/errors/SW90003.md +17 -0
  191. package/docs/errors/SW90004.md +17 -0
  192. package/docs/errors/SW90005.md +16 -0
  193. package/docs/errors/SW90006.md +17 -0
  194. package/docs/errors/SW90007.md +17 -0
  195. package/docs/errors/SW90008.md +17 -0
  196. package/docs/errors/index.md +125 -0
  197. package/docs/guides/animations.md +73 -0
  198. package/docs/guides/design-systems.md +119 -0
  199. package/docs/guides/element-relationships.md +136 -0
  200. package/docs/guides/lint-adoption.md +128 -0
  201. package/docs/guides/migrating-from-css.md +126 -0
  202. package/docs/guides/migrating-from-tailwind.md +179 -0
  203. package/docs/guides/recommended-practices.md +338 -0
  204. package/docs/guides/responsive-styles.md +103 -0
  205. package/docs/guides/reusable-styles.md +110 -0
  206. package/docs/guides/style.md +181 -0
  207. package/docs/guides/tailwind-compatibility.md +126 -0
  208. package/docs/guides/view-transitions.md +84 -0
  209. package/docs/guides/web-components.md +216 -0
  210. package/docs/index.md +136 -0
  211. package/docs/integrations.md +190 -0
  212. package/docs/lints/ambiguous-style-base-order.md +50 -0
  213. package/docs/lints/bypassed-undefinition.md +50 -0
  214. package/docs/lints/clamped-value.md +44 -0
  215. package/docs/lints/conflicting-provider-properties.md +47 -0
  216. package/docs/lints/conflicting-utilities.md +55 -0
  217. package/docs/lints/document-scoped-selector.md +45 -0
  218. package/docs/lints/duplicate-definition.md +44 -0
  219. package/docs/lints/duplicate-utility.md +44 -0
  220. package/docs/lints/duplicate-view-transition-name.md +45 -0
  221. package/docs/lints/ignored-definition-condition.md +51 -0
  222. package/docs/lints/ignored-tailwind-feature.md +62 -0
  223. package/docs/lints/incompatible-property-value.md +60 -0
  224. package/docs/lints/incompatible-theme-value.md +46 -0
  225. package/docs/lints/index.md +140 -0
  226. package/docs/lints/ineffective-anchor-scope.md +46 -0
  227. package/docs/lints/interfering-imported-style-base.md +57 -0
  228. package/docs/lints/invalid-animation-option.md +47 -0
  229. package/docs/lints/invalid-css-directive.md +43 -0
  230. package/docs/lints/invalid-css-import.md +43 -0
  231. package/docs/lints/invalid-css-input.md +45 -0
  232. package/docs/lints/invalid-cva-config.md +46 -0
  233. package/docs/lints/invalid-cva-input.md +50 -0
  234. package/docs/lints/invalid-keyframes-definition.md +47 -0
  235. package/docs/lints/invalid-keyframes-use.md +47 -0
  236. package/docs/lints/invalid-keyframes-variant.md +48 -0
  237. package/docs/lints/invalid-lint-suppression.md +47 -0
  238. package/docs/lints/invalid-marker-use.md +53 -0
  239. package/docs/lints/invalid-media-query.md +52 -0
  240. package/docs/lints/invalid-ref-input.md +49 -0
  241. package/docs/lints/invalid-rule-group-input.md +58 -0
  242. package/docs/lints/invalid-runtime-condition.md +67 -0
  243. package/docs/lints/invalid-style-composition.md +52 -0
  244. package/docs/lints/invalid-style-input.md +47 -0
  245. package/docs/lints/invalid-theme-reference.md +52 -0
  246. package/docs/lints/invalid-utility.md +44 -0
  247. package/docs/lints/invalid-variant.md +45 -0
  248. package/docs/lints/invalid-view-transition-definition.md +46 -0
  249. package/docs/lints/invalid-view-transition-use.md +46 -0
  250. package/docs/lints/invalid-view-transition-variant.md +51 -0
  251. package/docs/lints/mismatched-framework-import.md +47 -0
  252. package/docs/lints/missing-document-target.md +44 -0
  253. package/docs/lints/missing-ref-attachment.md +44 -0
  254. package/docs/lints/missing-view-transition-name.md +46 -0
  255. package/docs/lints/mutating-macro-argument.md +48 -0
  256. package/docs/lints/no-arbitrary-breakpoints.md +50 -0
  257. package/docs/lints/no-arbitrary-colors.md +51 -0
  258. package/docs/lints/no-arbitrary-spacing.md +57 -0
  259. package/docs/lints/no-class-property.md +58 -0
  260. package/docs/lints/no-important.md +50 -0
  261. package/docs/lints/no-restricted-declarations.md +76 -0
  262. package/docs/lints/no-restricted-length-units.md +73 -0
  263. package/docs/lints/no-restricted-theme-tokens.md +73 -0
  264. package/docs/lints/no-restricted-utilities.md +73 -0
  265. package/docs/lints/prefer-canonical-utilities.md +69 -0
  266. package/docs/lints/prefer-direct-styling.md +47 -0
  267. package/docs/lints/prefer-explicit-nesting-selector.md +42 -0
  268. package/docs/lints/prefer-logical-properties.md +49 -0
  269. package/docs/lints/prefer-sorted-utilities.md +46 -0
  270. package/docs/lints/prefer-typed-relationships.md +48 -0
  271. package/docs/lints/prefer-typed-variables.md +43 -0
  272. package/docs/lints/prefer-variant-directive.md +59 -0
  273. package/docs/lints/redundant-variant.md +50 -0
  274. package/docs/lints/repeated-nesting-selector.md +59 -0
  275. package/docs/lints/runtime-condition-requires-css-if.md +59 -0
  276. package/docs/lints/split-view-transition-class.md +47 -0
  277. package/docs/lints/suspending-macro-argument.md +46 -0
  278. package/docs/lints/unknown-utility.md +47 -0
  279. package/docs/lints/unknown-variant.md +42 -0
  280. package/docs/lints/unsatisfiable-variants.md +42 -0
  281. package/docs/lints/unused-lint-suppression.md +57 -0
  282. package/docs/lints/unverified-style-base.md +64 -0
  283. package/docs/macros/anchor-scope.md +90 -0
  284. package/docs/macros/css.md +68 -0
  285. package/docs/macros/cva.md +153 -0
  286. package/docs/macros/index.md +30 -0
  287. package/docs/macros/keyframes.md +98 -0
  288. package/docs/macros/media.md +65 -0
  289. package/docs/macros/ref/as-anchor.md +70 -0
  290. package/docs/macros/ref/as-container.md +64 -0
  291. package/docs/macros/ref/at.md +68 -0
  292. package/docs/macros/ref/condition.md +86 -0
  293. package/docs/macros/ref/in.md +81 -0
  294. package/docs/macros/ref/index.md +115 -0
  295. package/docs/macros/ref/position-anchor.md +64 -0
  296. package/docs/macros/style.md +185 -0
  297. package/docs/macros/view-transition.md +159 -0
  298. package/docs/utilities.md +35 -0
  299. package/docs/why.md +144 -0
  300. package/index.css +7 -0
  301. package/package.json +135 -8
  302. package/skills/migrate-to-stillwind/SKILL.md +81 -0
  303. package/skills/setup-stillwind/SKILL.md +51 -0
  304. package/skills/stillwind/SKILL.md +54 -0
  305. package/index.js +0 -1
@@ -0,0 +1,126 @@
1
+ ---
2
+ title: "Migrating from CSS"
3
+ description: "Move styles from plain CSS, CSS Modules, preprocessors, or CSS-in-JS into style() calls and theme tokens."
4
+ ---
5
+
6
+ # Migrating from CSS
7
+
8
+ You want to move a project that styles elements with plain CSS, CSS Modules,
9
+ Sass, Less, or CSS-in-JS to Stillwind. Unlike a migration from Tailwind CSS,
10
+ you translate declarations into utilities. Check the pages in the browser after
11
+ each step, because the translation can change how elements look.
12
+
13
+ ## Set up Stillwind next to the existing CSS
14
+
15
+ Install Stillwind and register the build integration as described in
16
+ [Getting started](../index.md). Your existing stylesheets keep working while you
17
+ migrate.
18
+
19
+ `@import "stillwind"` includes the preflight reset, which changes the default
20
+ styles of elements such as headings and lists. To migrate in steps, leave out
21
+ the reset until the old styles are gone:
22
+
23
+ ```css
24
+ @layer properties, theme, base, components, utilities;
25
+
26
+ @import "stillwind/theme.css" layer(theme);
27
+ @import "stillwind/utilities.css" layer(utilities);
28
+ @import "stillwind/builtins.css";
29
+ @import "stillwind/templates.css";
30
+ ```
31
+
32
+ Stillwind's CSS is in cascade layers. A declaration outside a layer wins over a
33
+ declaration in a layer, whatever their specificity. While an old rule matches an
34
+ element, it overrides the utilities on that element. Remove the old rule when
35
+ you move its declarations.
36
+
37
+ ## Move values into the theme
38
+
39
+ Collect the colors, spacing, font sizes, radii, and breakpoints that the old
40
+ CSS repeats, such as Sass variables or custom properties in `:root`. Define them
41
+ as `@theme` tokens by role:
42
+
43
+ ```css
44
+ @theme {
45
+ --color-surface: oklch(0.98 0 0);
46
+ --color-accent: oklch(0.6 0.2 250);
47
+ --breakpoint-tablet: 48rem;
48
+ }
49
+ ```
50
+
51
+ Each token adds utilities, such as `bg-surface` and `tablet:`. Merge values that
52
+ mean the same thing. Keep values separate when they are equal by chance.
53
+ [Design systems](design-systems.md) describes how to name tokens.
54
+
55
+ ## Move rules into style()
56
+
57
+ Translate the declarations of each rule into utilities, and apply them with
58
+ `style()` on the element:
59
+
60
+ ```css title="Button.module.css"
61
+ .button {
62
+ padding: 0.5rem 1rem;
63
+ border-radius: 0.375rem;
64
+ background: var(--accent);
65
+ }
66
+
67
+ .button:hover {
68
+ opacity: 0.9;
69
+ }
70
+
71
+ .button[disabled] {
72
+ cursor: wait;
73
+ }
74
+ ```
75
+
76
+ ```tsx
77
+ import { style } from "stillwind/react";
78
+
79
+ export function Button({ loading }: { loading: boolean }) {
80
+ return (
81
+ <button
82
+ disabled={loading}
83
+ {...style("rounded-md bg-accent px-4 py-2 hover:opacity-90 disabled:cursor-wait")}
84
+ >
85
+ Save
86
+ </button>
87
+ );
88
+ }
89
+ ```
90
+
91
+ Translate selectors into variants:
92
+
93
+ | Old CSS | Stillwind |
94
+ | -------------------------------------- | ---------------------------------------------------------------------- |
95
+ | `:hover`, `:focus-visible`, `:checked` | `hover:`, `focus-visible:`, `checked:` |
96
+ | `@media (min-width: 768px)` | A breakpoint variant, such as `md:` |
97
+ | `[aria-expanded="true"]`, `[data-x]` | `aria-expanded:`, `data-[x]:` |
98
+ | `.parent:hover .child` | A ref, see [Element relationships](element-relationships.md) |
99
+ | A toggled modifier class | An attribute and its variant |
100
+ | A value set from JavaScript | A custom property in `style()` |
101
+
102
+ A declaration without a matching utility can use an arbitrary property, such as
103
+ `[content-visibility:auto]`. When several elements need it, define a custom
104
+ utility instead.
105
+
106
+ ## Replace global rules
107
+
108
+ - Keep resets and base element styles until you enable the preflight reset.
109
+ Then remove the rules that it replaces.
110
+ - Move `@keyframes` next to the component that uses them with
111
+ [style.keyframes()](../macros/keyframes.md).
112
+ - Move styles for HTML that you do not control, such as rendered Markdown, into
113
+ a custom utility. See [Recommended practices](recommended-practices.md#avoid-separate-css).
114
+
115
+ ## Replace CSS-in-JS
116
+
117
+ Move static styles from `styled()` components or `css` props into `style()`
118
+ calls. Express props that change styles with attributes and variants, as in
119
+ [Reusable styles](reusable-styles.md). For a continuous value, set a
120
+ custom property in `style()`.
121
+
122
+ ## Check the migrated code
123
+
124
+ Run the [CLI checks](lint-adoption.md) over the migrated files, and
125
+ compare the pages with the old version in the browser. After you remove the last
126
+ old stylesheet, switch to `@import "stillwind"` and check the pages again.
@@ -0,0 +1,179 @@
1
+ ---
2
+ title: "Migrating from Tailwind CSS"
3
+ description: "Move a Tailwind CSS v4 project to Stillwind, from the stylesheet and build to components and configuration."
4
+ ---
5
+
6
+ # Migrating from Tailwind CSS
7
+
8
+ You want to move an existing Tailwind CSS v4 project to Stillwind. Your utilities,
9
+ variants, theme, and plugins keep working. What changes is where you write them:
10
+ in `style()` calls instead of `className` strings.
11
+ [Tailwind CSS compatibility](tailwind-compatibility.md) lists the tested
12
+ plugins and the differences.
13
+
14
+ Tailwind scans your files for anything that looks like a class name. Stillwind
15
+ generates CSS only for the utilities in `style()` calls. A class in a plain
16
+ `className` string, or in HTML from another source, gets no CSS after the
17
+ migration. Move every utility that you want to keep into `style()`.
18
+
19
+ ## Replace the stylesheet and the build plugin
20
+
21
+ In your stylesheet, replace `@import "tailwindcss"` with `@import "stillwind"`:
22
+
23
+ ```css
24
+ @import "stillwind";
25
+
26
+ @theme {
27
+ --color-brand: oklch(0.6 0.2 250);
28
+ }
29
+ ```
30
+
31
+ Keep your `@theme`, `@utility`, `@custom-variant`, `@variant`, `@apply`, and
32
+ `@plugin` rules.
33
+
34
+ Replace the Tailwind build plugin, such as `@tailwindcss/vite`, with the
35
+ Stillwind integration. Then create `stillwind.config.ts`, as described in
36
+ [Getting started](../index.md#configure-the-project), and set up your framework, as
37
+ described in [Framework integrations](../integrations.md).
38
+
39
+ ## Move classes into style()
40
+
41
+ Replace each `className` string with a `style()` call that you spread onto the
42
+ element:
43
+
44
+ ```tsx
45
+ import { style } from "stillwind/react";
46
+
47
+ export function Button() {
48
+ return <button {...style("rounded-md bg-brand px-4 py-2 text-white")}>Continue</button>;
49
+ }
50
+ ```
51
+
52
+ Import `style` from the entrypoint of the framework that renders the element.
53
+ For a class that another stylesheet defines, pass it in a `class` field, such as
54
+ `style("p-4", { class: "external-card" })`.
55
+
56
+ A large codebase may have hundreds of `className` strings. Your coding agent can
57
+ write a one-off codemod for your repository that converts them in one pass.
58
+
59
+ ## Replace class helpers
60
+
61
+ `style()` and `style.cva()` replace the libraries that Tailwind projects use to
62
+ build class strings:
63
+
64
+ | Library | Stillwind |
65
+ | ----------------------------------- | ----------------------------------------- |
66
+ | `clsx`, `classnames` | `style()` with conditions |
67
+ | `tailwind-merge` | Compose a base with new utilities |
68
+ | `cva` from class-variance-authority | `style.cva()` with the same configuration |
69
+
70
+ ### clsx and classnames
71
+
72
+ Pass conditions as arguments:
73
+
74
+ ```tsx
75
+ import { style } from "stillwind/react";
76
+
77
+ export function SaveButton({ loading }: { loading: boolean }) {
78
+ return (
79
+ <button {...style("rounded-md bg-brand px-4 py-2 text-white", loading && "opacity-60")}>
80
+ Save
81
+ </button>
82
+ );
83
+ }
84
+ ```
85
+
86
+ Do not convert the object form of `clsx`. In `clsx({ "opacity-60": loading })`,
87
+ each key is a class name. In `style()`, each key of an object is a variant, such
88
+ as `"hover:"`. Rewrite each entry as `loading && "opacity-60"`.
89
+
90
+ ### tailwind-merge
91
+
92
+ Remove `twMerge()` calls. Store the base style and pass it to another `style()`
93
+ call. The compiler emits the new utilities after the base's CSS. They override
94
+ competing declarations when the other cascade criteria, such as specificity
95
+ and importance, are equal. See [Override a style](style.md#override-a-style)
96
+ and [CSS ordering](../concepts/css-ordering.md).
97
+
98
+ ### cva
99
+
100
+ Replace `cva(` with `style.cva(`, and import `VariantProps` from your framework's
101
+ entrypoint:
102
+
103
+ ```tsx
104
+ import { style, type VariantProps } from "stillwind/react";
105
+
106
+ const button = style.cva("rounded-md px-4 py-2", {
107
+ variants: {
108
+ tone: {
109
+ neutral: "bg-gray-100",
110
+ primary: "bg-brand text-white",
111
+ },
112
+ },
113
+ defaultVariants: {
114
+ tone: "neutral",
115
+ },
116
+ });
117
+
118
+ export function Button({ tone }: VariantProps<typeof button>) {
119
+ return <button {...button({ tone })}>Continue</button>;
120
+ }
121
+ ```
122
+
123
+ `variants`, `defaultVariants`, and `compoundVariants` work as in
124
+ class-variance-authority. Write each option value as a plain utility string,
125
+ without `&&` or a ternary. The props that the factory returns cannot be passed
126
+ to `style()` as a base. The [style.cva() reference](../macros/cva.md) lists the
127
+ other differences.
128
+
129
+ For new components, consider state variants and `data-*` attributes instead of
130
+ options. See [Reusable styles](reusable-styles.md).
131
+
132
+ ## Move configuration
133
+
134
+ Some Tailwind settings move from the stylesheet to `stillwind.config.ts`:
135
+
136
+ | Tailwind | Stillwind |
137
+ | --------------------------------- | -------------------------------------------- |
138
+ | `@config "./tailwind.config.js"` | The `tailwind` field of the project |
139
+ | `@import "tailwindcss" important` | The `important` field of the project |
140
+ | `@source` and `source(...)` | Not supported; see below |
141
+ | `blocklist` | The `no-restricted-utilities` lint rule |
142
+ | `prefix(tw)` | Write utilities without `tw:`; see below |
143
+ | `theme(...)` on the import | Not supported; define the tokens in `@theme` |
144
+
145
+ The `tailwind` field accepts a Tailwind configuration object. Its `theme`,
146
+ `presets`, `plugins`, `darkMode`, and `important` keys work as in Tailwind.
147
+ Other keys have no effect. This field requires the `tailwindcss` package.
148
+
149
+ Set `important` in one place only. Setting both `important` and
150
+ `tailwind.important` is an error.
151
+
152
+ Stillwind does not need the `tw:` class prefix, because it generates unique class
153
+ names. Theme variables can still collide with other CSS in the page. To keep the
154
+ `--tw-` names of `prefix(tw)`, set `themePrefix: "--tw-"` on the project. The
155
+ prefix applies to the generated CSS, including `var(--color-brand)` in your
156
+ stylesheet and in arbitrary values, so you can keep `var(--tw-color-brand)` or use
157
+ the shorter name. JavaScript that reads or sets a theme variable by name must use
158
+ the prefixed name.
159
+
160
+ Stillwind does not support `@source`, including `@source inline()`, or a safelist,
161
+ because only `style()` calls generate utilities. Tailwind classes inside a
162
+ dependency also get no CSS. Write each utility that you need in a `style()` call
163
+ in your own code.
164
+
165
+ Stillwind ignores `@config`, `@source`, `@reference`, and import options in the
166
+ stylesheet, and the CLI reports them with
167
+ [ignored-tailwind-feature](../lints/ignored-tailwind-feature.md). Remove them after
168
+ you move their settings. The same rule reports a v3 path in `theme()`, such as
169
+ `theme(colors.red.500)`. Use `--theme(--color-red-500)` instead.
170
+
171
+ Keep your `@plugin` rules and the `@import` rules of CSS packages.
172
+ [Tailwind CSS compatibility](tailwind-compatibility.md#plugins-and-css-packages)
173
+ lists the packages that the test suite covers.
174
+
175
+ ## Check the migrated code
176
+
177
+ Run the [CLI checks](lint-adoption.md) over the migrated files. They
178
+ report utilities that Stillwind cannot resolve and Tailwind features that it
179
+ ignores. Then test the production build and your pages in the browser.
@@ -0,0 +1,338 @@
1
+ ---
2
+ title: "Recommended practices"
3
+ description: "Keep styles next to their elements, reuse them through components, and avoid the mistakes that produce no CSS."
4
+ ---
5
+
6
+ # Recommended practices
7
+
8
+ This page collects the practices that keep a Stillwind project easy to change.
9
+ It also lists the mistakes that silently produce no CSS. The examples use React.
10
+
11
+ ## Keep styles next to their elements
12
+
13
+ Write the utilities in a `style()` call on the element that they style. When
14
+ several places need the same styles, reuse them in this order:
15
+
16
+ 1. Extract a component of your framework, and keep the `style()` call on its
17
+ element. The styles stay next to the markup that they depend on.
18
+ 2. Define a custom utility in your stylesheet when a component does not fit,
19
+ such as for links inside other components' text. A utility is available in
20
+ every file of the project, so its effect is wider than a component's.
21
+ 3. Export a stored `style()` result. The styles then move away from the element
22
+ that uses them.
23
+
24
+ When you use an imported style, spread it through `style()`:
25
+
26
+ ```tsx
27
+ import { style } from "stillwind/react";
28
+
29
+ import { card } from "./card";
30
+
31
+ export function Panel() {
32
+ return <section {...style(card)}>…</section>;
33
+ }
34
+ ```
35
+
36
+ `{...style(card)}` shows that the element receives Stillwind styles, and you can
37
+ add utilities in the same call. A plain `{...card}` hides this.
38
+
39
+ ## Spread style() onto the element
40
+
41
+ Spread the result of `style()` onto the element. Do not read `className`,
42
+ `class`, or `style` out of the result. The result can contain more than one
43
+ prop, and its shape depends on the framework and on the inputs. If code needs a
44
+ class string for another purpose, that code does not need `style()`, and a
45
+ migration can leave it unchanged.
46
+
47
+ Set custom properties in the `style()` call, such as
48
+ `style("w-(--progress)", { "--progress": value })`. `style()` returns a `style`
49
+ prop when it needs inline values, so a separate `style` prop on the same
50
+ element can conflict with it. Set the `style` prop directly only on elements
51
+ without a `style()` call. You can also use `style()` for an element that has
52
+ custom properties and no utilities.
53
+
54
+ ## Express states with attributes
55
+
56
+ Keep the same classes on an element, and let its attributes decide which styles
57
+ apply:
58
+
59
+ - For a state with an attribute, such as `disabled` or `aria-pressed`, use the
60
+ matching variant.
61
+ - For an option without a matching attribute, set a `data-*` attribute and use
62
+ a `data-[…]:` variant.
63
+ - For a value from a continuous range, set a custom property in the `style()`
64
+ call, and read it in a utility such as `w-(--progress)`.
65
+
66
+ Use a condition such as `selected && "bg-blue-50"` only when no attribute fits.
67
+ [Reusable styles](reusable-styles.md) shows each approach.
68
+
69
+ Do not track in JavaScript a state that CSS can detect, such as hover, focus,
70
+ or the width of a container. Use the matching variant, and keep component state
71
+ for what the application needs.
72
+
73
+ ## Connect elements with refs
74
+
75
+ When an element's style depends on another element, such as a hovered parent, a
76
+ sibling, a container, or an anchor, connect them with a ref from
77
+ `style.ref()`. Do not use `group-*`, `peer-*`, named containers, or hand-written
78
+ parent and sibling selectors:
79
+
80
+ ```tsx
81
+ import { style } from "stillwind/react";
82
+
83
+ export function Card() {
84
+ const card = style.ref("card");
85
+ return (
86
+ <article {...style(card, "rounded-lg p-4")}>
87
+ <h2 {...style({ [card("hover")]: "text-blue-600" })}>Project</h2>
88
+ </article>
89
+ );
90
+ }
91
+ ```
92
+
93
+ A ref is a variable, so TypeScript reports a misspelled ref, and two components
94
+ cannot collide on the same name. Anchors for anchor positioning use refs too.
95
+ [Element relationships](element-relationships.md) covers siblings,
96
+ containers, and anchors.
97
+
98
+ ## Define animations in their components
99
+
100
+ Define keyframes with [style.keyframes()](../macros/keyframes.md) and view
101
+ transitions with [style.viewTransition()](../macros/view-transition.md) in the
102
+ code that uses them. Do not add global `@keyframes` rules or fixed
103
+ `view-transition-name` values. The macros generate unique names, so you can
104
+ add, move, or remove a component without checking other code.
105
+
106
+ ## Declare refs and animations in the smallest scope
107
+
108
+ Declare a ref, keyframes, or a view transition in the smallest scope that
109
+ contains all of its uses, as you would declare any other variable. Place the
110
+ declaration next to those uses:
111
+
112
+ - A declaration that one component uses belongs in that component's function.
113
+ - A declaration that a callback uses, such as a `map()` callback, belongs in
114
+ that callback.
115
+ - A declaration that several components of one module use belongs at the top
116
+ level of that module.
117
+ - When other modules use a declaration, export it from one module, and import
118
+ it where you need it.
119
+
120
+ Each declaration creates one name wherever you write it. A smaller scope limits
121
+ where the variable is visible, and it does not create a new name for each render
122
+ or call.
123
+
124
+ ## Express options with one of a fixed set of values
125
+
126
+ For a prop that takes one of several values, such as a `type` or a `tone`,
127
+ use one of these forms. Set the value as a `data-*` attribute, and write one
128
+ variant group for each value:
129
+
130
+ ```tsx
131
+ import { style } from "stillwind/react";
132
+
133
+ export function Alert({ type }: { type: "info" | "warning" | "error" }) {
134
+ return (
135
+ <div
136
+ data-type={type}
137
+ {...style({
138
+ "": "rounded-md border p-4",
139
+ "data-[type=info]:": "border-sky-300 bg-sky-50",
140
+ "data-[type=warning]:": "border-amber-300 bg-amber-50",
141
+ "data-[type=error]:": "border-red-300 bg-red-50",
142
+ })}
143
+ />
144
+ );
145
+ }
146
+ ```
147
+
148
+ Or select the utilities with an object lookup:
149
+
150
+ ```tsx
151
+ import { style } from "stillwind/react";
152
+
153
+ export function Alert({ type }: { type: "info" | "warning" | "error" }) {
154
+ return (
155
+ <div
156
+ {...style(
157
+ "rounded-md border p-4",
158
+ {
159
+ info: "border-sky-300 bg-sky-50",
160
+ warning: "border-amber-300 bg-amber-50",
161
+ error: "border-red-300 bg-red-50",
162
+ }[type],
163
+ )}
164
+ />
165
+ );
166
+ }
167
+ ```
168
+
169
+ The attribute form keeps the classes static and changes a `data-*` attribute.
170
+ The attribute also shows the value in the browser's developer tools and in test
171
+ queries. The lookup form changes the classes and adds no attribute. In both
172
+ forms, each value has its utilities in one place.
173
+
174
+ The two forms produce different CSS:
175
+
176
+ - The attribute form compiles into one class. The element always has this
177
+ class, and the attribute selectors decide which declarations apply.
178
+ - The lookup form generates one class for each value. The lookup selects one of
179
+ these classes at runtime. In this example, the common styles add one more
180
+ class, which the element always has.
181
+
182
+ In both forms, the styles for a value usually win over the common styles. In the
183
+ attribute form, the attribute selector adds specificity, and the variant order
184
+ places the rules after the common styles. In the lookup form, the compiler
185
+ places the utilities that a condition selects after the unconditional
186
+ utilities. More specific selectors and `!important` can still change the
187
+ result. [CSS ordering](../concepts/css-ordering.md) describes these rules.
188
+
189
+ ## Group utilities by variant
190
+
191
+ When several utilities share a variant, group them under one key instead of
192
+ repeating the prefix:
193
+
194
+ ```tsx
195
+ style({
196
+ "": "rounded-md bg-gray-100 px-4 py-2",
197
+ "hover:": "bg-gray-200 text-gray-900",
198
+ "focus-visible:": "outline-2 outline-offset-2 outline-accent",
199
+ });
200
+
201
+ // Or write the base utilities as a separate string.
202
+ style("rounded-md bg-gray-100 px-4 py-2", {
203
+ "hover:": "bg-gray-200 text-gray-900",
204
+ "focus-visible:": "outline-2 outline-offset-2 outline-accent",
205
+ });
206
+ ```
207
+
208
+ The key `""` groups utilities without adding a variant. Each group shows the
209
+ styles of one state, so readers do not need to collect the prefixed utilities
210
+ from a long string.
211
+
212
+ > **The key "" accepts the same inputs as a variant**
213
+ >
214
+ > The value of `""` accepts only the inputs that a variant group accepts. Write ref attachments,
215
+ > `class` values, custom properties, and bases directly in the `style()` arguments, outside the
216
+ > object. Otherwise the CLI reports
217
+ > [invalid-rule-group-input](../lints/invalid-rule-group-input.md), and the compiler omits the whole
218
+ > group. Ref projections, keyframes uses, and view-transition uses can appear in the group.
219
+
220
+ ## Keep values in the theme
221
+
222
+ Define colors, spacing, and breakpoints as `@theme` tokens, and use the
223
+ utilities that they add. Avoid arbitrary values such as `text-[#abcdef]` and
224
+ `max-[768px]:`. [Design systems](design-systems.md) enables lint
225
+ rules that report them.
226
+
227
+ ## Choose how to define themes
228
+
229
+ When the application has only a light and a dark theme, define each color
230
+ token with `light-dark()`, and let `color-scheme` select the value.
231
+ [Design systems](design-systems.md) shows this setup.
232
+
233
+ When the application can have more themes, `light-dark()` cannot express them.
234
+ Define the tokens as ordinary values, and override them for each theme with an
235
+ attribute selector. Set `color-scheme` in each theme, so that form controls and
236
+ scroll bars match:
237
+
238
+ ```css
239
+ @theme {
240
+ --color-surface: #ffffff;
241
+ --color-foreground: #202b45;
242
+ }
243
+
244
+ [data-theme="dark"] {
245
+ color-scheme: dark;
246
+ --color-surface: #1b263b;
247
+ --color-foreground: #e4edff;
248
+ }
249
+
250
+ [data-theme="sepia"] {
251
+ color-scheme: light;
252
+ --color-surface: #f4ecd8;
253
+ --color-foreground: #433422;
254
+ }
255
+ ```
256
+
257
+ Set `data-theme` on the root element, or on a container to theme part of the
258
+ page. The utilities, such as `bg-surface`, stay the same in every theme.
259
+
260
+ When a theme needs styles beyond its tokens, define a variant for it with
261
+ [@custom-variant](../at-rules/custom-variant.md), and use the variant instead
262
+ of a hand-written selector:
263
+
264
+ ```css
265
+ @custom-variant theme-sepia (&:where([data-theme="sepia"], [data-theme="sepia"] *));
266
+ ```
267
+
268
+ ## Use breakpoints from the theme in JavaScript
269
+
270
+ When JavaScript needs a breakpoint, get its media query with
271
+ [style.media()](../macros/media.md) instead of repeating the value:
272
+
273
+ ```ts
274
+ import { style } from "stillwind/react";
275
+
276
+ const sidebar = window.matchMedia(style.media("sidebar"));
277
+ ```
278
+
279
+ A query such as `matchMedia("(width >= 52.5rem)")` does not follow a later
280
+ change of the breakpoint in the theme. Prefer a variant when CSS alone can make the
281
+ change. [Responsive styles](responsive-styles.md) shows more uses.
282
+
283
+ ## Define utilities with @apply
284
+
285
+ Write the body of a custom utility with `@apply`, and write its conditions as
286
+ variants:
287
+
288
+ ```css
289
+ @utility link {
290
+ @apply text-accent underline-offset-4 hover:underline;
291
+ }
292
+ ```
293
+
294
+ Do not write selectors or media queries by hand. The variants follow your
295
+ theme, and they avoid differences that are easy to miss. For example, the
296
+ `hover:` variant applies only on devices that can hover, while a plain `:hover`
297
+ rule stays active after a tap on a touch screen. Inside a style rule, use
298
+ [@variant](../at-rules/variant.md) instead of a condition.
299
+
300
+ ## Avoid separate CSS
301
+
302
+ Write styles in `style()` calls and custom utilities, not in CSS files with
303
+ your own class names. A custom utility works with every variant, such as
304
+ `hover:link`, and a fixed class name does not. For a reusable condition, define
305
+ a variant with [@custom-variant](../at-rules/custom-variant.md) instead of
306
+ writing its selector in several rules.
307
+
308
+ For HTML that you do not control, such as rendered Markdown, define the styles
309
+ in a custom utility and apply it to the container. You can also use a Tailwind
310
+ plugin such as `@tailwindcss/typography`.
311
+
312
+ ## Run the checks after each change
313
+
314
+ Run `stillwind lint --fix` and `stillwind fmt` after you change styles, and fix
315
+ the remaining findings. Add a suppression comment only for a deliberate
316
+ exception, and give the reason. See
317
+ [Checks in the editor and CI](lint-adoption.md).
318
+
319
+ ## Mistakes that produce no CSS
320
+
321
+ The build succeeds in each of these cases, but the styles do not apply. Run
322
+ `stillwind lint` to find most of them.
323
+
324
+ - A class name outside `style()`, such as in a `className` string, gets no CSS.
325
+ - A utility name that your code builds at runtime, such as `` `bg-${color}-600` ``,
326
+ gets no CSS. Write complete names, such as
327
+ `color === "red" ? "bg-red-600" : "bg-blue-600"`.
328
+ - A `style()` call written directly inside another `style()` call contributes
329
+ nothing. Store the inner style in a variable first.
330
+ - Custom properties in a base do not carry over to the styles that extend it.
331
+ Set them in the `style()` call that is spread onto the element.
332
+ - Classes in the `class` field pass through without generated CSS.
333
+ - A suppression comment hides a finding only. A misspelled utility still
334
+ produces no CSS.
335
+
336
+ The compiler can evaluate the arguments of `style()` in any order, and it can
337
+ skip arguments whose result is not used. Calculate values and perform effects
338
+ before you call `style()`.