@tenphi/tasty 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,376 @@
1
+ # Zero Runtime Mode (tastyStatic)
2
+
3
+ `tastyStatic` is a build-time utility for generating CSS with zero runtime overhead. It's designed for static sites, no-JS websites, and performance-critical applications where you want to eliminate all runtime styling code.
4
+
5
+ ---
6
+
7
+ ## When to Use
8
+
9
+ - **Static site generation (SSG)** — Pre-render all styles at build time
10
+ - **No-JavaScript websites** — CSS works without any JS runtime
11
+ - **Performance-critical pages** — Zero runtime overhead for styling
12
+ - **Landing pages** — Minimal bundle size with pre-generated CSS
13
+
14
+ ## Quick Start
15
+
16
+ The zero-runtime mode is part of the main `@tenphi/tasty` package. No additional packages required.
17
+
18
+ ### Basic Usage
19
+
20
+ ```tsx
21
+ import { tastyStatic } from '@tenphi/tasty/static';
22
+
23
+ // Define styles - returns StaticStyle object
24
+ const button = tastyStatic({
25
+ display: 'inline-flex',
26
+ padding: '2x 4x',
27
+ fill: '#purple',
28
+ color: '#white',
29
+ radius: '1r',
30
+ });
31
+
32
+ // Use in JSX - works via toString() coercion
33
+ <button className={button}>Click me</button>
34
+
35
+ // Or access className explicitly
36
+ <button className={button.className}>Click me</button>
37
+ ```
38
+
39
+ ---
40
+
41
+ ## API Reference
42
+
43
+ ### tastyStatic(styles)
44
+
45
+ Creates a `StaticStyle` object from a styles definition.
46
+
47
+ ```tsx
48
+ const card = tastyStatic({
49
+ padding: '4x',
50
+ fill: '#white',
51
+ border: true,
52
+ radius: true,
53
+ });
54
+ ```
55
+
56
+ ### tastyStatic(base, styles)
57
+
58
+ Extends an existing `StaticStyle` with additional styles. Uses `mergeStyles` internally for proper nested selector handling.
59
+
60
+ ```tsx
61
+ const button = tastyStatic({
62
+ padding: '2x 4x',
63
+ fill: '#blue',
64
+ Icon: { color: '#white' },
65
+ });
66
+
67
+ const primaryButton = tastyStatic(button, {
68
+ fill: '#purple',
69
+ Icon: { opacity: 0.8 },
70
+ });
71
+ ```
72
+
73
+ ### tastyStatic(selector, styles)
74
+
75
+ Generates global styles for a CSS selector. The call is removed from the bundle after transformation.
76
+
77
+ ```tsx
78
+ tastyStatic('body', {
79
+ fill: '#surface',
80
+ color: '#text',
81
+ preset: 't3',
82
+ });
83
+ ```
84
+
85
+ ---
86
+
87
+ ## StaticStyle Object
88
+
89
+ | Property | Type | Description |
90
+ |----------|------|-------------|
91
+ | `className` | `string` | Space-separated class names for use in JSX |
92
+ | `styles` | `Styles` | The original (or merged) styles object |
93
+ | `toString()` | `() => string` | Returns `className` for string coercion |
94
+
95
+ ---
96
+
97
+ ## Babel Plugin Configuration
98
+
99
+ ### Basic Configuration
100
+
101
+ ```javascript
102
+ // babel.config.js
103
+ module.exports = {
104
+ plugins: [
105
+ ['@tenphi/tasty/babel-plugin', {
106
+ output: 'public/tasty.css',
107
+ }]
108
+ ]
109
+ };
110
+ ```
111
+
112
+ ### With Configuration
113
+
114
+ ```javascript
115
+ module.exports = {
116
+ plugins: [
117
+ ['@tenphi/tasty/babel-plugin', {
118
+ output: 'public/tasty.css',
119
+ config: {
120
+ states: {
121
+ '@mobile': '@media(w < 768px)',
122
+ '@tablet': '@media(w < 1024px)',
123
+ '@dark': '@root(theme=dark)',
124
+ },
125
+ devMode: true,
126
+ },
127
+ }]
128
+ ]
129
+ };
130
+ ```
131
+
132
+ ### Plugin Options
133
+
134
+ | Option | Type | Default | Description |
135
+ |--------|------|---------|-------------|
136
+ | `output` | `string` | `'tasty.css'` | Path for generated CSS file |
137
+ | `config.states` | `Record<string, string>` | `{}` | Predefined state aliases |
138
+ | `config.devMode` | `boolean` | `false` | Add source comments to CSS |
139
+ | `config.recipes` | `Record<string, RecipeStyles>` | `{}` | Predefined style recipes |
140
+
141
+ ---
142
+
143
+ ## Recipes
144
+
145
+ Recipes work with `tastyStatic` the same way as with runtime `tasty`:
146
+
147
+ ```javascript
148
+ // babel.config.js
149
+ module.exports = {
150
+ plugins: [
151
+ ['@tenphi/tasty/babel-plugin', {
152
+ output: 'public/tasty.css',
153
+ config: {
154
+ recipes: {
155
+ card: { padding: '4x', fill: '#surface', radius: '1r', border: true },
156
+ elevated: { shadow: '2x 2x 4x #shadow' },
157
+ },
158
+ },
159
+ }]
160
+ ]
161
+ };
162
+ ```
163
+
164
+ ```tsx
165
+ import { tastyStatic } from '@tenphi/tasty/static';
166
+
167
+ const card = tastyStatic({
168
+ recipe: 'card elevated',
169
+ color: '#text',
170
+ });
171
+
172
+ <div className={card}>Styled card</div>
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Next.js Integration
178
+
179
+ ```javascript
180
+ // next.config.js
181
+ const { withTastyZero } = require('@tenphi/tasty/next');
182
+
183
+ module.exports = withTastyZero({
184
+ output: 'public/tasty.css',
185
+ config: {
186
+ states: {
187
+ '@mobile': '@media(w < 768px)',
188
+ },
189
+ devMode: process.env.NODE_ENV === 'development',
190
+ },
191
+ })({
192
+ reactStrictMode: true,
193
+ });
194
+ ```
195
+
196
+ ### Including the CSS
197
+
198
+ ```tsx
199
+ // app/layout.tsx (App Router)
200
+ import '@/public/tasty.css';
201
+
202
+ // or pages/_app.tsx (Pages Router)
203
+ import '../public/tasty.css';
204
+ ```
205
+
206
+ ---
207
+
208
+ ## Vite Integration
209
+
210
+ ```typescript
211
+ // vite.config.ts
212
+ import { defineConfig } from 'vite';
213
+ import react from '@vitejs/plugin-react';
214
+
215
+ export default defineConfig({
216
+ plugins: [
217
+ react({
218
+ babel: {
219
+ plugins: [
220
+ ['@tenphi/tasty/babel-plugin', {
221
+ output: 'public/tasty.css',
222
+ config: {
223
+ states: { '@mobile': '@media(w < 768px)' },
224
+ },
225
+ }],
226
+ ],
227
+ },
228
+ }),
229
+ ],
230
+ });
231
+ ```
232
+
233
+ ---
234
+
235
+ ## Build Transformation
236
+
237
+ ### Before (Source Code)
238
+
239
+ ```tsx
240
+ import { tastyStatic } from '@tenphi/tasty/static';
241
+
242
+ const button = tastyStatic({
243
+ padding: '2x 4x',
244
+ fill: '#purple',
245
+ color: '#white',
246
+ });
247
+
248
+ tastyStatic('.heading', { preset: 'h1' });
249
+
250
+ export const Button = () => <button className={button}>Click</button>;
251
+ ```
252
+
253
+ ### After (Production Build)
254
+
255
+ ```tsx
256
+ const button = {
257
+ className: 'ts3f2a1b ts8c4d2e',
258
+ styles: { padding: '2x 4x', fill: '#purple', color: '#white' },
259
+ toString() { return this.className; }
260
+ };
261
+
262
+ export const Button = () => <button className={button}>Click</button>;
263
+ ```
264
+
265
+ ### Generated CSS (tasty.css)
266
+
267
+ ```css
268
+ /* Generated by @tenphi/tasty/zero - DO NOT EDIT */
269
+
270
+ .ts3f2a1b.ts3f2a1b {
271
+ padding: 16px 32px;
272
+ }
273
+
274
+ .ts8c4d2e.ts8c4d2e {
275
+ background: #9370db;
276
+ color: #fff;
277
+ }
278
+
279
+ .heading.heading {
280
+ font-size: 2.5rem;
281
+ font-weight: 700;
282
+ line-height: 1.2;
283
+ }
284
+ ```
285
+
286
+ ---
287
+
288
+ ## Style Extension
289
+
290
+ ```tsx
291
+ // Base button
292
+ const button = tastyStatic({
293
+ display: 'inline-flex',
294
+ padding: '2x 4x',
295
+ radius: '1r',
296
+ fill: '#gray.20',
297
+ color: '#text',
298
+ transition: 'fill 0.15s',
299
+ });
300
+
301
+ // Variants
302
+ const primaryButton = tastyStatic(button, {
303
+ fill: '#purple',
304
+ color: '#white',
305
+ });
306
+
307
+ const dangerButton = tastyStatic(button, {
308
+ fill: '#danger',
309
+ color: '#white',
310
+ });
311
+ ```
312
+
313
+ ---
314
+
315
+ ## State-based Styling
316
+
317
+ ```tsx
318
+ const card = tastyStatic({
319
+ padding: {
320
+ '': '4x',
321
+ '@mobile': '2x',
322
+ },
323
+ display: {
324
+ '': 'flex',
325
+ '@mobile': 'block',
326
+ },
327
+ });
328
+ ```
329
+
330
+ ---
331
+
332
+ ## Extending Style Types (TypeScript)
333
+
334
+ If you add custom style properties, use module augmentation so `tastyStatic` recognizes them too. See [Extending Style Types](configuration.md#extending-style-types-typescript) in the configuration docs.
335
+
336
+ ---
337
+
338
+ ## Limitations
339
+
340
+ 1. **Static values only** — All style values must be known at build time
341
+ 2. **No runtime props** — Cannot use `styleProps` or dynamic `styles` prop
342
+ 3. **No mods at runtime** — Modifiers must be defined statically
343
+ 4. **Build-time transformation required** — Babel plugin must process files
344
+
345
+ ### Workarounds
346
+
347
+ For dynamic styling needs, combine with regular CSS or CSS variables:
348
+
349
+ ```tsx
350
+ const card = tastyStatic({
351
+ padding: '4x',
352
+ fill: 'var(--card-bg, #white)',
353
+ });
354
+
355
+ <div
356
+ className={card}
357
+ style={{ '--card-bg': isActive ? '#purple' : '#white' }}
358
+ />
359
+ ```
360
+
361
+ ---
362
+
363
+ ## Best Practices
364
+
365
+ 1. **Define base styles** for common patterns, then extend for variants
366
+ 2. **Use selector mode** for global/body styles
367
+ 3. **Enable devMode** in development for easier debugging
368
+ 4. **Configure states** for consistent responsive breakpoints
369
+ 5. **Import generated CSS** early in your app entry point
370
+
371
+ ---
372
+
373
+ ## Related
374
+
375
+ - [Usage Guide](usage.md) — Runtime styling: component creation, state mappings, sub-elements, variants, and hooks
376
+ - [Configuration](configuration.md) — Global configuration: tokens, recipes, custom units, and style handlers