@cwcss/crosswind 0.2.0 → 0.2.1
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/README.md +562 -18
- package/dist/bin/cli.js +1921 -2698
- package/dist/build.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/generator.d.ts +4 -24
- package/dist/index.d.ts +1 -1
- package/dist/parser.d.ts +1 -1
- package/dist/plugin.d.ts +1 -1
- package/dist/preflight-forms.d.ts +2 -1
- package/dist/preflight.d.ts +2 -1
- package/dist/rules.d.ts +13 -1
- package/dist/scanner.d.ts +1 -4
- package/dist/src/index.js +1916 -2689
- package/dist/types.d.ts +11 -2
- package/package.json +1 -1
- package/dist/rules-advanced.d.ts +0 -27
- package/dist/rules-effects.d.ts +0 -25
- package/dist/rules-forms.d.ts +0 -7
- package/dist/rules-grid.d.ts +0 -13
- package/dist/rules-interactivity.d.ts +0 -41
- package/dist/rules-layout.d.ts +0 -26
- package/dist/rules-transforms.d.ts +0 -33
- package/dist/rules-typography.d.ts +0 -41
- package/dist/transformer-compile-class.d.ts +0 -37
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @cwcss/crosswind
|
|
2
2
|
|
|
3
|
-
A performant
|
|
3
|
+
A performant utility-first CSS engine, compatible with Tailwind CSS. Built with TypeScript and optimized for Bun.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,16 +8,32 @@ A performant Utility-First CSS framework, similar to Tailwind or UnoCSS. Built w
|
|
|
8
8
|
bun add @cwcss/crosswind
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Programmatic API
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { CSSGenerator, defaultConfig } from '@cwcss/crosswind'
|
|
17
|
+
|
|
18
|
+
const gen = new CSSGenerator(defaultConfig)
|
|
19
|
+
gen.generate('flex')
|
|
20
|
+
gen.generate('items-center')
|
|
21
|
+
gen.generate('gap-4')
|
|
22
|
+
gen.generate('p-8')
|
|
23
|
+
gen.generate('bg-blue-500')
|
|
24
|
+
gen.generate('text-white')
|
|
25
|
+
gen.generate('rounded-lg')
|
|
26
|
+
gen.generate('hover:bg-blue-600')
|
|
27
|
+
gen.generate('dark:bg-gray-900')
|
|
28
|
+
|
|
29
|
+
const css = gen.toCSS(true) // true = include preflight
|
|
13
30
|
```
|
|
14
31
|
|
|
15
|
-
|
|
32
|
+
### Build API
|
|
16
33
|
|
|
17
34
|
```typescript
|
|
18
|
-
import { build
|
|
35
|
+
import { build } from '@cwcss/crosswind'
|
|
19
36
|
|
|
20
|
-
// Build CSS from your content files
|
|
21
37
|
const result = await build({
|
|
22
38
|
content: ['./src/**/*.html', './src/**/*.tsx'],
|
|
23
39
|
output: './dist/styles.css',
|
|
@@ -28,24 +44,552 @@ const result = await build({
|
|
|
28
44
|
### CLI
|
|
29
45
|
|
|
30
46
|
```bash
|
|
31
|
-
# Run the crosswind CLI
|
|
32
47
|
crosswind build
|
|
33
48
|
crosswind build --watch
|
|
34
49
|
crosswind build --minify
|
|
35
50
|
```
|
|
36
51
|
|
|
37
|
-
##
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
Create a `crosswind.config.ts` in your project root:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import type { CrosswindConfig } from '@cwcss/crosswind'
|
|
58
|
+
|
|
59
|
+
export default {
|
|
60
|
+
content: ['./src/**/*.{html,tsx,stx}'],
|
|
61
|
+
output: './dist/styles.css',
|
|
62
|
+
minify: false,
|
|
63
|
+
|
|
64
|
+
theme: {
|
|
65
|
+
extend: {
|
|
66
|
+
colors: {
|
|
67
|
+
brand: {
|
|
68
|
+
50: '#eff6ff',
|
|
69
|
+
500: '#3b82f6',
|
|
70
|
+
900: '#1e3a5a',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
spacing: {
|
|
74
|
+
'18': '4.5rem',
|
|
75
|
+
'112': '28rem',
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
safelist: ['bg-brand-500', 'text-white'],
|
|
81
|
+
blocklist: ['opacity-0'],
|
|
82
|
+
} satisfies Partial<CrosswindConfig>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Theme
|
|
86
|
+
|
|
87
|
+
The default theme includes Tailwind-compatible values for:
|
|
88
|
+
|
|
89
|
+
- **colors** - Full color palette (slate, gray, zinc, red, orange, yellow, green, blue, indigo, purple, pink, etc.) with 50-950 shades in oklch
|
|
90
|
+
- **spacing** - 0 through 96, plus `px` (1px), fractional values
|
|
91
|
+
- **fontSize** - xs through 9xl with line-height pairs
|
|
92
|
+
- **fontFamily** - sans, serif, mono
|
|
93
|
+
- **screens** - sm (640px), md (768px), lg (1024px), xl (1280px), 2xl (1536px)
|
|
94
|
+
- **borderRadius** - none, sm, DEFAULT, md, lg, xl, 2xl, 3xl, full
|
|
95
|
+
- **boxShadow** - sm, DEFAULT, md, lg, xl, 2xl, inner, none
|
|
96
|
+
|
|
97
|
+
All theme values can be extended or overridden via `theme.extend`.
|
|
98
|
+
|
|
99
|
+
## Utilities
|
|
100
|
+
|
|
101
|
+
### Layout
|
|
102
|
+
|
|
103
|
+
| Utility | CSS |
|
|
104
|
+
|---------|-----|
|
|
105
|
+
| `block`, `inline-block`, `flex`, `grid`, `hidden` | `display: *` |
|
|
106
|
+
| `static`, `fixed`, `absolute`, `relative`, `sticky` | `position: *` |
|
|
107
|
+
| `top-*`, `right-*`, `bottom-*`, `left-*`, `inset-*` | Positioning |
|
|
108
|
+
| `z-*` | `z-index` |
|
|
109
|
+
| `overflow-*`, `overflow-x-*`, `overflow-y-*` | Overflow |
|
|
110
|
+
| `float-*`, `clear-*` | Float & clear (includes logical `start`/`end`) |
|
|
111
|
+
| `isolate`, `isolation-auto` | Isolation |
|
|
112
|
+
| `object-cover`, `object-contain`, `object-fill`, `object-none` | Object fit |
|
|
113
|
+
| `object-top`, `object-center`, `object-bottom`, etc. | Object position |
|
|
114
|
+
| `columns-*` | Multi-column layout |
|
|
115
|
+
| `break-before-*`, `break-after-*`, `break-inside-*` | Break behavior |
|
|
116
|
+
| `box-border`, `box-content` | Box sizing |
|
|
117
|
+
| `aspect-auto`, `aspect-square`, `aspect-video` | Aspect ratio |
|
|
118
|
+
| `visible`, `invisible`, `collapse` | Visibility |
|
|
119
|
+
|
|
120
|
+
### Flexbox
|
|
121
|
+
|
|
122
|
+
| Utility | CSS |
|
|
123
|
+
|---------|-----|
|
|
124
|
+
| `flex-row`, `flex-col`, `flex-row-reverse`, `flex-col-reverse` | Direction |
|
|
125
|
+
| `flex-wrap`, `flex-nowrap`, `flex-wrap-reverse` | Wrap |
|
|
126
|
+
| `flex-1`, `flex-auto`, `flex-initial`, `flex-none` | Flex shorthand |
|
|
127
|
+
| `grow`, `grow-0`, `shrink`, `shrink-0` | Grow & shrink |
|
|
128
|
+
| `basis-*` | Flex basis (supports fractions: `basis-1/2`) |
|
|
129
|
+
| `justify-*`, `items-*`, `self-*` | Alignment |
|
|
130
|
+
| `justify-items-*`, `justify-self-*` | Justify items/self |
|
|
131
|
+
| `content-*` | Align content |
|
|
132
|
+
| `order-*`, `order-first`, `order-last`, `order-none` | Order |
|
|
133
|
+
|
|
134
|
+
### Grid
|
|
135
|
+
|
|
136
|
+
| Utility | CSS |
|
|
137
|
+
|---------|-----|
|
|
138
|
+
| `grid-cols-*`, `grid-rows-*` | Template columns/rows (1-12, none, subgrid) |
|
|
139
|
+
| `col-span-*`, `col-start-*`, `col-end-*` | Column placement |
|
|
140
|
+
| `row-span-*`, `row-start-*`, `row-end-*` | Row placement |
|
|
141
|
+
| `grid-flow-row`, `grid-flow-col`, `grid-flow-dense` | Auto flow |
|
|
142
|
+
| `auto-cols-*`, `auto-rows-*` | Auto columns/rows |
|
|
143
|
+
| `gap-*`, `gap-x-*`, `gap-y-*` | Gap |
|
|
144
|
+
| `place-content-*`, `place-items-*`, `place-self-*` | Place shortcuts |
|
|
145
|
+
|
|
146
|
+
Arbitrary grid templates use underscore-to-space conversion:
|
|
147
|
+
|
|
148
|
+
```html
|
|
149
|
+
<div class="grid grid-cols-[120px_1fr_200px]">
|
|
150
|
+
<!-- grid-template-columns: 120px 1fr 200px -->
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Spacing
|
|
154
|
+
|
|
155
|
+
| Utility | CSS |
|
|
156
|
+
|---------|-----|
|
|
157
|
+
| `p-*`, `px-*`, `py-*`, `pt-*`, `pr-*`, `pb-*`, `pl-*` | Padding |
|
|
158
|
+
| `ps-*`, `pe-*` | Padding inline start/end (logical) |
|
|
159
|
+
| `m-*`, `mx-*`, `my-*`, `mt-*`, `mr-*`, `mb-*`, `ml-*` | Margin |
|
|
160
|
+
| `ms-*`, `me-*` | Margin inline start/end (logical) |
|
|
161
|
+
| `space-x-*`, `space-y-*` | Space between children |
|
|
162
|
+
|
|
163
|
+
Negative values supported: `-m-4`, `-translate-x-1`.
|
|
164
|
+
|
|
165
|
+
### Sizing
|
|
166
|
+
|
|
167
|
+
| Utility | CSS |
|
|
168
|
+
|---------|-----|
|
|
169
|
+
| `w-*`, `h-*` | Width & height |
|
|
170
|
+
| `size-*` | Width + height shorthand |
|
|
171
|
+
| `min-w-*`, `max-w-*`, `min-h-*`, `max-h-*` | Min/max sizing |
|
|
172
|
+
|
|
173
|
+
Values: spacing scale, `auto`, `full` (100%), `screen` (100vw/vh), `min`, `max`, `fit`, fractions (`w-1/2`).
|
|
174
|
+
|
|
175
|
+
### Colors
|
|
176
|
+
|
|
177
|
+
All color utilities support opacity modifiers:
|
|
178
|
+
|
|
179
|
+
```html
|
|
180
|
+
<!-- Integer opacity (0-100 scale) -->
|
|
181
|
+
<div class="bg-blue-500/50"> <!-- 50% opacity -->
|
|
182
|
+
<div class="text-white/75"> <!-- 75% opacity -->
|
|
183
|
+
<div class="border-black/10"> <!-- 10% opacity -->
|
|
184
|
+
|
|
185
|
+
<!-- Arbitrary opacity (0-1 scale) -->
|
|
186
|
+
<div class="bg-white/[0.04]"> <!-- 4% opacity -->
|
|
187
|
+
<div class="text-black/[0.87]"> <!-- 87% opacity -->
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
| Utility | CSS |
|
|
191
|
+
|---------|-----|
|
|
192
|
+
| `bg-*` | Background color |
|
|
193
|
+
| `text-*` | Text color |
|
|
194
|
+
| `border-*` | Border color |
|
|
195
|
+
| `ring-*` | Ring color |
|
|
196
|
+
| `divide-*` | Divide color (supports opacity: `divide-white/10`) |
|
|
197
|
+
| `placeholder-*` | Placeholder color |
|
|
198
|
+
| `accent-*` | Accent color |
|
|
199
|
+
| `caret-*` | Caret color |
|
|
200
|
+
| `fill-*`, `stroke-*` | SVG fill & stroke |
|
|
201
|
+
|
|
202
|
+
Special values: `current` (currentColor), `transparent`, `inherit`, `white`, `black`.
|
|
203
|
+
|
|
204
|
+
### Typography
|
|
205
|
+
|
|
206
|
+
| Utility | CSS |
|
|
207
|
+
|---------|-----|
|
|
208
|
+
| `text-xs` through `text-9xl` | Font size |
|
|
209
|
+
| `font-thin` through `font-black` | Font weight |
|
|
210
|
+
| `font-sans`, `font-serif`, `font-mono` | Font family |
|
|
211
|
+
| `italic`, `not-italic` | Font style |
|
|
212
|
+
| `tracking-*` | Letter spacing |
|
|
213
|
+
| `leading-*` | Line height |
|
|
214
|
+
| `text-left`, `text-center`, `text-right`, `text-justify` | Alignment |
|
|
215
|
+
| `uppercase`, `lowercase`, `capitalize`, `normal-case` | Text transform |
|
|
216
|
+
| `underline`, `overline`, `line-through`, `no-underline` | Decoration |
|
|
217
|
+
| `decoration-*` | Decoration style, color, thickness |
|
|
218
|
+
| `truncate`, `text-ellipsis`, `text-clip` | Text overflow |
|
|
219
|
+
| `text-wrap`, `text-nowrap`, `text-balance`, `text-pretty` | Text wrap |
|
|
220
|
+
| `line-clamp-*` | Line clamp |
|
|
221
|
+
| `indent-*` | Text indent |
|
|
222
|
+
| `antialiased`, `subpixel-antialiased` | Font smoothing |
|
|
223
|
+
| `tabular-nums`, `lining-nums`, `oldstyle-nums`, etc. | Font variant numeric |
|
|
224
|
+
| `hyphens-none`, `hyphens-manual`, `hyphens-auto` | Hyphens |
|
|
225
|
+
| `whitespace-*` | White space |
|
|
226
|
+
| `break-normal`, `break-words`, `break-all` | Word break |
|
|
227
|
+
|
|
228
|
+
### Borders
|
|
229
|
+
|
|
230
|
+
| Utility | CSS |
|
|
231
|
+
|---------|-----|
|
|
232
|
+
| `border`, `border-0`, `border-2`, `border-4`, `border-8` | Border width |
|
|
233
|
+
| `border-t`, `border-r`, `border-b`, `border-l` | Side borders |
|
|
234
|
+
| `border-s`, `border-e` | Logical side borders (inline-start/end) |
|
|
235
|
+
| `border-x`, `border-y` | Axis borders |
|
|
236
|
+
| `border-solid`, `border-dashed`, `border-dotted`, `border-double`, `border-none` | Style |
|
|
237
|
+
| `rounded-*` | Border radius |
|
|
238
|
+
| `rounded-s-*`, `rounded-e-*` | Logical border radius |
|
|
239
|
+
| `rounded-ss-*`, `rounded-se-*`, `rounded-es-*`, `rounded-ee-*` | Corner-specific logical radius |
|
|
240
|
+
| `outline-*` | Outline width, style, color |
|
|
241
|
+
| `outline-offset-*` | Outline offset |
|
|
242
|
+
| `ring-*`, `ring-offset-*` | Ring |
|
|
243
|
+
| `divide-x`, `divide-y` | Divide width |
|
|
244
|
+
| `divide-*` | Divide color, style, opacity |
|
|
245
|
+
|
|
246
|
+
### Effects & Filters
|
|
247
|
+
|
|
248
|
+
| Utility | CSS |
|
|
249
|
+
|---------|-----|
|
|
250
|
+
| `shadow-*` | Box shadow |
|
|
251
|
+
| `shadow-{color}` | Shadow color |
|
|
252
|
+
| `opacity-*` | Opacity (0-100) |
|
|
253
|
+
| `mix-blend-*` | Mix blend mode |
|
|
254
|
+
| `bg-blend-*` | Background blend mode |
|
|
255
|
+
| `blur-*`, `brightness-*`, `contrast-*`, `grayscale-*` | Filters |
|
|
256
|
+
| `invert-*`, `saturate-*`, `sepia-*`, `hue-rotate-*` | Filters |
|
|
257
|
+
| `drop-shadow-*` | Drop shadow filter |
|
|
258
|
+
| `backdrop-blur-*`, `backdrop-brightness-*`, etc. | Backdrop filters |
|
|
259
|
+
|
|
260
|
+
### Backgrounds & Gradients
|
|
261
|
+
|
|
262
|
+
| Utility | CSS |
|
|
263
|
+
|---------|-----|
|
|
264
|
+
| `bg-fixed`, `bg-local`, `bg-scroll` | Background attachment |
|
|
265
|
+
| `bg-clip-border`, `bg-clip-padding`, `bg-clip-content`, `bg-clip-text` | Background clip |
|
|
266
|
+
| `bg-top`, `bg-center`, `bg-bottom`, etc. | Background position |
|
|
267
|
+
| `bg-repeat`, `bg-no-repeat`, `bg-repeat-x`, `bg-repeat-y` | Background repeat |
|
|
268
|
+
| `bg-auto`, `bg-cover`, `bg-contain` | Background size |
|
|
269
|
+
|
|
270
|
+
**Linear gradients:**
|
|
271
|
+
|
|
272
|
+
```html
|
|
273
|
+
<div class="bg-gradient-to-r from-blue-500 via-purple-500 to-pink-500">
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Directions: `bg-gradient-to-{t,tr,r,br,b,bl,l,tl}`.
|
|
277
|
+
|
|
278
|
+
**Radial gradients:**
|
|
279
|
+
|
|
280
|
+
```html
|
|
281
|
+
<div class="bg-radial from-white to-blue-500">
|
|
282
|
+
<div class="bg-radial-at-t from-yellow-200 to-orange-500">
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Positions: `bg-radial-at-{t,tr,r,br,b,bl,l,tl,c}`.
|
|
286
|
+
|
|
287
|
+
**Conic gradients:**
|
|
288
|
+
|
|
289
|
+
```html
|
|
290
|
+
<div class="bg-conic from-red-500 via-yellow-500 to-green-500">
|
|
291
|
+
<div class="bg-conic-from-r from-blue-500 to-purple-500">
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Starting angles: `bg-conic-from-{t,tr,r,br,b,bl,l,tl}`.
|
|
295
|
+
|
|
296
|
+
### Transforms & Transitions
|
|
297
|
+
|
|
298
|
+
| Utility | CSS |
|
|
299
|
+
|---------|-----|
|
|
300
|
+
| `scale-*`, `scale-x-*`, `scale-y-*` | Scale |
|
|
301
|
+
| `rotate-*` | Rotate |
|
|
302
|
+
| `translate-x-*`, `translate-y-*` | Translate |
|
|
303
|
+
| `skew-x-*`, `skew-y-*` | Skew |
|
|
304
|
+
| `origin-*` | Transform origin |
|
|
305
|
+
| `transition`, `transition-all`, `transition-colors`, `transition-opacity`, `transition-shadow`, `transition-transform` | Transition property |
|
|
306
|
+
| `duration-*` | Transition duration |
|
|
307
|
+
| `ease-linear`, `ease-in`, `ease-out`, `ease-in-out` | Timing function |
|
|
308
|
+
| `delay-*` | Transition delay |
|
|
309
|
+
| `animate-spin`, `animate-ping`, `animate-pulse`, `animate-bounce`, `animate-none` | Animation |
|
|
310
|
+
| `perspective-*` | 3D perspective |
|
|
311
|
+
| `backface-visible`, `backface-hidden` | Backface visibility |
|
|
312
|
+
|
|
313
|
+
### Interactivity
|
|
314
|
+
|
|
315
|
+
| Utility | CSS |
|
|
316
|
+
|---------|-----|
|
|
317
|
+
| `cursor-*` | Cursor style |
|
|
318
|
+
| `pointer-events-none`, `pointer-events-auto` | Pointer events |
|
|
319
|
+
| `resize`, `resize-x`, `resize-y`, `resize-none` | Resize |
|
|
320
|
+
| `select-none`, `select-text`, `select-all`, `select-auto` | User select |
|
|
321
|
+
| `scroll-auto`, `scroll-smooth` | Scroll behavior |
|
|
322
|
+
| `scroll-m-*`, `scroll-p-*` | Scroll margin/padding |
|
|
323
|
+
| `snap-x`, `snap-y`, `snap-both`, `snap-mandatory`, `snap-proximity` | Scroll snap |
|
|
324
|
+
| `snap-start`, `snap-end`, `snap-center`, `snap-align-none` | Snap align |
|
|
325
|
+
| `touch-auto`, `touch-none`, `touch-manipulation`, `touch-pan-*` | Touch action |
|
|
326
|
+
| `will-change-auto`, `will-change-scroll`, `will-change-contents`, `will-change-transform` | Will change |
|
|
327
|
+
| `appearance-none`, `appearance-auto` | Appearance |
|
|
328
|
+
| `scrollbar-auto`, `scrollbar-thin`, `scrollbar-none` | Scrollbar width |
|
|
329
|
+
|
|
330
|
+
### Content
|
|
331
|
+
|
|
332
|
+
```html
|
|
333
|
+
<div class="before:content-['*'] before:text-red-500">Required</div>
|
|
334
|
+
<div class="before:content-empty before:block before:h-4"></div>
|
|
335
|
+
<div class="after:content-[attr(data-count)]"></div>
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
| Utility | CSS |
|
|
339
|
+
|---------|-----|
|
|
340
|
+
| `content-none` | `content: none` |
|
|
341
|
+
| `content-empty` | `content: ""` |
|
|
342
|
+
| `content-['text']` | `content: 'text'` |
|
|
343
|
+
| `content-[attr(data-*)]` | `content: attr(data-*)` |
|
|
344
|
+
|
|
345
|
+
### SVG
|
|
346
|
+
|
|
347
|
+
| Utility | CSS |
|
|
348
|
+
|---------|-----|
|
|
349
|
+
| `fill-none`, `fill-current`, `fill-{color}` | Fill |
|
|
350
|
+
| `stroke-none`, `stroke-current`, `stroke-{color}` | Stroke color |
|
|
351
|
+
| `stroke-0`, `stroke-1`, `stroke-2` | Stroke width |
|
|
352
|
+
|
|
353
|
+
### Tables
|
|
354
|
+
|
|
355
|
+
| Utility | CSS |
|
|
356
|
+
|---------|-----|
|
|
357
|
+
| `border-collapse`, `border-separate` | Border collapse |
|
|
358
|
+
| `border-spacing-*` | Border spacing |
|
|
359
|
+
| `table-auto`, `table-fixed` | Table layout |
|
|
360
|
+
| `caption-top`, `caption-bottom` | Caption side |
|
|
361
|
+
|
|
362
|
+
## Variants
|
|
363
|
+
|
|
364
|
+
### Pseudo-class Variants
|
|
365
|
+
|
|
366
|
+
```html
|
|
367
|
+
<div class="hover:bg-blue-600 focus:ring-2 active:scale-95">
|
|
368
|
+
<div class="first:mt-0 last:mb-0 odd:bg-gray-50 even:bg-white">
|
|
369
|
+
<div class="disabled:opacity-50 checked:bg-blue-500 required:border-red-500">
|
|
370
|
+
<div class="focus-within:ring-2 focus-visible:outline-2">
|
|
371
|
+
<div class="visited:text-purple-600 target:ring-2">
|
|
372
|
+
<div class="open:rotate-180 empty:hidden">
|
|
373
|
+
<div class="valid:border-green-500 invalid:border-red-500 read-only:opacity-75">
|
|
374
|
+
<div class="autofill:bg-yellow-50 indeterminate:bg-gray-300">
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Negation Variants
|
|
378
|
+
|
|
379
|
+
```html
|
|
380
|
+
<div class="not-first:mt-4 not-last:mb-4">
|
|
381
|
+
<div class="not-disabled:cursor-pointer not-empty:block">
|
|
382
|
+
<div class="not-checked:bg-gray-100 not-only:border-b">
|
|
383
|
+
<div class="not-first-of-type:pt-4 not-last-of-type:pb-4">
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Pseudo-element Variants
|
|
387
|
+
|
|
388
|
+
```html
|
|
389
|
+
<div class="before:content-[''] before:block before:h-4">
|
|
390
|
+
<div class="after:content-['*'] after:text-red-500">
|
|
391
|
+
<li class="marker:text-blue-500">Item</li>
|
|
392
|
+
<input class="placeholder:text-gray-400">
|
|
393
|
+
<p class="selection:bg-blue-200">Selectable text</p>
|
|
394
|
+
<input class="file:bg-blue-50 file:border-0" type="file">
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Responsive Variants
|
|
398
|
+
|
|
399
|
+
```html
|
|
400
|
+
<div class="p-4 sm:p-6 md:p-8 lg:p-12 xl:p-16 2xl:p-20">
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
| Variant | Breakpoint |
|
|
404
|
+
|---------|-----------|
|
|
405
|
+
| `sm:` | 640px |
|
|
406
|
+
| `md:` | 768px |
|
|
407
|
+
| `lg:` | 1024px |
|
|
408
|
+
| `xl:` | 1280px |
|
|
409
|
+
| `2xl:` | 1536px |
|
|
410
|
+
|
|
411
|
+
### Dark & Light Mode
|
|
412
|
+
|
|
413
|
+
```html
|
|
414
|
+
<div class="bg-white dark:bg-gray-900 light:bg-gray-50">
|
|
415
|
+
<div class="text-gray-900 dark:text-white">
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
Uses class-based strategy (`.dark`/`.light` parent class).
|
|
419
|
+
|
|
420
|
+
### Group & Peer Variants
|
|
421
|
+
|
|
422
|
+
```html
|
|
423
|
+
<!-- Group: parent state affects children -->
|
|
424
|
+
<div class="group">
|
|
425
|
+
<p class="group-hover:text-blue-500">Hovering parent</p>
|
|
426
|
+
<p class="group-focus:ring-2">Parent focused</p>
|
|
427
|
+
<p class="group-has-[:checked]:bg-blue-50">Parent has checked input</p>
|
|
428
|
+
</div>
|
|
429
|
+
|
|
430
|
+
<!-- Named groups (for nesting) -->
|
|
431
|
+
<div class="group/card">
|
|
432
|
+
<div class="group/button">
|
|
433
|
+
<span class="group-hover/card:text-blue-500">Card hovered</span>
|
|
434
|
+
</div>
|
|
435
|
+
</div>
|
|
436
|
+
|
|
437
|
+
<!-- Peer: sibling state affects element -->
|
|
438
|
+
<input class="peer" />
|
|
439
|
+
<p class="peer-invalid:text-red-500">Error message</p>
|
|
440
|
+
<p class="peer-has-[:checked]:text-green-500">Checked sibling</p>
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### has: Variant
|
|
444
|
+
|
|
445
|
+
```html
|
|
446
|
+
<div class="has-[:focus]:ring-2"> <!-- :has(:focus) -->
|
|
447
|
+
<div class="has-[input:checked]:bg-blue-50"> <!-- :has(input:checked) -->
|
|
448
|
+
<div class="has-[>img]:p-4"> <!-- :has(>img) -->
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### aria-* Variants
|
|
452
|
+
|
|
453
|
+
```html
|
|
454
|
+
<div class="aria-disabled:opacity-50"> <!-- [aria-disabled="true"] -->
|
|
455
|
+
<div class="aria-expanded:rotate-180"> <!-- [aria-expanded="true"] -->
|
|
456
|
+
<div class="aria-[sort=ascending]:text-blue-500"> <!-- [aria-sort=ascending] -->
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### data-* Variants
|
|
460
|
+
|
|
461
|
+
```html
|
|
462
|
+
<div class="data-loading:opacity-50"> <!-- [data-loading] -->
|
|
463
|
+
<div class="data-[state=active]:bg-white"> <!-- [data-state=active] -->
|
|
464
|
+
<div class="data-[theme=dark]:bg-black"> <!-- [data-theme=dark] -->
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Media Query Variants
|
|
468
|
+
|
|
469
|
+
```html
|
|
470
|
+
<div class="landscape:flex-row portrait:flex-col">
|
|
471
|
+
<div class="motion-safe:animate-bounce motion-reduce:animate-none">
|
|
472
|
+
<div class="contrast-more:border-2 contrast-less:border-0">
|
|
473
|
+
<div class="forced-colors:border print:hidden">
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
Media variants stack with responsive variants:
|
|
477
|
+
|
|
478
|
+
```html
|
|
479
|
+
<div class="lg:landscape:flex-row">
|
|
480
|
+
<!-- @media (min-width: 1024px) and (orientation: landscape) -->
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### @supports Variant
|
|
484
|
+
|
|
485
|
+
```html
|
|
486
|
+
<div class="supports-[display:grid]:grid">
|
|
487
|
+
<div class="supports-[backdrop-filter:blur(0)]:backdrop-blur-sm">
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Container Queries
|
|
491
|
+
|
|
492
|
+
```html
|
|
493
|
+
<div class="@container">
|
|
494
|
+
<div class="@sm:flex @md:grid @lg:grid-cols-3">
|
|
495
|
+
</div>
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Direction Variants
|
|
499
|
+
|
|
500
|
+
```html
|
|
501
|
+
<div class="rtl:text-right ltr:text-left">
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
## Arbitrary Values
|
|
505
|
+
|
|
506
|
+
Use brackets for any CSS value:
|
|
507
|
+
|
|
508
|
+
```html
|
|
509
|
+
<div class="w-[350px] h-[calc(100vh-4rem)] p-[clamp(1rem,3vw,2rem)]">
|
|
510
|
+
<div class="text-[#1a1a1a] bg-[rgb(255,0,0)] border-[oklch(50%_0.2_240)]">
|
|
511
|
+
<div class="grid-cols-[120px_1fr_200px]"> <!-- underscores become spaces -->
|
|
512
|
+
<div class="text-[clamp(1rem,3vw,2rem)]">
|
|
513
|
+
<div class="font-[600]">
|
|
514
|
+
<div class="tracking-[0.2em]">
|
|
515
|
+
<div class="leading-[1.7]">
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### Arbitrary Properties
|
|
519
|
+
|
|
520
|
+
```html
|
|
521
|
+
<div class="[mask-type:luminance]">
|
|
522
|
+
<div class="[text-wrap:balance]">
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### Type Hints
|
|
526
|
+
|
|
527
|
+
```html
|
|
528
|
+
<div class="text-[color:var(--brand)]">
|
|
529
|
+
<div class="text-[length:var(--size)]">
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
## Important Modifier
|
|
533
|
+
|
|
534
|
+
Prefix with `!` to apply `!important`:
|
|
535
|
+
|
|
536
|
+
```html
|
|
537
|
+
<div class="!p-4 !text-red-500">
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
## Presets
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
import type { Preset } from '@cwcss/crosswind'
|
|
544
|
+
|
|
545
|
+
const myPreset: Preset = {
|
|
546
|
+
name: 'my-preset',
|
|
547
|
+
theme: {
|
|
548
|
+
extend: {
|
|
549
|
+
colors: {
|
|
550
|
+
brand: '#3b82f6',
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
shortcuts: {
|
|
555
|
+
btn: 'px-4 py-2 rounded font-semibold',
|
|
556
|
+
},
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
export default {
|
|
560
|
+
presets: [myPreset],
|
|
561
|
+
}
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
## Shortcuts
|
|
565
|
+
|
|
566
|
+
Define reusable class combinations:
|
|
567
|
+
|
|
568
|
+
```typescript
|
|
569
|
+
export default {
|
|
570
|
+
shortcuts: {
|
|
571
|
+
'btn': 'px-4 py-2 rounded-lg font-semibold transition-colors',
|
|
572
|
+
'btn-primary': 'btn bg-blue-500 text-white hover:bg-blue-600',
|
|
573
|
+
'card': 'rounded-xl border border-gray-200 p-6 shadow-sm',
|
|
574
|
+
},
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
## Performance
|
|
579
|
+
|
|
580
|
+
Crosswind uses several optimizations for fast CSS generation:
|
|
581
|
+
|
|
582
|
+
- **O(1) static utility map** for ~80% of common utilities (display, flex, grid, transitions, etc.)
|
|
583
|
+
- **Pre-computed color map** with flat cache for instant color lookups
|
|
584
|
+
- **Class-level caching** prevents duplicate generation
|
|
585
|
+
- **Selector caching** avoids rebuilding selectors with variants
|
|
586
|
+
- **Media query caching** for responsive and feature variants
|
|
587
|
+
- **Negative match cache** to skip known-unmatched utilities
|
|
38
588
|
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
- Configurable theme (colors, spacing, typography, etc.)
|
|
44
|
-
- Variant support (hover, focus, dark mode, responsive, and more)
|
|
45
|
-
- Custom rules and shortcuts
|
|
46
|
-
- Preset system for extensibility
|
|
47
|
-
- Bun plugin support
|
|
48
|
-
- Cross-platform CLI binaries (Linux, macOS, Windows)
|
|
589
|
+
Benchmarks (1000 utilities):
|
|
590
|
+
- Simple utilities: ~0.7ms
|
|
591
|
+
- Complex utilities: ~4.5ms
|
|
592
|
+
- Arbitrary values: ~0.6ms
|
|
49
593
|
|
|
50
594
|
## License
|
|
51
595
|
|