@tenphi/tasty 0.14.0 → 0.14.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 +58 -43
- package/dist/styles/types.d.ts +18 -3
- package/dist/tasty.d.ts +3 -3
- package/docs/README.md +5 -4
- package/docs/adoption.md +6 -4
- package/docs/comparison.md +9 -7
- package/docs/design-system.md +1 -1
- package/docs/getting-started.md +11 -9
- package/docs/methodology.md +3 -1
- package/docs/ssr.md +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<h1 align="center">Tasty</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<strong>
|
|
9
|
-
|
|
8
|
+
<strong>Deterministic styling for stateful component systems.</strong><br>
|
|
9
|
+
A design-system styling engine that compiles component states into mutually exclusive selectors.
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
12
|
<p align="center">
|
|
@@ -17,23 +17,30 @@
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Tasty is a styling engine for design systems that generates deterministic CSS for stateful components. It compiles state maps into **mutually exclusive selectors**, so each property resolves from declared state logic instead of selector competition.
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
It fits best when a team is defining a house styling language for reusable components: tokens, style props, state aliases, recipes, and sub-element rules that need to stay predictable as the system grows.
|
|
23
23
|
|
|
24
24
|
## Why Tasty
|
|
25
25
|
|
|
26
|
-
- **Deterministic
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- **
|
|
34
|
-
- **Runtime
|
|
35
|
-
- **
|
|
36
|
-
- **
|
|
26
|
+
- **Deterministic composition, not cascade fights** — Tasty generates mutually exclusive selectors, so stateful styles resolve from the state map you declared rather than source order or specificity accidents. See [How It Actually Works](#how-it-actually-works).
|
|
27
|
+
- **Built for design-system teams** — Best fit for teams building reusable components with intersecting states, variants, tokens, sub-elements, responsive rules, and extension semantics that must stay predictable over time.
|
|
28
|
+
- **A governed styling model, not just syntax sugar** — Tasty is not just a syntax layer. It gives design-system teams a way to define the styling language product teams consume: tokens, units, recipes, style props, state aliases, and sub-element rules.
|
|
29
|
+
- **DSL that still feels like CSS** — Property names you already know (`padding`, `color`, `display`) with syntax sugar that removes boilerplate. Learn the DSL in minutes, not days. Start with the [Style DSL](docs/dsl.md), then use [Style Properties](docs/styles.md) as the handler reference.
|
|
30
|
+
|
|
31
|
+
### Supporting capabilities
|
|
32
|
+
|
|
33
|
+
- **Typed style props** — `styleProps` lets you expose selected styles as typed React props. Use `<Button placeSelf="end">` or `<Space flow="row" gap="2x">` without extra wrappers, utility classes, or `styles` overrides. The same props also accept state maps, so responsive values work with the same API. See [CSS properties as props](#css-properties-as-props).
|
|
34
|
+
- **Runtime, SSR, and zero-runtime options** — Use `tasty()` for runtime React components, add SSR integrations when your framework renders that runtime on the server, or use `tastyStatic()` when you specifically want build-time extraction instead of runtime styling.
|
|
35
|
+
- **Broad modern CSS coverage** — Media queries, container queries, `@supports`, `:has()`, `@starting-style`, `@property`, `@keyframes`, and more. Features that do not fit the component model (such as `@layer` and `!important`) are intentionally left out.
|
|
36
|
+
- **Performance and caching** — Runtime mode injects CSS on demand, reuses chunks aggressively, and relies on multi-level caching so large component systems stay practical.
|
|
37
|
+
- **TypeScript-first and AI-friendly** — Style definitions are declarative, structurally consistent, and fully typed, which helps both humans and tooling understand advanced stateful styles without hidden cascade logic.
|
|
38
|
+
|
|
39
|
+
## Why It Exists
|
|
40
|
+
|
|
41
|
+
Modern component styling becomes fragile when multiple selectors can still win for the same property. Hover, disabled, theme, breakpoint, parent state, and root state rules start competing through specificity and source order.
|
|
42
|
+
|
|
43
|
+
Tasty replaces that competition with explicit state-map resolution. Each property compiles into mutually exclusive branches, so reusable component styling stays deterministic as systems grow. For the full mechanism, jump to [How It Actually Works](#how-it-actually-works).
|
|
37
44
|
|
|
38
45
|
## Installation
|
|
39
46
|
|
|
@@ -56,20 +63,13 @@ yarn add @tenphi/tasty
|
|
|
56
63
|
|
|
57
64
|
## Start Here
|
|
58
65
|
|
|
66
|
+
- **[Comparison](docs/comparison.md)** — read this first if you are evaluating whether Tasty fits your team's styling model
|
|
67
|
+
- **[Adoption Guide](docs/adoption.md)** — understand who Tasty is for, where it fits, and how to introduce it incrementally
|
|
59
68
|
- **[Getting Started](docs/getting-started.md)** — the canonical onboarding path: install, first component, optional shared `configure()`, ESLint, editor tooling, and rendering mode selection
|
|
60
|
-
- **[
|
|
69
|
+
- **[Style rendering pipeline](docs/PIPELINE.md)** — see the selector model behind deterministic style resolution
|
|
70
|
+
- **[Docs Hub](docs/README.md)** — choose docs by role and task: runtime, zero-runtime, runtime SSR integration, design-system authoring, internals, and debugging
|
|
61
71
|
- **[Methodology](docs/methodology.md)** — the recommended component model and public API conventions for design-system code
|
|
62
72
|
|
|
63
|
-
## Choose a Rendering Mode
|
|
64
|
-
|
|
65
|
-
| Mode | Entry point | Best for | Trade-off |
|
|
66
|
-
|------|-------------|----------|-----------|
|
|
67
|
-
| **Runtime** | `@tenphi/tasty` | Interactive apps and design systems | Full feature set; CSS is generated on demand at runtime |
|
|
68
|
-
| **Zero-runtime** | `@tenphi/tasty/static` | Static sites, SSG, landing pages | Requires the Babel plugin; no component-level `styleProps` or runtime-only APIs |
|
|
69
|
-
| **SSR** | `@tenphi/tasty/ssr/*` | Next.js, Astro, and other streaming React SSR setups | Uses runtime `tasty()` with server-collected CSS and hydration cache transfer |
|
|
70
|
-
|
|
71
|
-
All three share the same DSL, tokens, units, and state mappings. See [Getting Started](docs/getting-started.md#choosing-a-rendering-mode), [Zero Runtime](docs/tasty-static.md), and [Server-Side Rendering](docs/ssr.md).
|
|
72
|
-
|
|
73
73
|
## Quick Start
|
|
74
74
|
|
|
75
75
|
### Create a styled component
|
|
@@ -82,12 +82,12 @@ const Card = tasty({
|
|
|
82
82
|
styles: {
|
|
83
83
|
display: 'flex',
|
|
84
84
|
flow: 'column',
|
|
85
|
-
padding: '
|
|
86
|
-
gap: '
|
|
87
|
-
fill: '
|
|
88
|
-
color: '
|
|
89
|
-
border: '
|
|
90
|
-
radius: '
|
|
85
|
+
padding: '24px',
|
|
86
|
+
gap: '12px',
|
|
87
|
+
fill: 'white',
|
|
88
|
+
color: '#222',
|
|
89
|
+
border: '1px solid #ddd',
|
|
90
|
+
radius: '12px',
|
|
91
91
|
},
|
|
92
92
|
});
|
|
93
93
|
|
|
@@ -95,7 +95,7 @@ const Card = tasty({
|
|
|
95
95
|
<Card>Hello World</Card>
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
Every value maps to CSS you'd recognize. This example is intentionally config-free
|
|
98
|
+
Every value maps to CSS you'd recognize. This example is intentionally plain and config-free. When you want a more design-system-shaped authoring model, Tasty also supports built-in units, tokens, recipes, state aliases, and color values such as `okhsl(...)` without extra runtime libraries.
|
|
99
99
|
|
|
100
100
|
Use `configure()` when you want to define shared tokens, state aliases, recipes, or other conventions for your app or design system. For a fuller onboarding path, follow [Getting Started](docs/getting-started.md).
|
|
101
101
|
|
|
@@ -165,9 +165,9 @@ Use `configure()` once when your app or design system needs shared aliases, toke
|
|
|
165
165
|
|
|
166
166
|
### CSS properties as props
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
Beyond state resolution, Tasty can also expose selected style controls as typed component props. That lets design systems keep layout and composition inside governed component APIs instead of pushing teams toward wrapper elements or ad hoc styling escapes.
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
With `styleProps`, a component can expose the styles you choose as normal typed props. You can adjust layout, spacing, alignment, or positioning where the component is used while staying inside a typed, design-system-aware API.
|
|
171
171
|
|
|
172
172
|
```tsx
|
|
173
173
|
import { tasty, FLOW_STYLES, POSITION_STYLES } from '@tenphi/tasty';
|
|
@@ -216,13 +216,24 @@ The same props also support state maps, so responsive values use the exact same
|
|
|
216
216
|
|
|
217
217
|
Layout components can expose flow props. Buttons can expose positioning props. Each component can offer only the style props that make sense for its role, while still keeping tokens, custom units, and state maps fully typed. This works in runtime `tasty()` components, not in `tastyStatic()`.
|
|
218
218
|
|
|
219
|
+
## Choose a Styling Approach
|
|
220
|
+
|
|
221
|
+
Once you understand the component model, pick the rendering mode that matches your app.
|
|
222
|
+
|
|
223
|
+
| Approach | Entry point | Best for | Trade-off |
|
|
224
|
+
|----------|-------------|----------|-----------|
|
|
225
|
+
| **Runtime** | `@tenphi/tasty` | Interactive apps with reusable stateful components and design systems | Full feature set; CSS is generated on demand at runtime |
|
|
226
|
+
| **Zero-runtime** | `@tenphi/tasty/static` | Static sites, SSG, landing pages | Requires the Babel plugin; no component-level `styleProps` or runtime-only APIs |
|
|
227
|
+
|
|
228
|
+
If your framework can execute runtime React code on the server, you can also add **SSR on top of runtime** with `@tenphi/tasty/ssr/*`. This uses the same `tasty()` pipeline, but collects CSS during server rendering and hydrates the cache on the client. That is the model for Next.js, generic React SSR, and Astro islands. See [Getting Started](docs/getting-started.md#choosing-a-rendering-mode), [Zero Runtime](docs/tasty-static.md), and [Server-Side Rendering](docs/ssr.md).
|
|
229
|
+
|
|
219
230
|
## How It Actually Works
|
|
220
231
|
|
|
221
232
|
This is the core idea that makes everything else possible.
|
|
222
233
|
|
|
223
234
|
For the end-to-end architecture — parsing state keys, building exclusive conditions, merging by output, and materializing selectors and at-rules — see **[Style rendering pipeline](docs/PIPELINE.md)**.
|
|
224
235
|
|
|
225
|
-
|
|
236
|
+
### The structural problem with normal CSS
|
|
226
237
|
|
|
227
238
|
First, the **cascade** resolves conflicts by specificity and source order: when multiple selectors match, the one with the highest specificity wins, or — if specificity is equal — the last one in source order wins. That makes styles inherently fragile. Reordering imports, adding a media query, or composing components from different libraries can silently break styling.
|
|
228
239
|
|
|
@@ -235,7 +246,11 @@ A small example makes this tangible. Two rules for a button's background:
|
|
|
235
246
|
|
|
236
247
|
Both selectors have specificity `(0, 1, 1)`. When the button is hovered **and** disabled, both match — and the last rule in source order wins. Swap the two lines and a hovered disabled button silently turns blue instead of gray. This class of bug is invisible in code review because the logic is correct; only the ordering is wrong.
|
|
237
248
|
|
|
238
|
-
|
|
249
|
+
### Why real state logic is hard to author by hand
|
|
250
|
+
|
|
251
|
+
Authoring selectors that capture real-world state logic is fundamentally hard. A single state like "dark mode" may depend on a root attribute, an OS preference, or both — each branch needing its own selector, proper negation of competing branches, and correct `@media` nesting. The example below shows the CSS you'd write by hand for just *one* property with *one* state. Scale that across dozens of properties, then add breakpoints and container queries, and the selector logic quickly becomes unmanageable.
|
|
252
|
+
|
|
253
|
+
### What Tasty generates instead
|
|
239
254
|
|
|
240
255
|
Tasty solves both problems at once: **every state mapping compiles into mutually exclusive selectors.**
|
|
241
256
|
|
|
@@ -280,8 +295,6 @@ Better — but the bare `.t0` default still matches unconditionally. It matches
|
|
|
280
295
|
|
|
281
296
|
This is just *one* property with *one* state, and getting it right already takes multiple iterations. The correct selectors require negating every other branch — which is exactly what Tasty generates automatically:
|
|
282
297
|
|
|
283
|
-
Tasty generates the correct version automatically:
|
|
284
|
-
|
|
285
298
|
```css
|
|
286
299
|
/* Branch 1: Explicit dark schema */
|
|
287
300
|
:root[data-schema="dark"] .t0.t0 {
|
|
@@ -308,9 +321,11 @@ Tasty generates the correct version automatically:
|
|
|
308
321
|
}
|
|
309
322
|
```
|
|
310
323
|
|
|
324
|
+
### What guarantee that gives you
|
|
325
|
+
|
|
311
326
|
Every rule is guarded by the negation of higher-priority rules. No two rules can match at the same time. No specificity arithmetic. No source-order dependence. Components compose and extend without collisions.
|
|
312
327
|
|
|
313
|
-
By absorbing selector complexity, Tasty makes advanced CSS patterns practical again — nested container queries, multi-condition `@supports` gates, and combined root-state/media branches. You stay in pure CSS instead of relying on JavaScript workarounds, so the browser can optimize layout, painting, and transitions natively. Tasty
|
|
328
|
+
By absorbing selector complexity, Tasty makes advanced CSS patterns practical again — nested container queries, multi-condition `@supports` gates, and combined root-state/media branches. You stay in pure CSS instead of relying on JavaScript workarounds, so the browser can optimize layout, painting, and transitions natively. Tasty keeps the solution in CSS while removing much of the selector bookkeeping that is hard to maintain by hand.
|
|
314
329
|
|
|
315
330
|
[Try it in the Cube UI Kit Storybook playground →](https://cube-ui-kit.vercel.app/?path=/story/getting-started-tasty-playground--playground)
|
|
316
331
|
|
|
@@ -533,7 +548,7 @@ module.exports = {
|
|
|
533
548
|
| **Sub-elements** | Built-in (`<C.Title>`) | Manual (`data-element`) |
|
|
534
549
|
| **Variants** | Built-in (`variants` option) | Separate static styles |
|
|
535
550
|
| **Framework** | React | Any (requires Babel) |
|
|
536
|
-
| **Best for** | Interactive apps, design systems | Static sites, SSG, landing pages |
|
|
551
|
+
| **Best for** | Interactive apps with reusable stateful components, design systems | Static sites, SSG, landing pages |
|
|
537
552
|
|
|
538
553
|
Both share the same DSL, tokens, units, state mappings, and recipes.
|
|
539
554
|
|
|
@@ -714,9 +729,9 @@ Open-source React UI kit built on Tasty + React Aria. 100+ production components
|
|
|
714
729
|
|
|
715
730
|
## Documentation
|
|
716
731
|
|
|
717
|
-
Start from the docs hub if you want the shortest path to the right guide for your role or
|
|
732
|
+
Start from the docs hub if you want the shortest path to the right guide for your role or styling approach.
|
|
718
733
|
|
|
719
|
-
- **[Docs Hub](docs/README.md)** — audience-based navigation across onboarding, design-system authoring, runtime, zero-runtime, SSR, debugging, and internals
|
|
734
|
+
- **[Docs Hub](docs/README.md)** — audience-based navigation across onboarding, design-system authoring, runtime, zero-runtime, runtime SSR integration, debugging, and internals
|
|
720
735
|
|
|
721
736
|
### Start here
|
|
722
737
|
|
package/dist/styles/types.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ type PresetNameKey = Extract<keyof TastyPresetNames, string>;
|
|
|
40
40
|
type PresetName = [PresetNameKey] extends [never] ? string : PresetNameKey;
|
|
41
41
|
type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
|
42
42
|
type OpaquePercentage = '' | `.${Digit}` | `.${Digit}${Digit}` | '.100';
|
|
43
|
+
type ColorValue = `#${NamedColor}${OpaquePercentage}` | `rgb(${string})` | `hsl(${string})` | `okhsl(${string})` | `oklch(${string})` | (string & {});
|
|
43
44
|
type NoType = false | null | undefined;
|
|
44
45
|
interface StylesInterface extends Omit<CSSProperties, 'color' | 'fill' | 'font' | 'outline' | 'type' | 'gap' | 'padding' | 'margin' | 'width' | 'height' | 'border' | 'transition' | 'placeContent' | 'placeItems'> {
|
|
45
46
|
/**
|
|
@@ -57,13 +58,20 @@ interface StylesInterface extends Omit<CSSProperties, 'color' | 'fill' | 'font'
|
|
|
57
58
|
/**
|
|
58
59
|
* Set the background color of the element. Shortcut for `background-color` with enhanced support for Tasty color tokens and syntaxes.
|
|
59
60
|
*
|
|
61
|
+
* Supports double-color syntax: the second color is applied as a foreground overlay via a CSS custom property.
|
|
62
|
+
*
|
|
60
63
|
* Examples:
|
|
61
64
|
* - `fill="#purple.10"` // purple background with 10% opacity
|
|
62
65
|
* - `fill="#danger"` // danger theme color
|
|
63
66
|
* - `fill="rgb(255 128 0)"` // custom RGB color
|
|
67
|
+
* - `fill="rgb(255 128 0 / 0.5)"` // RGB with opacity
|
|
68
|
+
* - `fill="hsl(200 100% 50%)"` // HSL color
|
|
69
|
+
* - `fill="okhsl(200 100% 50%)"` // perceptually uniform OKHSL color
|
|
70
|
+
* - `fill="oklch(0.7 0.15 200)"` // OKLCH color
|
|
71
|
+
* - `fill="#primary #secondary"` // double color (second as foreground overlay)
|
|
64
72
|
* - `fill={true}` // default fill color
|
|
65
73
|
*/
|
|
66
|
-
fill?:
|
|
74
|
+
fill?: ColorValue | boolean;
|
|
67
75
|
/**
|
|
68
76
|
* @deprecated Use `fill` instead.
|
|
69
77
|
*/
|
|
@@ -92,19 +100,26 @@ interface StylesInterface extends Omit<CSSProperties, 'color' | 'fill' | 'font'
|
|
|
92
100
|
* - `svgFill="#purple.10"` // purple fill with 10% opacity
|
|
93
101
|
* - `svgFill="#danger"` // danger theme color
|
|
94
102
|
* - `svgFill="rgb(255 128 0)"` // custom RGB color
|
|
103
|
+
* - `svgFill="hsl(200 100% 50%)"` // HSL color
|
|
104
|
+
* - `svgFill="okhsl(200 100% 50%)"` // OKHSL color
|
|
105
|
+
* - `svgFill="oklch(0.7 0.15 200)"` // OKLCH color
|
|
95
106
|
* - `svgFill="currentColor"` // inherit from parent color
|
|
96
107
|
*/
|
|
97
|
-
svgFill?:
|
|
108
|
+
svgFill?: ColorValue;
|
|
98
109
|
/**
|
|
99
110
|
* Set the text (current) color of the element. Shortcut for `color` with enhanced support for Tasty color tokens and syntaxes.
|
|
100
111
|
*
|
|
101
112
|
* Examples:
|
|
102
113
|
* - `color="#purple"` // purple text color
|
|
103
114
|
* - `color="#danger.6"` // danger color with 60% opacity
|
|
115
|
+
* - `color="rgb(255 128 0)"` // custom RGB color
|
|
116
|
+
* - `color="hsl(200 100% 50%)"` // HSL color
|
|
117
|
+
* - `color="okhsl(200 100% 50%)"` // OKHSL color
|
|
118
|
+
* - `color="oklch(0.7 0.15 200)"` // OKLCH color
|
|
104
119
|
* - `color="red"` // CSS color name
|
|
105
120
|
* - `color={true}` // currentColor
|
|
106
121
|
*/
|
|
107
|
-
color?:
|
|
122
|
+
color?: ColorValue | boolean;
|
|
108
123
|
/**
|
|
109
124
|
* The fade style applies gradient-based fading masks to the edges of an element. Replaces complex CSS mask gradients with a simple, declarative API.
|
|
110
125
|
*
|
package/dist/tasty.d.ts
CHANGED
|
@@ -104,8 +104,8 @@ declare const Element: ForwardRefExoticComponent<AllBaseProps<keyof HTMLElementT
|
|
|
104
104
|
image?: StyleValue<csstype.Property.BackgroundImage | undefined> | StyleValueStateMap<csstype.Property.BackgroundImage | undefined>;
|
|
105
105
|
marker?: StyleValue<csstype.Property.Marker | undefined> | StyleValueStateMap<csstype.Property.Marker | undefined>;
|
|
106
106
|
mask?: StyleValue<csstype.Property.Mask<string | number> | undefined> | StyleValueStateMap<csstype.Property.Mask<string | number> | undefined>;
|
|
107
|
-
fill?: StyleValue<boolean | (string & {}) | `#${string}` | `#${string}.0` | `#${string}.1` | `#${string}.2` | `#${string}.7` | `#${string}.3` | `#${string}.4` | `#${string}.5` | `#${string}.6` | `#${string}.8` | `#${string}.9` | `#${string}.00` | `#${string}.01` | `#${string}.02` | `#${string}.07` | `#${string}.03` | `#${string}.04` | `#${string}.05` | `#${string}.06` | `#${string}.08` | `#${string}.09` | `#${string}.10` | `#${string}.11` | `#${string}.12` | `#${string}.17` | `#${string}.13` | `#${string}.14` | `#${string}.15` | `#${string}.16` | `#${string}.18` | `#${string}.19` | `#${string}.20` | `#${string}.21` | `#${string}.22` | `#${string}.27` | `#${string}.23` | `#${string}.24` | `#${string}.25` | `#${string}.26` | `#${string}.28` | `#${string}.29` | `#${string}.70` | `#${string}.71` | `#${string}.72` | `#${string}.77` | `#${string}.73` | `#${string}.74` | `#${string}.75` | `#${string}.76` | `#${string}.78` | `#${string}.79` | `#${string}.30` | `#${string}.31` | `#${string}.32` | `#${string}.37` | `#${string}.33` | `#${string}.34` | `#${string}.35` | `#${string}.36` | `#${string}.38` | `#${string}.39` | `#${string}.40` | `#${string}.41` | `#${string}.42` | `#${string}.47` | `#${string}.43` | `#${string}.44` | `#${string}.45` | `#${string}.46` | `#${string}.48` | `#${string}.49` | `#${string}.50` | `#${string}.51` | `#${string}.52` | `#${string}.57` | `#${string}.53` | `#${string}.54` | `#${string}.55` | `#${string}.56` | `#${string}.58` | `#${string}.59` | `#${string}.60` | `#${string}.61` | `#${string}.62` | `#${string}.67` | `#${string}.63` | `#${string}.64` | `#${string}.65` | `#${string}.66` | `#${string}.68` | `#${string}.69` | `#${string}.80` | `#${string}.81` | `#${string}.82` | `#${string}.87` | `#${string}.83` | `#${string}.84` | `#${string}.85` | `#${string}.86` | `#${string}.88` | `#${string}.89` | `#${string}.90` | `#${string}.91` | `#${string}.92` | `#${string}.97` | `#${string}.93` | `#${string}.94` | `#${string}.95` | `#${string}.96` | `#${string}.98` | `#${string}.99` | `#${string}.100` | `rgb(${string})` | `
|
|
108
|
-
color?: StyleValue<string |
|
|
107
|
+
fill?: StyleValue<boolean | ((string & {}) | `#${string}` | `#${string}.0` | `#${string}.1` | `#${string}.2` | `#${string}.7` | `#${string}.3` | `#${string}.4` | `#${string}.5` | `#${string}.6` | `#${string}.8` | `#${string}.9` | `#${string}.00` | `#${string}.01` | `#${string}.02` | `#${string}.07` | `#${string}.03` | `#${string}.04` | `#${string}.05` | `#${string}.06` | `#${string}.08` | `#${string}.09` | `#${string}.10` | `#${string}.11` | `#${string}.12` | `#${string}.17` | `#${string}.13` | `#${string}.14` | `#${string}.15` | `#${string}.16` | `#${string}.18` | `#${string}.19` | `#${string}.20` | `#${string}.21` | `#${string}.22` | `#${string}.27` | `#${string}.23` | `#${string}.24` | `#${string}.25` | `#${string}.26` | `#${string}.28` | `#${string}.29` | `#${string}.70` | `#${string}.71` | `#${string}.72` | `#${string}.77` | `#${string}.73` | `#${string}.74` | `#${string}.75` | `#${string}.76` | `#${string}.78` | `#${string}.79` | `#${string}.30` | `#${string}.31` | `#${string}.32` | `#${string}.37` | `#${string}.33` | `#${string}.34` | `#${string}.35` | `#${string}.36` | `#${string}.38` | `#${string}.39` | `#${string}.40` | `#${string}.41` | `#${string}.42` | `#${string}.47` | `#${string}.43` | `#${string}.44` | `#${string}.45` | `#${string}.46` | `#${string}.48` | `#${string}.49` | `#${string}.50` | `#${string}.51` | `#${string}.52` | `#${string}.57` | `#${string}.53` | `#${string}.54` | `#${string}.55` | `#${string}.56` | `#${string}.58` | `#${string}.59` | `#${string}.60` | `#${string}.61` | `#${string}.62` | `#${string}.67` | `#${string}.63` | `#${string}.64` | `#${string}.65` | `#${string}.66` | `#${string}.68` | `#${string}.69` | `#${string}.80` | `#${string}.81` | `#${string}.82` | `#${string}.87` | `#${string}.83` | `#${string}.84` | `#${string}.85` | `#${string}.86` | `#${string}.88` | `#${string}.89` | `#${string}.90` | `#${string}.91` | `#${string}.92` | `#${string}.97` | `#${string}.93` | `#${string}.94` | `#${string}.95` | `#${string}.96` | `#${string}.98` | `#${string}.99` | `#${string}.100` | `rgb(${string})` | `hsl(${string})` | `okhsl(${string})` | `oklch(${string})`) | undefined> | StyleValueStateMap<boolean | ((string & {}) | `#${string}` | `#${string}.0` | `#${string}.1` | `#${string}.2` | `#${string}.7` | `#${string}.3` | `#${string}.4` | `#${string}.5` | `#${string}.6` | `#${string}.8` | `#${string}.9` | `#${string}.00` | `#${string}.01` | `#${string}.02` | `#${string}.07` | `#${string}.03` | `#${string}.04` | `#${string}.05` | `#${string}.06` | `#${string}.08` | `#${string}.09` | `#${string}.10` | `#${string}.11` | `#${string}.12` | `#${string}.17` | `#${string}.13` | `#${string}.14` | `#${string}.15` | `#${string}.16` | `#${string}.18` | `#${string}.19` | `#${string}.20` | `#${string}.21` | `#${string}.22` | `#${string}.27` | `#${string}.23` | `#${string}.24` | `#${string}.25` | `#${string}.26` | `#${string}.28` | `#${string}.29` | `#${string}.70` | `#${string}.71` | `#${string}.72` | `#${string}.77` | `#${string}.73` | `#${string}.74` | `#${string}.75` | `#${string}.76` | `#${string}.78` | `#${string}.79` | `#${string}.30` | `#${string}.31` | `#${string}.32` | `#${string}.37` | `#${string}.33` | `#${string}.34` | `#${string}.35` | `#${string}.36` | `#${string}.38` | `#${string}.39` | `#${string}.40` | `#${string}.41` | `#${string}.42` | `#${string}.47` | `#${string}.43` | `#${string}.44` | `#${string}.45` | `#${string}.46` | `#${string}.48` | `#${string}.49` | `#${string}.50` | `#${string}.51` | `#${string}.52` | `#${string}.57` | `#${string}.53` | `#${string}.54` | `#${string}.55` | `#${string}.56` | `#${string}.58` | `#${string}.59` | `#${string}.60` | `#${string}.61` | `#${string}.62` | `#${string}.67` | `#${string}.63` | `#${string}.64` | `#${string}.65` | `#${string}.66` | `#${string}.68` | `#${string}.69` | `#${string}.80` | `#${string}.81` | `#${string}.82` | `#${string}.87` | `#${string}.83` | `#${string}.84` | `#${string}.85` | `#${string}.86` | `#${string}.88` | `#${string}.89` | `#${string}.90` | `#${string}.91` | `#${string}.92` | `#${string}.97` | `#${string}.93` | `#${string}.94` | `#${string}.95` | `#${string}.96` | `#${string}.98` | `#${string}.99` | `#${string}.100` | `rgb(${string})` | `hsl(${string})` | `okhsl(${string})` | `oklch(${string})`) | undefined>;
|
|
108
|
+
color?: StyleValue<boolean | ((string & {}) | `#${string}` | `#${string}.0` | `#${string}.1` | `#${string}.2` | `#${string}.7` | `#${string}.3` | `#${string}.4` | `#${string}.5` | `#${string}.6` | `#${string}.8` | `#${string}.9` | `#${string}.00` | `#${string}.01` | `#${string}.02` | `#${string}.07` | `#${string}.03` | `#${string}.04` | `#${string}.05` | `#${string}.06` | `#${string}.08` | `#${string}.09` | `#${string}.10` | `#${string}.11` | `#${string}.12` | `#${string}.17` | `#${string}.13` | `#${string}.14` | `#${string}.15` | `#${string}.16` | `#${string}.18` | `#${string}.19` | `#${string}.20` | `#${string}.21` | `#${string}.22` | `#${string}.27` | `#${string}.23` | `#${string}.24` | `#${string}.25` | `#${string}.26` | `#${string}.28` | `#${string}.29` | `#${string}.70` | `#${string}.71` | `#${string}.72` | `#${string}.77` | `#${string}.73` | `#${string}.74` | `#${string}.75` | `#${string}.76` | `#${string}.78` | `#${string}.79` | `#${string}.30` | `#${string}.31` | `#${string}.32` | `#${string}.37` | `#${string}.33` | `#${string}.34` | `#${string}.35` | `#${string}.36` | `#${string}.38` | `#${string}.39` | `#${string}.40` | `#${string}.41` | `#${string}.42` | `#${string}.47` | `#${string}.43` | `#${string}.44` | `#${string}.45` | `#${string}.46` | `#${string}.48` | `#${string}.49` | `#${string}.50` | `#${string}.51` | `#${string}.52` | `#${string}.57` | `#${string}.53` | `#${string}.54` | `#${string}.55` | `#${string}.56` | `#${string}.58` | `#${string}.59` | `#${string}.60` | `#${string}.61` | `#${string}.62` | `#${string}.67` | `#${string}.63` | `#${string}.64` | `#${string}.65` | `#${string}.66` | `#${string}.68` | `#${string}.69` | `#${string}.80` | `#${string}.81` | `#${string}.82` | `#${string}.87` | `#${string}.83` | `#${string}.84` | `#${string}.85` | `#${string}.86` | `#${string}.88` | `#${string}.89` | `#${string}.90` | `#${string}.91` | `#${string}.92` | `#${string}.97` | `#${string}.93` | `#${string}.94` | `#${string}.95` | `#${string}.96` | `#${string}.98` | `#${string}.99` | `#${string}.100` | `rgb(${string})` | `hsl(${string})` | `okhsl(${string})` | `oklch(${string})`) | undefined> | StyleValueStateMap<boolean | ((string & {}) | `#${string}` | `#${string}.0` | `#${string}.1` | `#${string}.2` | `#${string}.7` | `#${string}.3` | `#${string}.4` | `#${string}.5` | `#${string}.6` | `#${string}.8` | `#${string}.9` | `#${string}.00` | `#${string}.01` | `#${string}.02` | `#${string}.07` | `#${string}.03` | `#${string}.04` | `#${string}.05` | `#${string}.06` | `#${string}.08` | `#${string}.09` | `#${string}.10` | `#${string}.11` | `#${string}.12` | `#${string}.17` | `#${string}.13` | `#${string}.14` | `#${string}.15` | `#${string}.16` | `#${string}.18` | `#${string}.19` | `#${string}.20` | `#${string}.21` | `#${string}.22` | `#${string}.27` | `#${string}.23` | `#${string}.24` | `#${string}.25` | `#${string}.26` | `#${string}.28` | `#${string}.29` | `#${string}.70` | `#${string}.71` | `#${string}.72` | `#${string}.77` | `#${string}.73` | `#${string}.74` | `#${string}.75` | `#${string}.76` | `#${string}.78` | `#${string}.79` | `#${string}.30` | `#${string}.31` | `#${string}.32` | `#${string}.37` | `#${string}.33` | `#${string}.34` | `#${string}.35` | `#${string}.36` | `#${string}.38` | `#${string}.39` | `#${string}.40` | `#${string}.41` | `#${string}.42` | `#${string}.47` | `#${string}.43` | `#${string}.44` | `#${string}.45` | `#${string}.46` | `#${string}.48` | `#${string}.49` | `#${string}.50` | `#${string}.51` | `#${string}.52` | `#${string}.57` | `#${string}.53` | `#${string}.54` | `#${string}.55` | `#${string}.56` | `#${string}.58` | `#${string}.59` | `#${string}.60` | `#${string}.61` | `#${string}.62` | `#${string}.67` | `#${string}.63` | `#${string}.64` | `#${string}.65` | `#${string}.66` | `#${string}.68` | `#${string}.69` | `#${string}.80` | `#${string}.81` | `#${string}.82` | `#${string}.87` | `#${string}.83` | `#${string}.84` | `#${string}.85` | `#${string}.86` | `#${string}.88` | `#${string}.89` | `#${string}.90` | `#${string}.91` | `#${string}.92` | `#${string}.97` | `#${string}.93` | `#${string}.94` | `#${string}.95` | `#${string}.96` | `#${string}.98` | `#${string}.99` | `#${string}.100` | `rgb(${string})` | `hsl(${string})` | `okhsl(${string})` | `oklch(${string})`) | undefined>;
|
|
109
109
|
font?: StyleValue<boolean | csstype.Property.FontFamily | undefined> | StyleValueStateMap<boolean | csstype.Property.FontFamily | undefined>;
|
|
110
110
|
outline?: StyleValue<string | boolean | undefined> | StyleValueStateMap<string | boolean | undefined>;
|
|
111
111
|
gap?: StyleValue<boolean | csstype.Property.Gap<string | number> | undefined> | StyleValueStateMap<boolean | csstype.Property.Gap<string | number> | undefined>;
|
|
@@ -957,7 +957,7 @@ declare const Element: ForwardRefExoticComponent<AllBaseProps<keyof HTMLElementT
|
|
|
957
957
|
colorInterpolation?: StyleValue<csstype.Property.ColorInterpolation | undefined> | StyleValueStateMap<csstype.Property.ColorInterpolation | undefined>;
|
|
958
958
|
colorRendering?: StyleValue<csstype.Property.ColorRendering | undefined> | StyleValueStateMap<csstype.Property.ColorRendering | undefined>;
|
|
959
959
|
glyphOrientationVertical?: StyleValue<csstype.Property.GlyphOrientationVertical | undefined> | StyleValueStateMap<csstype.Property.GlyphOrientationVertical | undefined>;
|
|
960
|
-
svgFill?: StyleValue<(string & {}) | `#${string}` | `#${string}.0` | `#${string}.1` | `#${string}.2` | `#${string}.7` | `#${string}.3` | `#${string}.4` | `#${string}.5` | `#${string}.6` | `#${string}.8` | `#${string}.9` | `#${string}.00` | `#${string}.01` | `#${string}.02` | `#${string}.07` | `#${string}.03` | `#${string}.04` | `#${string}.05` | `#${string}.06` | `#${string}.08` | `#${string}.09` | `#${string}.10` | `#${string}.11` | `#${string}.12` | `#${string}.17` | `#${string}.13` | `#${string}.14` | `#${string}.15` | `#${string}.16` | `#${string}.18` | `#${string}.19` | `#${string}.20` | `#${string}.21` | `#${string}.22` | `#${string}.27` | `#${string}.23` | `#${string}.24` | `#${string}.25` | `#${string}.26` | `#${string}.28` | `#${string}.29` | `#${string}.70` | `#${string}.71` | `#${string}.72` | `#${string}.77` | `#${string}.73` | `#${string}.74` | `#${string}.75` | `#${string}.76` | `#${string}.78` | `#${string}.79` | `#${string}.30` | `#${string}.31` | `#${string}.32` | `#${string}.37` | `#${string}.33` | `#${string}.34` | `#${string}.35` | `#${string}.36` | `#${string}.38` | `#${string}.39` | `#${string}.40` | `#${string}.41` | `#${string}.42` | `#${string}.47` | `#${string}.43` | `#${string}.44` | `#${string}.45` | `#${string}.46` | `#${string}.48` | `#${string}.49` | `#${string}.50` | `#${string}.51` | `#${string}.52` | `#${string}.57` | `#${string}.53` | `#${string}.54` | `#${string}.55` | `#${string}.56` | `#${string}.58` | `#${string}.59` | `#${string}.60` | `#${string}.61` | `#${string}.62` | `#${string}.67` | `#${string}.63` | `#${string}.64` | `#${string}.65` | `#${string}.66` | `#${string}.68` | `#${string}.69` | `#${string}.80` | `#${string}.81` | `#${string}.82` | `#${string}.87` | `#${string}.83` | `#${string}.84` | `#${string}.85` | `#${string}.86` | `#${string}.88` | `#${string}.89` | `#${string}.90` | `#${string}.91` | `#${string}.92` | `#${string}.97` | `#${string}.93` | `#${string}.94` | `#${string}.95` | `#${string}.96` | `#${string}.98` | `#${string}.99` | `#${string}.100` | `rgb(${string})` | `
|
|
960
|
+
svgFill?: StyleValue<((string & {}) | `#${string}` | `#${string}.0` | `#${string}.1` | `#${string}.2` | `#${string}.7` | `#${string}.3` | `#${string}.4` | `#${string}.5` | `#${string}.6` | `#${string}.8` | `#${string}.9` | `#${string}.00` | `#${string}.01` | `#${string}.02` | `#${string}.07` | `#${string}.03` | `#${string}.04` | `#${string}.05` | `#${string}.06` | `#${string}.08` | `#${string}.09` | `#${string}.10` | `#${string}.11` | `#${string}.12` | `#${string}.17` | `#${string}.13` | `#${string}.14` | `#${string}.15` | `#${string}.16` | `#${string}.18` | `#${string}.19` | `#${string}.20` | `#${string}.21` | `#${string}.22` | `#${string}.27` | `#${string}.23` | `#${string}.24` | `#${string}.25` | `#${string}.26` | `#${string}.28` | `#${string}.29` | `#${string}.70` | `#${string}.71` | `#${string}.72` | `#${string}.77` | `#${string}.73` | `#${string}.74` | `#${string}.75` | `#${string}.76` | `#${string}.78` | `#${string}.79` | `#${string}.30` | `#${string}.31` | `#${string}.32` | `#${string}.37` | `#${string}.33` | `#${string}.34` | `#${string}.35` | `#${string}.36` | `#${string}.38` | `#${string}.39` | `#${string}.40` | `#${string}.41` | `#${string}.42` | `#${string}.47` | `#${string}.43` | `#${string}.44` | `#${string}.45` | `#${string}.46` | `#${string}.48` | `#${string}.49` | `#${string}.50` | `#${string}.51` | `#${string}.52` | `#${string}.57` | `#${string}.53` | `#${string}.54` | `#${string}.55` | `#${string}.56` | `#${string}.58` | `#${string}.59` | `#${string}.60` | `#${string}.61` | `#${string}.62` | `#${string}.67` | `#${string}.63` | `#${string}.64` | `#${string}.65` | `#${string}.66` | `#${string}.68` | `#${string}.69` | `#${string}.80` | `#${string}.81` | `#${string}.82` | `#${string}.87` | `#${string}.83` | `#${string}.84` | `#${string}.85` | `#${string}.86` | `#${string}.88` | `#${string}.89` | `#${string}.90` | `#${string}.91` | `#${string}.92` | `#${string}.97` | `#${string}.93` | `#${string}.94` | `#${string}.95` | `#${string}.96` | `#${string}.98` | `#${string}.99` | `#${string}.100` | `rgb(${string})` | `hsl(${string})` | `okhsl(${string})` | `oklch(${string})`) | undefined> | StyleValueStateMap<((string & {}) | `#${string}` | `#${string}.0` | `#${string}.1` | `#${string}.2` | `#${string}.7` | `#${string}.3` | `#${string}.4` | `#${string}.5` | `#${string}.6` | `#${string}.8` | `#${string}.9` | `#${string}.00` | `#${string}.01` | `#${string}.02` | `#${string}.07` | `#${string}.03` | `#${string}.04` | `#${string}.05` | `#${string}.06` | `#${string}.08` | `#${string}.09` | `#${string}.10` | `#${string}.11` | `#${string}.12` | `#${string}.17` | `#${string}.13` | `#${string}.14` | `#${string}.15` | `#${string}.16` | `#${string}.18` | `#${string}.19` | `#${string}.20` | `#${string}.21` | `#${string}.22` | `#${string}.27` | `#${string}.23` | `#${string}.24` | `#${string}.25` | `#${string}.26` | `#${string}.28` | `#${string}.29` | `#${string}.70` | `#${string}.71` | `#${string}.72` | `#${string}.77` | `#${string}.73` | `#${string}.74` | `#${string}.75` | `#${string}.76` | `#${string}.78` | `#${string}.79` | `#${string}.30` | `#${string}.31` | `#${string}.32` | `#${string}.37` | `#${string}.33` | `#${string}.34` | `#${string}.35` | `#${string}.36` | `#${string}.38` | `#${string}.39` | `#${string}.40` | `#${string}.41` | `#${string}.42` | `#${string}.47` | `#${string}.43` | `#${string}.44` | `#${string}.45` | `#${string}.46` | `#${string}.48` | `#${string}.49` | `#${string}.50` | `#${string}.51` | `#${string}.52` | `#${string}.57` | `#${string}.53` | `#${string}.54` | `#${string}.55` | `#${string}.56` | `#${string}.58` | `#${string}.59` | `#${string}.60` | `#${string}.61` | `#${string}.62` | `#${string}.67` | `#${string}.63` | `#${string}.64` | `#${string}.65` | `#${string}.66` | `#${string}.68` | `#${string}.69` | `#${string}.80` | `#${string}.81` | `#${string}.82` | `#${string}.87` | `#${string}.83` | `#${string}.84` | `#${string}.85` | `#${string}.86` | `#${string}.88` | `#${string}.89` | `#${string}.90` | `#${string}.91` | `#${string}.92` | `#${string}.97` | `#${string}.93` | `#${string}.94` | `#${string}.95` | `#${string}.96` | `#${string}.98` | `#${string}.99` | `#${string}.100` | `rgb(${string})` | `hsl(${string})` | `okhsl(${string})` | `oklch(${string})`) | undefined>;
|
|
961
961
|
fade?: StyleValue<string | undefined> | StyleValueStateMap<string | undefined>;
|
|
962
962
|
scrollbar?: StyleValue<string | boolean | undefined> | StyleValueStateMap<string | boolean | undefined>;
|
|
963
963
|
boldFontWeight?: StyleValue<number | undefined> | StyleValueStateMap<number | undefined>;
|
package/docs/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# Tasty Docs
|
|
2
2
|
|
|
3
|
-
Use this
|
|
3
|
+
Tasty is a styling engine for design systems that turns component state into deterministic CSS by compiling state maps into mutually exclusive selectors. Use this hub to choose the right guide once you know whether you are evaluating the model, adopting it in a design system, or implementing with it day to day.
|
|
4
4
|
|
|
5
5
|
## Start Here
|
|
6
6
|
|
|
7
7
|
- **New to Tasty**: [Getting Started](getting-started.md) for installation, the first component, optional shared `configure()`, ESLint, editor tooling, and rendering mode selection.
|
|
8
8
|
- **Learning the component model**: [Methodology](methodology.md) for root + sub-elements, `styleProps`, tokens, extension, and recommended boundaries between `styles`, `style`, and wrappers.
|
|
9
|
-
- **Evaluating
|
|
9
|
+
- **Evaluating the selector model**: [Style rendering pipeline](PIPELINE.md) for how mutually exclusive selectors make stateful styling deterministic.
|
|
10
|
+
- **Evaluating fit**: [Comparison](comparison.md) for tool-selection context, then [Adoption Guide](adoption.md) for audience fit and rollout strategy inside a design system.
|
|
10
11
|
|
|
11
12
|
## By Role
|
|
12
13
|
|
|
@@ -14,11 +15,11 @@ Use this page when you know what you want to do, but not which document to open
|
|
|
14
15
|
- **Design-system author**: [Methodology](methodology.md), [Building a Design System](design-system.md), [Configuration](configuration.md), and [Adoption Guide](adoption.md).
|
|
15
16
|
- **Platform or tooling engineer**: [Configuration](configuration.md), [Zero Runtime (tastyStatic)](tasty-static.md), [Server-Side Rendering](ssr.md), and [Debug Utilities](debug.md).
|
|
16
17
|
|
|
17
|
-
## By
|
|
18
|
+
## By Styling Approach
|
|
18
19
|
|
|
19
20
|
- **Runtime React components**: [Runtime API](runtime.md)
|
|
20
21
|
- **Zero-runtime / build-time extraction**: [Zero Runtime (tastyStatic)](tasty-static.md)
|
|
21
|
-
- **
|
|
22
|
+
- **Runtime `tasty()` with server collection and hydration**: [Server-Side Rendering](ssr.md)
|
|
22
23
|
|
|
23
24
|
## By Task
|
|
24
25
|
|
package/docs/adoption.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Adoption Guide
|
|
2
2
|
|
|
3
|
-
Tasty is not a drop-in replacement for another styling library. It is a **substrate for building a design-system-defined styling language
|
|
3
|
+
Tasty is not a drop-in replacement for another styling library. It is a **substrate for building a design-system-defined styling language**: what the comparison guide calls a house styling language. That means adoption usually starts where styling has already become a composition problem, not with an all-at-once rewrite.
|
|
4
4
|
|
|
5
5
|
This guide is for design-system maintainers and platform engineers evaluating Tasty or introducing it into an existing codebase. Use this document for rollout strategy and adoption sequencing; use the [Comparison guide](comparison.md) when the open question is whether Tasty is the right tool in the first place.
|
|
6
6
|
|
|
@@ -116,6 +116,8 @@ See [Configuration](configuration.md) for the full `configure()` API.
|
|
|
116
116
|
|
|
117
117
|
You do not need to adopt everything at once. Tasty is designed to be introduced layer by layer.
|
|
118
118
|
|
|
119
|
+
A practical way to start is with the components that already suffer from intersecting state and variant logic: buttons, inputs, menus, disclosures, dialogs, list items, interactive cards, and compound components. Those are the places where deterministic resolution pays off fastest.
|
|
120
|
+
|
|
119
121
|
### Phase 1 -- Tokens and units
|
|
120
122
|
|
|
121
123
|
Start by defining your design tokens and custom units. This is the lowest-risk step: it only configures the parser and does not require rewriting any components.
|
|
@@ -161,7 +163,7 @@ configure({
|
|
|
161
163
|
|
|
162
164
|
### Phase 3 -- Migrate a few primitives
|
|
163
165
|
|
|
164
|
-
Pick 2-3
|
|
166
|
+
Pick 2-3 widely used primitives (Box, Text, Button) and rewrite them with `tasty()`. Keep the public API identical so product code does not need to change.
|
|
165
167
|
|
|
166
168
|
```tsx
|
|
167
169
|
const Box = tasty({
|
|
@@ -175,11 +177,11 @@ const Box = tasty({
|
|
|
175
177
|
});
|
|
176
178
|
```
|
|
177
179
|
|
|
178
|
-
At this point you can validate the DSL, token workflow, and component authoring experience before
|
|
180
|
+
At this point you can validate the DSL, token workflow, and component authoring experience before expanding the rollout.
|
|
179
181
|
|
|
180
182
|
### Phase 4 -- Encode complex states
|
|
181
183
|
|
|
182
|
-
Move components with intersecting states (buttons with hover + disabled + theme variants, inputs with focus + error + readonly) to Tasty's state map syntax. This is where mutually exclusive selectors start paying off.
|
|
184
|
+
Move the components with the most painful intersecting states (buttons with hover + disabled + theme variants, inputs with focus + error + readonly) to Tasty's state map syntax. This is where mutually exclusive selectors start paying off.
|
|
183
185
|
|
|
184
186
|
```tsx
|
|
185
187
|
const Button = tasty({
|
package/docs/comparison.md
CHANGED
|
@@ -4,6 +4,10 @@ Use this guide when you are deciding whether Tasty is the right tool. If you hav
|
|
|
4
4
|
|
|
5
5
|
Tasty is best understood not as a general-purpose CSS framework, but as a **styling engine for design systems and shared component APIs**.
|
|
6
6
|
|
|
7
|
+
It targets a different layer: helping design-system teams define a **house styling language** on top of CSS.
|
|
8
|
+
|
|
9
|
+
That does not require a big upfront configuration step. Tasty's built-in units and normal CSS color values work out of the box, and `okhsl(...)` is available immediately as the recommended path for color authoring. The extra setup comes later if a team wants shared tokens, aliases, recipes, or stricter conventions.
|
|
10
|
+
|
|
7
11
|
Most styling tools focus on one of these layers:
|
|
8
12
|
|
|
9
13
|
- direct app styling
|
|
@@ -12,9 +16,7 @@ Most styling tools focus on one of these layers:
|
|
|
12
16
|
- utility composition
|
|
13
17
|
- atomic CSS generation
|
|
14
18
|
|
|
15
|
-
Tasty
|
|
16
|
-
|
|
17
|
-
That does not mean a big upfront configuration step is required. Tasty's built-in units and normal CSS color values work out of the box, and `okhsl(...)` is available immediately as the recommended path for color authoring. The extra setup comes later if a team wants shared tokens, aliases, recipes, or stricter conventions.
|
|
19
|
+
Tasty's house styling language can include tokens, state semantics, style props, recipes, custom units, and sub-element rules.
|
|
18
20
|
|
|
19
21
|
That is why syntax-level comparisons are often shallow. The more meaningful comparison is about:
|
|
20
22
|
|
|
@@ -87,9 +89,9 @@ Tasty compiles this into selectors where `disabled` is guarded by `:not(:hover)`
|
|
|
87
89
|
|
|
88
90
|
That makes Tasty less of a "better way to write CSS objects" and more of a **state-aware style compiler for design systems**.
|
|
89
91
|
|
|
90
|
-
Beyond state resolution, Tasty
|
|
92
|
+
Beyond state resolution, Tasty also provides several structural capabilities that reinforce the design-system layer:
|
|
91
93
|
|
|
92
|
-
- **CSS properties as typed React props** — `styleProps` lets a component expose selected style properties as normal props (`<Button placeSelf="end">`), including state maps for responsive values.
|
|
94
|
+
- **CSS properties as typed React props** — `styleProps` lets a component expose selected style properties as normal props (`<Button placeSelf="end">`), including state maps for responsive values. This keeps layout and composition controls inside a governed component API instead of pushing teams back to ad hoc styling escapes.
|
|
93
95
|
- **Sub-element styling** — Compound components declare inner parts via capitalized keys in `styles` and `data-element` attributes. States, tokens, and recipes apply across the entire element tree from a single definition. See [Runtime API — Sub-element Styling](runtime.md#sub-element-styling).
|
|
94
96
|
- **Auto-inferred `@property`** — When a custom property is assigned a concrete value, Tasty infers the CSS `@property` syntax and registers it automatically, enabling smooth transitions on custom properties without manual declarations.
|
|
95
97
|
- **AI-friendly style definitions** — Style definitions are declarative, self-contained, and structurally consistent. AI tools can read, refactor, and generate Tasty styles as confidently as a human — no hidden cascade logic or implicit ordering to second-guess.
|
|
@@ -122,7 +124,7 @@ So this is not mainly a comparison of syntax. It is a comparison of **governance
|
|
|
122
124
|
- Tailwind: developers author directly with framework vocabulary
|
|
123
125
|
- Tasty: design-system authors define the vocabulary product teams consume
|
|
124
126
|
|
|
125
|
-
Tailwind is
|
|
127
|
+
Tailwind is a stronger fit for fast product styling with framework-owned vocabulary. Tasty is a stronger fit when styling should be exposed through a design-system-owned API and state resolution needs to stay deterministic as the component model grows.
|
|
126
128
|
|
|
127
129
|
To make this concrete, consider a button with `hover`, `disabled`, and `theme=danger` states.
|
|
128
130
|
|
|
@@ -301,7 +303,7 @@ So while Stitches and Emotion are strong tools for building components, Tasty is
|
|
|
301
303
|
|
|
302
304
|
That makes it narrower in audience, but deeper in architectural ambition.
|
|
303
305
|
|
|
304
|
-
|
|
306
|
+
For teams evaluating runtime styling at scale, Tasty also documents its runtime benchmarks and caching model in the main [README](../README.md#performance). That matters, but it is still secondary to the core question of whether you want Tasty's deterministic selector model.
|
|
305
307
|
|
|
306
308
|
---
|
|
307
309
|
|
package/docs/design-system.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This guide walks through building a design-system styling layer on top of Tasty — defining tokens, state aliases, recipes, primitive components, and compound components with sub-elements.
|
|
4
4
|
|
|
5
|
-
It assumes you have already decided to adopt Tasty. For evaluation criteria, audience fit, and incremental adoption phases, see the [Adoption Guide](adoption.md). For the recommended component patterns and mental model, see [Methodology](methodology.md).
|
|
5
|
+
It assumes you have already decided to adopt Tasty. The goal is not just to centralize tokens, but to define a styling language whose component states resolve deterministically across variants, responsive rules, and sub-elements. For evaluation criteria, audience fit, and incremental adoption phases, see the [Adoption Guide](adoption.md). For the recommended component patterns and mental model, see [Methodology](methodology.md).
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
package/docs/getting-started.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Getting Started
|
|
2
2
|
|
|
3
|
-
This guide walks you from zero to a working Tasty component, then through the optional shared configuration and tooling layers. For a feature overview, see the [README](../README.md). For the full style language reference, see the [Style DSL](dsl.md). For the React API, see the [Runtime API](runtime.md). For the rest of the docs by role or task, see the [Docs Hub](README.md).
|
|
3
|
+
This guide walks you from zero to a working Tasty component, then through the optional shared configuration and tooling layers. It is the right starting point when you already want to try Tasty in code. If you are still deciding whether Tasty fits your team, start with [Comparison](comparison.md) and [Adoption Guide](adoption.md) first. For a feature overview, see the [README](../README.md). For the full style language reference, see the [Style DSL](dsl.md). For the React API, see the [Runtime API](runtime.md). For the rest of the docs by role or task, see the [Docs Hub](README.md).
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -10,6 +10,8 @@ This guide walks you from zero to a working Tasty component, then through the op
|
|
|
10
10
|
- **React** >= 18 (peer dependency)
|
|
11
11
|
- **Package manager**: pnpm, npm, or yarn
|
|
12
12
|
|
|
13
|
+
Tasty can be used immediately in a React app, but it is most compelling for teams building reusable components with intersecting states, variants, tokens, and design-system conventions.
|
|
14
|
+
|
|
13
15
|
---
|
|
14
16
|
|
|
15
17
|
## Install
|
|
@@ -177,25 +179,25 @@ export default [
|
|
|
177
179
|
|
|
178
180
|
## Choosing a rendering mode
|
|
179
181
|
|
|
180
|
-
Tasty
|
|
182
|
+
Tasty has two styling approaches. Pick the one that fits your use case, then decide whether your runtime setup also needs server rendering support:
|
|
181
183
|
|
|
182
|
-
|
|
|
184
|
+
| Approach | Entry point | Best for | Trade-off |
|
|
183
185
|
|------|-------------|----------|-----------|
|
|
184
|
-
| **Runtime** | `tasty()` from `@tenphi/tasty` | Interactive apps, design systems | CSS generated at runtime; full feature set (styleProps, sub-elements, variants) |
|
|
186
|
+
| **Runtime** | `tasty()` from `@tenphi/tasty` | Interactive apps with reusable stateful components, design systems | CSS generated at runtime; full feature set (styleProps, sub-elements, variants) |
|
|
185
187
|
| **Zero-runtime** | `tastyStatic()` from `@tenphi/tasty/static` | Static sites, landing pages, SSG | Zero JS overhead; requires Babel plugin; no dynamic props |
|
|
186
|
-
| **SSR** | `@tenphi/tasty/ssr/next` or `@tenphi/tasty/ssr/astro` | Next.js, Astro, streaming SSR | Runtime `tasty()` with server-rendered CSS and zero-cost hydration |
|
|
187
188
|
|
|
188
|
-
|
|
189
|
+
Both share the same DSL, tokens, units, and state mappings.
|
|
189
190
|
|
|
190
191
|
- Runtime is the default and requires no extra setup beyond `@tenphi/tasty`.
|
|
192
|
+
- If your framework can execute runtime code during server rendering, add SSR support on top of runtime with `@tenphi/tasty/ssr/next`, `@tenphi/tasty/ssr/astro`, or the core SSR API. This still uses `tasty()`; it just collects CSS on the server and hydrates the cache on the client.
|
|
191
193
|
- Zero-runtime requires the Babel plugin and additional peer dependencies. See [Zero Runtime (tastyStatic)](tasty-static.md).
|
|
192
|
-
- SSR works with existing `tasty()` components — wrap your app with a registry or
|
|
194
|
+
- SSR works with existing `tasty()` components — wrap your app with a registry, middleware, or collector. See [Server-Side Rendering](ssr.md).
|
|
193
195
|
|
|
194
196
|
---
|
|
195
197
|
|
|
196
198
|
## Next steps
|
|
197
199
|
|
|
198
|
-
- **[Docs Hub](README.md)** — Pick the next guide by role,
|
|
200
|
+
- **[Docs Hub](README.md)** — Pick the next guide by role, styling approach, or task
|
|
199
201
|
- **[Methodology](methodology.md)** — The recommended patterns for structuring Tasty components: sub-elements, styleProps, tokens, extension
|
|
200
202
|
- **[Style DSL](dsl.md)** — State maps, tokens, units, extending semantics, keyframes, @property
|
|
201
203
|
- **[Runtime API](runtime.md)** — `tasty()` factory, component props, variants, sub-elements, hooks
|
|
@@ -212,4 +214,4 @@ All three share the same DSL, tokens, units, and state mappings.
|
|
|
212
214
|
|
|
213
215
|
- Styles are missing on first render: make sure the file that calls `configure()` is imported before any `tasty()` component renders.
|
|
214
216
|
- Token or unit values are not what you expect: check your `configure({ tokens, units })` setup, then inspect the generated CSS variables with [Debug Utilities](debug.md).
|
|
215
|
-
- You need
|
|
217
|
+
- You need build-time extraction or server-rendered CSS delivery: use [Zero Runtime (tastyStatic)](tasty-static.md) for extraction, or add [Server-Side Rendering](ssr.md) on top of runtime `tasty()` when your framework renders on the server.
|
package/docs/methodology.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# Methodology
|
|
2
2
|
|
|
3
|
-
Tasty has opinions about how components should be structured. The patterns described here are not mandatory — Tasty works without them — but following them gets the most out of the engine:
|
|
3
|
+
Tasty has opinions about how components should be structured. The patterns described here are not mandatory — Tasty works without them — but following them gets the most out of the engine: deterministic state resolution, cleaner component APIs, simpler overrides, and fewer surprises as the system grows.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## Component architecture: root + sub-elements
|
|
8
8
|
|
|
9
|
+
This model matters most for design-system authors and platform teams building reusable, stateful components. It turns Tasty's selector guarantees into a component architecture that stays predictable as states, variants, and compound parts accumulate.
|
|
10
|
+
|
|
9
11
|
### The model
|
|
10
12
|
|
|
11
13
|
Every Tasty component has a **root element** and zero or more **sub-elements**. The root owns the state context. Sub-elements participate in the same context by default.
|
package/docs/ssr.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Server-Side Rendering (SSR)
|
|
2
2
|
|
|
3
|
-
Tasty supports server-side rendering with zero-cost client hydration. Your existing `tasty()` components work unchanged
|
|
3
|
+
Tasty supports server-side rendering with zero-cost client hydration. This does **not** introduce a separate styling engine: SSR uses the same runtime `tasty()` pipeline you already use on the client, then adds server-side CSS collection and client-side cache hydration. Your existing `tasty()` components work unchanged, and SSR remains opt-in with no per-component modifications. For the broader docs map, see the [Docs Hub](README.md).
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -18,7 +18,7 @@ The Astro integration (`@tenphi/tasty/ssr/astro`) has no additional dependencies
|
|
|
18
18
|
|
|
19
19
|
## How It Works
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
When the environment can execute runtime React code during server rendering, the same `tasty()` and `useStyles()` calls can run there too. In Next.js, generic React SSR, and Astro islands, Tasty simply changes where that runtime-generated CSS goes: `useStyles()` detects a `ServerStyleCollector` and collects CSS into it instead of trying to access the DOM. The collector accumulates all styles, serializes them as `<style>` tags and a cache state script in the HTML. On the client, `hydrateTastyCache()` pre-populates the injector cache so that `useStyles()` skips the rendering pipeline entirely during hydration.
|
|
22
22
|
|
|
23
23
|
```
|
|
24
24
|
Server Client
|