You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**WindCtrl** is a next-generation styling utility that unifies static Tailwind classes and dynamic inline styles into a single, type-safe interface.
6
6
7
-
It evolves the concept of Variant APIs (like [cva](https://cva.style/)) by introducing **Stackable Traits** to solve combinatorial explosion and **Interpolated Variants** for seamless dynamic value handling—all while maintaining a minimal runtime footprint optimized for Tailwind's JIT compiler.
7
+
It builds on existing variant APIs (like [cva](https://cva.style/)) and introduces **Stackable Traits** to avoid combinatorial explosion, as well as **Interpolated Variants** for seamless dynamic styling.
8
+
All of this is achieved with a minimal runtime footprint and full compatibility with Tailwind's JIT compiler.
8
9
9
10
## Features
10
11
11
-
- 🎨 **Unified API** - Seamlessly blends static Tailwind classes and dynamic inline styles into one cohesive interface.
12
12
- 🧩 **Trait System** - Solves combinatorial explosion by treating states as stackable, non-exclusive layers.
13
-
-🎯**Scoped Styling** - Context-aware styling using data attributes - no React Context required (RSC friendly).
13
+
-🎨**Unified API** - Seamlessly blends static Tailwind classes and dynamic inline styles into one cohesive interface.
14
14
- ⚡ **JIT Conscious** - Designed for Tailwind JIT: utilities stay as class strings, while truly dynamic values can be expressed as inline styles.
15
+
- 🎯 **Scoped Styling** - Context-aware styling using data attributes - no React Context required (RSC friendly).
15
16
- 🔒 **Type-Safe** - Best-in-class TypeScript support with automatic prop inference.
16
17
- 📦 **Minimal Overhead** - Ultra-lightweight runtime with only `clsx` and `tailwind-merge` as dependencies.
> **Note on Tailwind JIT**: Tailwind only generates CSS for class names it can statically detect in your source. Avoid constructing class strings dynamically (e.g. "`w-`" + `size`) unless you safelist them in your Tailwind config.
100
-
101
100
### Traits (Stackable States)
102
101
103
102
Traits are non-exclusive, stackable layers of state. Unlike `variants` (which are mutually exclusive), multiple traits can be active simultaneously. This declarative approach solves the "combinatorial explosion" problem often seen with `compoundVariants`.
Scopes enable **context-aware styling** without relying on React Context or client-side JavaScript. This makes them fully compatible with React Server Components (RSC). They utilize Tailwind's group modifier logic under the hood.
127
+
Slots allow you to define styles for **sub-elements** (e.g., icon, label) within a single component definition. Each slot returns its own class string, enabling clean compound component patterns.
128
+
129
+
Slots are completely optional and additive. You can start with a single-root component and introduce slots only when needed.
130
+
If a slot is never defined, it simply won't appear in the result.
> **Note on Tailwind JIT**: Tailwind only generates CSS for class names it can statically detect in your source. Avoid constructing class strings dynamically (e.g. "`w-`" + `size`) unless you safelist them in your Tailwind config.
237
+
238
+
### Scopes (RSC Support)
239
+
240
+
Scopes enable **context-aware styling** without relying on React Context or client-side JavaScript. This makes them fully compatible with React Server Components (RSC). They utilize Tailwind's group modifier logic under the hood.
241
+
242
+
```typescript
243
+
const button =windctrl({
244
+
scopes: {
245
+
header: "text-sm py-1",
246
+
footer: "text-xs text-gray-500",
168
247
},
169
248
});
170
249
171
250
// Usage
172
-
button({ intent: "primary", size: "lg" });
251
+
// 1. Wrap the parent with `data-windctrl-scope` and `group/windctrl-scope`
252
+
// 2. The button automatically adapts its style based on the parent
The scope classes are automatically prefixed with `group-data-[windctrl-scope=...]/windctrl-scope:` to target the parent's data attribute.
259
+
175
260
## Gotchas
176
261
177
262
-**Tailwind JIT:** Tailwind only generates CSS for class names it can statically detect. Avoid constructing class strings dynamically unless you safelist them.
0 commit comments