0
# Plugin System
1
2
WindiCSS features a powerful plugin system that allows you to extend the framework with custom utilities, components, variants, and base styles. The plugin API provides a comprehensive set of utilities for creating flexible and reusable extensions.
3
4
## Capabilities
5
6
### Plugin Creation
7
8
Main plugin creation function for developing WindiCSS extensions.
9
10
```typescript { .api }
11
/**
12
* Creates a WindiCSS plugin
13
* @param handler - Function that receives plugin utilities and defines the plugin behavior
14
* @param config - Optional configuration to merge with the processor config
15
* @returns Plugin object that can be added to the plugins array
16
*/
17
function plugin(
18
handler: (utils: PluginUtils) => void,
19
config?: Config
20
): PluginOutput;
21
22
interface PluginOutput {
23
handler: (utils: PluginUtils) => void;
24
config?: Config;
25
}
26
```
27
28
**Usage Examples:**
29
30
```typescript
31
import plugin from "windicss/plugin";
32
33
// Basic plugin
34
const buttonPlugin = plugin(({ addComponents }) => {
35
addComponents({
36
'.btn': {
37
padding: '0.5rem 1rem',
38
borderRadius: '0.375rem',
39
fontWeight: '500',
40
transition: 'all 0.2s'
41
},
42
'.btn-primary': {
43
backgroundColor: '#3b82f6',
44
color: '#ffffff'
45
}
46
});
47
});
48
49
// Plugin with configuration
50
const customPlugin = plugin(({ addUtilities, theme }) => {
51
addUtilities({
52
'.gradient-text': {
53
background: `linear-gradient(45deg, ${theme('colors.blue.500')}, ${theme('colors.purple.500')})`,
54
WebkitBackgroundClip: 'text',
55
WebkitTextFillColor: 'transparent'
56
}
57
});
58
}, {
59
theme: {
60
extend: {
61
colors: {
62
brand: '#ff6b6b'
63
}
64
}
65
}
66
});
67
```
68
69
### Plugin with Options
70
71
Creates configurable plugins that accept options for customization.
72
73
```typescript { .api }
74
/**
75
* Creates a plugin that accepts options for customization
76
* @param pluginFunction - Function that takes options and returns a plugin handler
77
* @param configFunction - Optional function that takes options and returns config
78
* @returns Function that accepts options and returns a plugin
79
*/
80
plugin.withOptions<T>(
81
pluginFunction: (options: T) => (utils: PluginUtils) => void,
82
configFunction?: (options: T) => Config
83
): PluginWithOptions<T>;
84
85
interface PluginWithOptions<T> {
86
(options?: T): PluginOutput;
87
__isOptionsFunction: true;
88
}
89
```
90
91
**Usage Examples:**
92
93
```typescript
94
// Plugin with options
95
const flexboxPlugin = plugin.withOptions<{
96
gap?: boolean;
97
grid?: boolean;
98
}>((options = {}) => ({ addUtilities }) => {
99
const utilities: Record<string, any> = {
100
'.flex-center': {
101
display: 'flex',
102
alignItems: 'center',
103
justifyContent: 'center'
104
}
105
};
106
107
if (options.gap) {
108
utilities['.flex-gap'] = {
109
display: 'flex',
110
gap: '1rem'
111
};
112
}
113
114
if (options.grid) {
115
utilities['.grid-center'] = {
116
display: 'grid',
117
placeItems: 'center'
118
};
119
}
120
121
addUtilities(utilities);
122
});
123
124
// Usage with options
125
const processor = new Processor({
126
plugins: [
127
flexboxPlugin({ gap: true, grid: true })
128
]
129
});
130
```
131
132
### Plugin Utilities Interface
133
134
Complete interface provided to plugin handlers for adding utilities, components, and more.
135
136
```typescript { .api }
137
interface PluginUtils {
138
/** Add utility classes */
139
addUtilities(utilities: Record<string, any>, options?: PluginUtilOptions): Style[];
140
/** Add component classes */
141
addComponents(components: Record<string, any>, options?: PluginUtilOptions): Style[];
142
/** Add base/global styles */
143
addBase(baseStyles: Record<string, any>): Style[];
144
/** Add custom variant */
145
addVariant(name: string, generator: VariantGenerator): Style | Style[];
146
/** Add dynamic utility generator */
147
addDynamic(key: string, generator: UtilityGenerator, options?: PluginUtilOptions): UtilityGenerator;
148
/** Access theme values */
149
theme(path: string, defaultValue?: any): any;
150
/** Access config values */
151
config(path: string, defaultValue?: any): any;
152
/** Escape CSS selector */
153
e(selector: string): string;
154
/** Add prefix to selector */
155
prefix(selector: string): string;
156
/** Access variant utilities */
157
variants(path: string, defaultValue?: string[]): string[];
158
}
159
160
interface PluginUtilOptions {
161
/** Whether to respect the configured prefix */
162
respectPrefix?: boolean;
163
/** Whether to respect the important configuration */
164
respectImportant?: boolean;
165
/** Whether to respect existing selector */
166
respectSelector?: boolean;
167
/** CSS layer for the utilities */
168
layer?: "base" | "components" | "utilities";
169
/** Variants to apply to utilities */
170
variants?: string[];
171
/** Order for CSS generation */
172
order?: number;
173
/** Group name for organization */
174
group?: string;
175
/** Completions for IDE support */
176
completions?: string[];
177
}
178
```
179
180
### Adding Utilities
181
182
Add custom utility classes to WindiCSS.
183
184
```typescript { .api }
185
/**
186
* Adds custom utility classes
187
* @param utilities - Object with CSS selectors as keys and style objects as values
188
* @param options - Options for utility generation
189
* @returns Array of generated Style objects
190
*/
191
addUtilities(
192
utilities: Record<string, any> | Array<Record<string, any>>,
193
options?: PluginUtilOptions
194
): Style[];
195
```
196
197
**Usage Examples:**
198
199
```typescript
200
const utilitiesPlugin = plugin(({ addUtilities }) => {
201
// Basic utilities
202
addUtilities({
203
'.scroll-smooth': {
204
scrollBehavior: 'smooth'
205
},
206
'.scroll-auto': {
207
scrollBehavior: 'auto'
208
}
209
});
210
211
// Utilities with variants and layer
212
addUtilities({
213
'.backdrop-blur': {
214
backdropFilter: 'blur(8px)'
215
},
216
'.backdrop-blur-sm': {
217
backdropFilter: 'blur(4px)'
218
}
219
}, {
220
respectPrefix: true,
221
respectImportant: true,
222
layer: 'utilities',
223
variants: ['responsive', 'hover']
224
});
225
226
// Responsive utilities
227
addUtilities({
228
'.container-xs': {
229
maxWidth: '480px',
230
marginLeft: 'auto',
231
marginRight: 'auto'
232
},
233
'.container-sm': {
234
maxWidth: '640px',
235
marginLeft: 'auto',
236
marginRight: 'auto'
237
}
238
});
239
});
240
```
241
242
### Adding Components
243
244
Add custom component classes with higher specificity than utilities.
245
246
```typescript { .api }
247
/**
248
* Adds custom component classes
249
* @param components - Object with CSS selectors as keys and style objects as values
250
* @param options - Options for component generation
251
* @returns Array of generated Style objects
252
*/
253
addComponents(
254
components: Record<string, any> | Array<Record<string, any>>,
255
options?: PluginUtilOptions
256
): Style[];
257
```
258
259
**Usage Examples:**
260
261
```typescript
262
const componentsPlugin = plugin(({ addComponents, theme }) => {
263
addComponents({
264
// Button components
265
'.btn': {
266
padding: '0.5rem 1rem',
267
borderRadius: theme('borderRadius.md'),
268
fontWeight: theme('fontWeight.medium'),
269
transition: 'all 0.15s ease-in-out',
270
cursor: 'pointer',
271
border: 'none',
272
'&:focus': {
273
outline: 'none',
274
boxShadow: '0 0 0 3px rgba(59, 130, 246, 0.1)'
275
}
276
},
277
'.btn-sm': {
278
padding: '0.25rem 0.75rem',
279
fontSize: theme('fontSize.sm')
280
},
281
'.btn-lg': {
282
padding: '0.75rem 1.5rem',
283
fontSize: theme('fontSize.lg')
284
},
285
286
// Card component
287
'.card': {
288
backgroundColor: theme('colors.white'),
289
borderRadius: theme('borderRadius.lg'),
290
boxShadow: theme('boxShadow.md'),
291
padding: theme('spacing.6')
292
}
293
});
294
});
295
```
296
297
### Adding Base Styles
298
299
Add global base styles that apply to HTML elements.
300
301
```typescript { .api }
302
/**
303
* Adds base/global styles
304
* @param baseStyles - Object with selectors and style objects
305
* @returns Array of generated Style objects
306
*/
307
addBase(baseStyles: Record<string, any>): Style[];
308
```
309
310
**Usage Examples:**
311
312
```typescript
313
const basePlugin = plugin(({ addBase, theme }) => {
314
addBase({
315
// Global styles
316
'html': {
317
scrollBehavior: 'smooth'
318
},
319
'body': {
320
fontFamily: theme('fontFamily.sans'),
321
lineHeight: theme('lineHeight.normal'),
322
color: theme('colors.gray.900'),
323
backgroundColor: theme('colors.gray.50')
324
},
325
326
// Custom elements
327
'h1, h2, h3, h4, h5, h6': {
328
fontWeight: theme('fontWeight.semibold'),
329
marginBottom: theme('spacing.4')
330
},
331
'p': {
332
marginBottom: theme('spacing.4')
333
},
334
335
// CSS custom properties
336
':root': {
337
'--primary-color': theme('colors.blue.500'),
338
'--secondary-color': theme('colors.green.500')
339
}
340
});
341
});
342
```
343
344
### Adding Dynamic Utilities
345
346
Add dynamic utility generators that create utilities based on arbitrary values.
347
348
```typescript { .api }
349
/**
350
* Adds dynamic utility generator
351
* @param key - Pattern to match for generating utilities
352
* @param generator - Function that generates styles based on matched values
353
* @param options - Options for utility generation
354
* @returns The generator function
355
*/
356
addDynamic(
357
key: string,
358
generator: UtilityGenerator,
359
options?: PluginUtilOptions
360
): UtilityGenerator;
361
362
type UtilityGenerator = (props: {
363
Utility: any;
364
Style: any;
365
Property: any;
366
Keyframes: any;
367
}) => Style | Style[] | undefined;
368
```
369
370
**Usage Examples:**
371
372
```typescript
373
const dynamicPlugin = plugin(({ addDynamic }) => {
374
// Custom spacing utilities
375
addDynamic('p-custom', ({ Utility, Style, Property }) => {
376
const match = Utility.raw.match(/^p-custom-(.+)$/);
377
if (match) {
378
const value = match[1];
379
return new Style(Utility.class, [
380
new Property('padding', `${value}px`)
381
]);
382
}
383
});
384
385
// Custom color utilities with opacity
386
addDynamic('bg-custom', ({ Utility, Style, Property }) => {
387
const match = Utility.raw.match(/^bg-custom-([a-zA-Z]+)-(\d+)$/);
388
if (match) {
389
const [, color, opacity] = match;
390
const opacityValue = parseInt(opacity) / 100;
391
return new Style(Utility.class, [
392
new Property('background-color', `rgba(var(--color-${color}), ${opacityValue})`)
393
]);
394
}
395
});
396
});
397
```
398
399
### Adding Variants
400
401
Add custom variants for conditional styling.
402
403
```typescript { .api }
404
/**
405
* Adds custom variant
406
* @param name - Name of the variant
407
* @param generator - Function that generates the variant style wrapper
408
* @returns Generated variant style
409
*/
410
addVariant(name: string, generator: VariantGenerator): Style | Style[];
411
412
type VariantGenerator = (utils: VariantUtils) => Style;
413
414
interface VariantUtils {
415
modifySelectors(modifier: (args: { className: string }) => string): Style;
416
atRule(name: string): Style;
417
pseudoClass(name: string): Style;
418
pseudoElement(name: string): Style;
419
parent(name: string): Style;
420
child(name: string): Style;
421
separator: string;
422
style: Style;
423
}
424
```
425
426
**Usage Examples:**
427
428
```typescript
429
const variantsPlugin = plugin(({ addVariant }) => {
430
// Custom pseudo-class variant
431
addVariant('hocus', ({ pseudoClass }) => {
432
return pseudoClass('hover, &:focus');
433
});
434
435
// Custom media query variant
436
addVariant('supports-grid', ({ atRule }) => {
437
return atRule('@supports (display: grid)');
438
});
439
440
// Custom parent selector variant
441
addVariant('group-hover', ({ modifySelectors }) => {
442
return modifySelectors(({ className }) => {
443
return `.group:hover .${className}`;
444
});
445
});
446
447
// Custom sibling variant
448
addVariant('sibling-checked', ({ modifySelectors }) => {
449
return modifySelectors(({ className }) => {
450
return `input[type="checkbox"]:checked ~ .${className}`;
451
});
452
});
453
});
454
```
455
456
### Accessing Theme and Config
457
458
Access theme values and configuration within plugins.
459
460
```typescript { .api }
461
/**
462
* Access theme values by path
463
* @param path - Dot-separated path to theme value
464
* @param defaultValue - Default value if path doesn't exist
465
* @returns Theme value or default
466
*/
467
theme(path: string, defaultValue?: any): any;
468
469
/**
470
* Access configuration values by path
471
* @param path - Dot-separated path to config value
472
* @param defaultValue - Default value if path doesn't exist
473
* @returns Config value or default
474
*/
475
config(path: string, defaultValue?: any): any;
476
```
477
478
**Usage Examples:**
479
480
```typescript
481
const themePlugin = plugin(({ addUtilities, theme, config }) => {
482
// Access theme values
483
const primaryColor = theme('colors.blue.500');
484
const borderRadius = theme('borderRadius.lg');
485
const fontFamily = theme('fontFamily.sans');
486
487
// Access config values
488
const prefix = config('prefix', '');
489
const separator = config('separator', ':');
490
const important = config('important', false);
491
492
addUtilities({
493
'.brand-card': {
494
backgroundColor: primaryColor,
495
borderRadius: borderRadius,
496
fontFamily: fontFamily.join(', '),
497
color: theme('colors.white'),
498
padding: theme('spacing.6')
499
}
500
});
501
});
502
```
503
504
### Built-in Plugin Examples
505
506
WindiCSS includes several built-in plugins that demonstrate the plugin system capabilities.
507
508
```typescript { .api }
509
import aspectRatio from "windicss/plugin/aspect-ratio";
510
import filters from "windicss/plugin/filters";
511
import forms from "windicss/plugin/forms";
512
import lineClamp from "windicss/plugin/line-clamp";
513
import typography from "windicss/plugin/typography";
514
import scrollSnap from "windicss/plugin/scroll-snap";
515
```
516
517
**Usage Example:**
518
519
```typescript
520
import Processor from "windicss";
521
import typography from "windicss/plugin/typography";
522
import forms from "windicss/plugin/forms";
523
524
const processor = new Processor({
525
plugins: [
526
typography({
527
modifiers: ['sm', 'lg', 'xl'],
528
className: 'prose'
529
}),
530
forms
531
]
532
});
533
```