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.
- package/AGENTS_TEMPLATE.md +5 -0
- package/LICENSE +21 -0
- package/README.md +166 -0
- package/TAILWINDCSS-MIT-LICENSE +21 -0
- package/css/builtin-metadata/sw-motion-properties.css +186 -0
- package/css/builtin-metadata/tw-legacy-metadata.css +36 -0
- package/css/builtin-metadata/tw-properties.css +944 -0
- package/css/builtin-metadata/tw-registry-metadata.css +52 -0
- package/css/builtin-metadata/tw-relationship-metadata.css +10 -0
- package/css/builtin-utilities/sw-motion-contexts.css +1043 -0
- package/css/builtin-utilities/tw-backgrounds.css +606 -0
- package/css/builtin-utilities/tw-borders.css +954 -0
- package/css/builtin-utilities/tw-effects.css +1209 -0
- package/css/builtin-utilities/tw-flex-grid.css +749 -0
- package/css/builtin-utilities/tw-interactivity.css +680 -0
- package/css/builtin-utilities/tw-layout.css +943 -0
- package/css/builtin-utilities/tw-masks.css +1268 -0
- package/css/builtin-utilities/tw-motion.css +142 -0
- package/css/builtin-utilities/tw-spacing-sizing.css +621 -0
- package/css/builtin-utilities/tw-svg.css +50 -0
- package/css/builtin-utilities/tw-transforms.css +652 -0
- package/css/builtin-utilities/tw-typography.css +720 -0
- package/css/builtin-variants/sw-conditional.css +5 -0
- package/css/builtin-variants/sw-document.css +13 -0
- package/css/builtin-variants/tw-conditional.css +187 -0
- package/css/builtin-variants/tw-dynamic-selector.css +49 -0
- package/css/builtin-variants/tw-relationship.css +41 -0
- package/css/builtin-variants/tw-state.css +159 -0
- package/css/builtin-variants/tw-structural.css +121 -0
- package/css/builtins.css +111 -0
- package/css/preflight.css +401 -0
- package/css/templates.css +40 -0
- package/css/theme.css +546 -0
- package/css/utilities.css +9 -0
- package/dist/class-object-D24FFYqO.js +6 -0
- package/dist/class-object-D24FFYqO.js.map +1 -0
- package/dist/class-object-D7ZGJOf_.d.ts +9 -0
- package/dist/class-string-CQHnc9GN.d.ts +9 -0
- package/dist/class-string-Db8-oI4q.js +6 -0
- package/dist/class-string-Db8-oI4q.js.map +1 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +2 -0
- package/dist/css.d.ts +100 -0
- package/dist/css.js +143 -0
- package/dist/css.js.map +1 -0
- package/dist/cva-BwX07CFw.js +204 -0
- package/dist/cva-BwX07CFw.js.map +1 -0
- package/dist/cva-DSpDNBYi.d.ts +9 -0
- package/dist/development-DttPQc71.d.ts +27 -0
- package/dist/development-J-JCSIm0.js +111 -0
- package/dist/development-J-JCSIm0.js.map +1 -0
- package/dist/frameworks/alpine.d.ts +20 -0
- package/dist/frameworks/alpine.js +18 -0
- package/dist/frameworks/alpine.js.map +1 -0
- package/dist/frameworks/astro.d.ts +3 -0
- package/dist/frameworks/astro.js +1 -0
- package/dist/frameworks/lit.d.ts +21 -0
- package/dist/frameworks/lit.js +38 -0
- package/dist/frameworks/lit.js.map +1 -0
- package/dist/frameworks/preact.d.ts +3 -0
- package/dist/frameworks/preact.js +1 -0
- package/dist/frameworks/qwik.d.ts +3 -0
- package/dist/frameworks/qwik.js +1 -0
- package/dist/frameworks/react.d.ts +10 -0
- package/dist/frameworks/react.js +6 -0
- package/dist/frameworks/react.js.map +1 -0
- package/dist/frameworks/solid.d.ts +3 -0
- package/dist/frameworks/solid.js +1 -0
- package/dist/frameworks/svelte.d.ts +3 -0
- package/dist/frameworks/svelte.js +1 -0
- package/dist/frameworks/vanilla.d.ts +27 -0
- package/dist/frameworks/vanilla.js +3 -0
- package/dist/frameworks/vue.d.ts +3 -0
- package/dist/frameworks/vue.js +1 -0
- package/dist/index-RwVFpxhE.d.ts +815 -0
- package/dist/macro/index.d.ts +2 -0
- package/dist/macro/index.js +1 -0
- package/dist/module-css.d.ts +30 -0
- package/dist/module-css.js +23 -0
- package/dist/module-css.js.map +1 -0
- package/dist/runtime/class-name-object-development.d.ts +10 -0
- package/dist/runtime/class-name-object-development.js +18 -0
- package/dist/runtime/class-name-object-development.js.map +1 -0
- package/dist/runtime/class-name-object.d.ts +16 -0
- package/dist/runtime/class-name-object.js +31 -0
- package/dist/runtime/class-name-object.js.map +1 -0
- package/dist/runtime/class-object-development.d.ts +10 -0
- package/dist/runtime/class-object-development.js +18 -0
- package/dist/runtime/class-object-development.js.map +1 -0
- package/dist/runtime/class-object.d.ts +16 -0
- package/dist/runtime/class-object.js +31 -0
- package/dist/runtime/class-object.js.map +1 -0
- package/dist/runtime/class-string-development.d.ts +10 -0
- package/dist/runtime/class-string-development.js +18 -0
- package/dist/runtime/class-string-development.js.map +1 -0
- package/dist/runtime/class-string.d.ts +16 -0
- package/dist/runtime/class-string.js +31 -0
- package/dist/runtime/class-string.js.map +1 -0
- package/dist/shared-B9IQXU6P.d.ts +32 -0
- package/dist/style-BV4ctkni.js +78 -0
- package/dist/style-BV4ctkni.js.map +1 -0
- package/dist/style-fTQbsVWZ.js +41 -0
- package/dist/style-fTQbsVWZ.js.map +1 -0
- package/docs/agents.md +76 -0
- package/docs/at-rules/apply.md +93 -0
- package/docs/at-rules/custom-variant.md +127 -0
- package/docs/at-rules/index.md +75 -0
- package/docs/at-rules/plugin.md +71 -0
- package/docs/at-rules/registry-directives.md +181 -0
- package/docs/at-rules/slot.md +58 -0
- package/docs/at-rules/stillwind-css-template.md +126 -0
- package/docs/at-rules/stillwind-property.md +133 -0
- package/docs/at-rules/stillwind-registry.md +115 -0
- package/docs/at-rules/stillwind-require-properties.md +91 -0
- package/docs/at-rules/stillwind-slot.md +85 -0
- package/docs/at-rules/stillwind-undef-arbitrary-property.md +75 -0
- package/docs/at-rules/stillwind-undef-utility.md +87 -0
- package/docs/at-rules/stillwind-undef-variant.md +55 -0
- package/docs/at-rules/theme.md +304 -0
- package/docs/at-rules/utility.md +286 -0
- package/docs/at-rules/variant.md +91 -0
- package/docs/concepts/css-ordering.md +245 -0
- package/docs/concepts/how-styles-compile.md +132 -0
- package/docs/configuration.md +298 -0
- package/docs/errors/SW01001.md +51 -0
- package/docs/errors/SW01002.md +52 -0
- package/docs/errors/SW01003.md +69 -0
- package/docs/errors/SW02001.md +23 -0
- package/docs/errors/SW02002.md +51 -0
- package/docs/errors/SW03001.md +71 -0
- package/docs/errors/SW03002.md +79 -0
- package/docs/errors/SW03003.md +36 -0
- package/docs/errors/SW10001.md +34 -0
- package/docs/errors/SW10002.md +36 -0
- package/docs/errors/SW10003.md +30 -0
- package/docs/errors/SW10004.md +39 -0
- package/docs/errors/SW10005.md +35 -0
- package/docs/errors/SW11001.md +37 -0
- package/docs/errors/SW11002.md +65 -0
- package/docs/errors/SW11003.md +20 -0
- package/docs/errors/SW12001.md +43 -0
- package/docs/errors/SW12002.md +42 -0
- package/docs/errors/SW13001.md +35 -0
- package/docs/errors/SW13002.md +33 -0
- package/docs/errors/SW13003.md +18 -0
- package/docs/errors/SW13004.md +45 -0
- package/docs/errors/SW14001.md +44 -0
- package/docs/errors/SW14002.md +47 -0
- package/docs/errors/SW14003.md +38 -0
- package/docs/errors/SW14004.md +48 -0
- package/docs/errors/SW14005.md +51 -0
- package/docs/errors/SW14006.md +19 -0
- package/docs/errors/SW14007.md +35 -0
- package/docs/errors/SW14008.md +41 -0
- package/docs/errors/SW15001.md +18 -0
- package/docs/errors/SW15002.md +19 -0
- package/docs/errors/SW15003.md +16 -0
- package/docs/errors/SW30001.md +21 -0
- package/docs/errors/SW30002.md +18 -0
- package/docs/errors/SW30003.md +17 -0
- package/docs/errors/SW30004.md +18 -0
- package/docs/errors/SW31001.md +20 -0
- package/docs/errors/SW31002.md +17 -0
- package/docs/errors/SW31003.md +18 -0
- package/docs/errors/SW31004.md +20 -0
- package/docs/errors/SW31005.md +18 -0
- package/docs/errors/SW31006.md +17 -0
- package/docs/errors/SW31007.md +18 -0
- package/docs/errors/SW31008.md +16 -0
- package/docs/errors/SW31009.md +18 -0
- package/docs/errors/SW31010.md +16 -0
- package/docs/errors/SW31011.md +17 -0
- package/docs/errors/SW32001.md +18 -0
- package/docs/errors/SW32002.md +45 -0
- package/docs/errors/SW32003.md +43 -0
- package/docs/errors/SW32004.md +17 -0
- package/docs/errors/SW32005.md +40 -0
- package/docs/errors/SW32006.md +18 -0
- package/docs/errors/SW32007.md +20 -0
- package/docs/errors/SW33001.md +17 -0
- package/docs/errors/SW33002.md +17 -0
- package/docs/errors/SW33003.md +17 -0
- package/docs/errors/SW33004.md +17 -0
- package/docs/errors/SW33005.md +20 -0
- package/docs/errors/SW34001.md +18 -0
- package/docs/errors/SW34002.md +17 -0
- package/docs/errors/SW34003.md +18 -0
- package/docs/errors/SW90001.md +17 -0
- package/docs/errors/SW90002.md +18 -0
- package/docs/errors/SW90003.md +17 -0
- package/docs/errors/SW90004.md +17 -0
- package/docs/errors/SW90005.md +16 -0
- package/docs/errors/SW90006.md +17 -0
- package/docs/errors/SW90007.md +17 -0
- package/docs/errors/SW90008.md +17 -0
- package/docs/errors/index.md +125 -0
- package/docs/guides/animations.md +73 -0
- package/docs/guides/design-systems.md +119 -0
- package/docs/guides/element-relationships.md +136 -0
- package/docs/guides/lint-adoption.md +128 -0
- package/docs/guides/migrating-from-css.md +126 -0
- package/docs/guides/migrating-from-tailwind.md +179 -0
- package/docs/guides/recommended-practices.md +338 -0
- package/docs/guides/responsive-styles.md +103 -0
- package/docs/guides/reusable-styles.md +110 -0
- package/docs/guides/style.md +181 -0
- package/docs/guides/tailwind-compatibility.md +126 -0
- package/docs/guides/view-transitions.md +84 -0
- package/docs/guides/web-components.md +216 -0
- package/docs/index.md +136 -0
- package/docs/integrations.md +190 -0
- package/docs/lints/ambiguous-style-base-order.md +50 -0
- package/docs/lints/bypassed-undefinition.md +50 -0
- package/docs/lints/clamped-value.md +44 -0
- package/docs/lints/conflicting-provider-properties.md +47 -0
- package/docs/lints/conflicting-utilities.md +55 -0
- package/docs/lints/document-scoped-selector.md +45 -0
- package/docs/lints/duplicate-definition.md +44 -0
- package/docs/lints/duplicate-utility.md +44 -0
- package/docs/lints/duplicate-view-transition-name.md +45 -0
- package/docs/lints/ignored-definition-condition.md +51 -0
- package/docs/lints/ignored-tailwind-feature.md +62 -0
- package/docs/lints/incompatible-property-value.md +60 -0
- package/docs/lints/incompatible-theme-value.md +46 -0
- package/docs/lints/index.md +140 -0
- package/docs/lints/ineffective-anchor-scope.md +46 -0
- package/docs/lints/interfering-imported-style-base.md +57 -0
- package/docs/lints/invalid-animation-option.md +47 -0
- package/docs/lints/invalid-css-directive.md +43 -0
- package/docs/lints/invalid-css-import.md +43 -0
- package/docs/lints/invalid-css-input.md +45 -0
- package/docs/lints/invalid-cva-config.md +46 -0
- package/docs/lints/invalid-cva-input.md +50 -0
- package/docs/lints/invalid-keyframes-definition.md +47 -0
- package/docs/lints/invalid-keyframes-use.md +47 -0
- package/docs/lints/invalid-keyframes-variant.md +48 -0
- package/docs/lints/invalid-lint-suppression.md +47 -0
- package/docs/lints/invalid-marker-use.md +53 -0
- package/docs/lints/invalid-media-query.md +52 -0
- package/docs/lints/invalid-ref-input.md +49 -0
- package/docs/lints/invalid-rule-group-input.md +58 -0
- package/docs/lints/invalid-runtime-condition.md +67 -0
- package/docs/lints/invalid-style-composition.md +52 -0
- package/docs/lints/invalid-style-input.md +47 -0
- package/docs/lints/invalid-theme-reference.md +52 -0
- package/docs/lints/invalid-utility.md +44 -0
- package/docs/lints/invalid-variant.md +45 -0
- package/docs/lints/invalid-view-transition-definition.md +46 -0
- package/docs/lints/invalid-view-transition-use.md +46 -0
- package/docs/lints/invalid-view-transition-variant.md +51 -0
- package/docs/lints/mismatched-framework-import.md +47 -0
- package/docs/lints/missing-document-target.md +44 -0
- package/docs/lints/missing-ref-attachment.md +44 -0
- package/docs/lints/missing-view-transition-name.md +46 -0
- package/docs/lints/mutating-macro-argument.md +48 -0
- package/docs/lints/no-arbitrary-breakpoints.md +50 -0
- package/docs/lints/no-arbitrary-colors.md +51 -0
- package/docs/lints/no-arbitrary-spacing.md +57 -0
- package/docs/lints/no-class-property.md +58 -0
- package/docs/lints/no-important.md +50 -0
- package/docs/lints/no-restricted-declarations.md +76 -0
- package/docs/lints/no-restricted-length-units.md +73 -0
- package/docs/lints/no-restricted-theme-tokens.md +73 -0
- package/docs/lints/no-restricted-utilities.md +73 -0
- package/docs/lints/prefer-canonical-utilities.md +69 -0
- package/docs/lints/prefer-direct-styling.md +47 -0
- package/docs/lints/prefer-explicit-nesting-selector.md +42 -0
- package/docs/lints/prefer-logical-properties.md +49 -0
- package/docs/lints/prefer-sorted-utilities.md +46 -0
- package/docs/lints/prefer-typed-relationships.md +48 -0
- package/docs/lints/prefer-typed-variables.md +43 -0
- package/docs/lints/prefer-variant-directive.md +59 -0
- package/docs/lints/redundant-variant.md +50 -0
- package/docs/lints/repeated-nesting-selector.md +59 -0
- package/docs/lints/runtime-condition-requires-css-if.md +59 -0
- package/docs/lints/split-view-transition-class.md +47 -0
- package/docs/lints/suspending-macro-argument.md +46 -0
- package/docs/lints/unknown-utility.md +47 -0
- package/docs/lints/unknown-variant.md +42 -0
- package/docs/lints/unsatisfiable-variants.md +42 -0
- package/docs/lints/unused-lint-suppression.md +57 -0
- package/docs/lints/unverified-style-base.md +64 -0
- package/docs/macros/anchor-scope.md +90 -0
- package/docs/macros/css.md +68 -0
- package/docs/macros/cva.md +153 -0
- package/docs/macros/index.md +30 -0
- package/docs/macros/keyframes.md +98 -0
- package/docs/macros/media.md +65 -0
- package/docs/macros/ref/as-anchor.md +70 -0
- package/docs/macros/ref/as-container.md +64 -0
- package/docs/macros/ref/at.md +68 -0
- package/docs/macros/ref/condition.md +86 -0
- package/docs/macros/ref/in.md +81 -0
- package/docs/macros/ref/index.md +115 -0
- package/docs/macros/ref/position-anchor.md +64 -0
- package/docs/macros/style.md +185 -0
- package/docs/macros/view-transition.md +159 -0
- package/docs/utilities.md +35 -0
- package/docs/why.md +144 -0
- package/index.css +7 -0
- package/package.json +135 -8
- package/skills/migrate-to-stillwind/SKILL.md +81 -0
- package/skills/setup-stillwind/SKILL.md +51 -0
- package/skills/stillwind/SKILL.md +54 -0
- 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()`.
|