teacss 0.4.6 → 0.5.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.
package/README.md CHANGED
@@ -1,364 +1,90 @@
1
1
  # TeaCSS
2
2
 
3
- **An LLM-friendly atomic CSS toolkit.**
3
+ The application package for TeaCSS.
4
4
 
5
- Readable utilities for humans. Predictable syntax for AI agents.
5
+ The root entry exports the official `cn`, `recipe`, `omitAttributes`,
6
+ runtime types, and Standard constant tables. Engine and preset factories are
7
+ available through explicit subpaths.
6
8
 
7
- ## Purpose
9
+ ## Install
8
10
 
9
- `teacss` is the application-facing package. Its root entry provides the
10
- official `cn` and `recipe` runtime helpers, the `omitAttributes` attribute
11
- helper, and Standard preset constant tables, while its subpaths expose the
12
- engine and official presets.
11
+ Install `teacss` as an application dependency and add the adapter for the
12
+ project's build tool:
13
13
 
14
- Use it for normal TeaCSS applications. Preset authors, custom integration
15
- authors, and tooling authors should import the narrower `@teacss/*` packages
16
- that own those extension APIs; the root entry intentionally does not expose
17
- low-level factories such as `createReciper`.
14
+ | Build tool | Development packages |
15
+ | -------------- | ------------------------------- |
16
+ | Vite | `@teacss/vite vite` |
17
+ | Astro | `@teacss/astro astro vite` |
18
+ | Rsbuild | `@teacss/rsbuild @rsbuild/core` |
19
+ | PostCSS | `@teacss/postcss postcss` |
20
+ | Bun Build | `@teacss/bun` |
21
+ | Standalone CLI | `@teacss/cli` |
18
22
 
19
- The base installation contains the runtime class helpers, engine core, and
20
- official presets. Build integrations are separate packages, so install and
21
- import the one owned by the selected build boundary directly:
22
-
23
- Install the package names below as development dependencies with npm, pnpm,
24
- Yarn, or Bun. Bun Build itself requires the Bun runtime.
25
-
26
- | Build boundary | Development packages | Import |
27
- | --- | --- | --- |
28
- | Vite | `@teacss/vite vite` | `@teacss/vite` |
29
- | Astro | `@teacss/astro astro vite` | `@teacss/astro` |
30
- | Rsbuild | `@teacss/rsbuild @rsbuild/core` | `@teacss/rsbuild` |
31
- | PostCSS | `@teacss/postcss postcss` | `@teacss/postcss` |
32
- | Bun Build | `@teacss/bun` | `@teacss/bun` |
33
-
34
- The standalone CLI is intentionally separate because `teacss` has no CLI
35
- subpath or executable:
36
-
37
- Install `@teacss/cli` as a development dependency with the project's package
38
- manager.
39
-
40
- TeaCSS is an atomic CSS toolkit designed around a simple idea: utility classes should read like CSS declarations. Its primary audience is large language models, so every language and design tradeoff is judged first by whether a model can reliably predict the output. Instead of compressing meaning into short aliases, TeaCSS uses an explicit `property:value` syntax that remains easy for developers to read and easy for AI agents to generate, validate, and reason about. Predictability takes precedence over brevity.
41
-
42
- ## Philosophy
43
-
44
- TeaCSS keeps three principles in view:
45
-
46
- * **Predictability over brevity.** A model should be able to infer the emitted CSS from the source token.
47
- * **Clarity over cleverness.** Classes should be readable first, compact only when that does not hide intent.
48
- * **One model over exceptions.** State, responsive behavior, relations, and arbitrary selectors all use the same trailing `@` condition axis. Write `p:4@hover`, never `hover:p:4`.
49
-
50
- ## Usage
51
-
52
- Install or update the optional TeaCSS skill:
53
-
54
- ```sh
55
- skills add teacss/skills --skill teacss
56
- skills update teacss
57
- ```
58
-
59
- Restart Codex after installing the skill.
60
-
61
- Install the application package and the integration used by the project. For
62
- Vite, install `teacss` as an application dependency and `@teacss/vite` plus
63
- `vite` as development dependencies with npm, pnpm, Yarn, or Bun.
64
-
65
- Use the Vite integration:
23
+ Example with Vite:
66
24
 
67
25
  ```ts
26
+ import { defineConfig } from "vite";
68
27
  import { pluginTeacss } from "@teacss/vite";
69
28
 
70
- export default {
71
- plugins: [pluginTeacss()],
72
- };
29
+ export default defineConfig({ plugins: [pluginTeacss()] });
73
30
  ```
74
31
 
75
- Create a TeaCSS entry at `index.css` or `src/index.css`:
76
-
77
32
  ```css
78
33
  @preset "standard";
79
- @source "./src/**/*.{ts,tsx}";
34
+ @source "./src/**/*.{ts,tsx,html}";
80
35
  @teacss;
81
36
  ```
82
37
 
83
- Add `@preset "icons";` when the app uses the official icon vocabulary.
84
- Add `@preset "articles";` for the fixed semantic-descendant utility
85
- `article:base`:
86
-
87
- ```html
88
- <article
89
- class="article:base max-inline-size:65ch m-a:auto font-size:3x text-color:$color-foreground"
90
- >
91
- <h1>Title</h1>
92
- <p>Readable long-form content.</p>
93
- </article>
94
- ```
95
-
96
- The utility defaults to TeaCSS's shared `shortcuts` layer
97
- (`LAYER_SHORTCUTS`). Under the default layer order, ordinary utilities in the
98
- `utilities` layer emit later. The preset does not create an article-specific
99
- layer.
100
-
101
- The articles factory is available only from its explicit subpath:
102
-
103
- ```ts
104
- import presetArticles, { presetArticles as namedPresetArticles } from "teacss/preset-articles";
105
- ```
106
-
107
- The root `teacss` entry does not re-export it.
108
-
109
- Import the generated stylesheet once from your app entry:
110
-
111
38
  ```ts
112
39
  import "virtual:teacss.css";
113
40
  ```
114
41
 
115
- Then write TeaCSS utilities in your markup:
116
-
117
- ```html
118
- <button class="p:4 bg-color:red-500 text-color:white bg-color:red-600@hover">
119
- Submit
120
- </button>
121
- ```
42
+ ## Presets
122
43
 
123
- The root entry also re-exports the Standard preset's constant tables for
124
- programmatic use:
44
+ Enable optional vocabularies explicitly:
125
45
 
126
- ```ts
127
- import { breakpointKeywords, primaryColors } from "teacss";
46
+ ```css
47
+ @preset "standard";
48
+ @preset "shortcuts";
49
+ @preset "icons";
128
50
  ```
129
51
 
130
- These are the same exports as `@teacss/preset-standard/constants`; there is no
131
- separate `teacss/constants` subpath.
52
+ Shortcuts includes `prose`, `prose-hans` and `prose-hant` for long-form content;
53
+ the separate Articles preset is retired. Shortcuts does not enable Standard. All preset factories are available from
54
+ subpaths:
132
55
 
133
- Grouped utilities can share the same condition:
134
-
135
- ```html
136
- <button class="{p:4;text-color:white;bg-color:red-500}@hover">
137
- Submit
138
- </button>
139
- ```
56
+ | Import | Export |
57
+ | ------------------------- | ------------------- |
58
+ | `teacss/preset-standard` | `presetStandard` |
59
+ | `teacss/preset-shortcuts` | `presetShortcuts` |
60
+ | `teacss/preset-icons` | `presetIcons` |
61
+ | `teacss/core` | Core engine exports |
140
62
 
141
- ## Runtime Recipes
142
-
143
- The application entry exports `recipe`, bound once to its exact official
144
- `cn`:
63
+ ## Runtime classes
145
64
 
146
65
  ```ts
147
- import { recipe, type ClassProp, type VariantProps } from "teacss";
66
+ import { cn, recipe, type ClassProp, type VariantProps } from "teacss";
67
+
68
+ cn("p:4 d:flex", "p:8"); // "d:flex p:8"
148
69
 
149
70
  const badge = recipe({
150
- className: "d:inline-flex align-items:center rd:full p-x:2",
71
+ className: "d:inline-flex p:2",
151
72
  variants: {
152
- tone: {
153
- neutral: "bg-color:gray-100 text-color:gray-900",
154
- accent: "bg-color:blue-500 text-color:white",
155
- },
73
+ tone: { accent: "bg-color:blue-500 text-color:white" },
156
74
  },
157
- compoundVariants: [
158
- {
159
- tone: "accent",
160
- className: "font-weight:700",
161
- },
162
- ],
163
75
  });
164
76
 
165
- badge({
166
- tone: "accent",
167
- className: "p-x:3",
168
- }); // string
169
-
170
77
  type BadgeProps = VariantProps<typeof badge> & ClassProp;
171
-
172
- function badgeClassName({ className, ...variants }: BadgeProps) {
173
- return badge({ ...variants, className });
174
- }
175
- ```
176
-
177
- A primitive string top-level `className` value selects the single-element form.
178
- Its variant choices and compound outputs are strings; the recipe call accepts
179
- variants plus caller `className` and returns the merged string directly.
180
-
181
- Use a non-empty object top-level `className` value for multiple elements:
182
-
183
- ```ts
184
- const button = recipe({
185
- className: {
186
- container: "d:inline-flex align-items:center p:2 p:4@md",
187
- icon: "inline-size:4x",
188
- },
189
- variants: {
190
- size: {
191
- small: {
192
- container: "p:2",
193
- icon: "inline-size:3x",
194
- },
195
- large: {
196
- container: "p:4",
197
- icon: "inline-size:5x",
198
- },
199
- },
200
- disabled: {
201
- true: {
202
- container: "opacity:50 pointer-events:none",
203
- },
204
- },
205
- },
206
- defaultVariants: {
207
- size: "small",
208
- disabled: false,
209
- },
210
- compoundVariants: [
211
- {
212
- size: "large",
213
- disabled: true,
214
- className: {
215
- container: "font-weight:700",
216
- icon: "inline-size:6x",
217
- },
218
- },
219
- {
220
- disabled: true,
221
- classKeys: ["container", "icon"],
222
- className: "opacity:80",
223
- },
224
- ],
225
- });
226
-
227
- const classes = button({
228
- size: "large",
229
- });
230
-
231
- classes.container({
232
- disabled: true,
233
- className: "p:6",
234
- });
235
- classes.icon();
236
-
237
- type ButtonProps = VariantProps<typeof button> & ClassProp;
238
-
239
- function buttonClassName({ className, ...variants }: ButtonProps) {
240
- return button(variants).container({ className });
241
- }
242
78
  ```
243
79
 
244
- There is no distinguished or required `root` key in an object-form top-level
245
- `className`; every declared key is an ordinary named class. Variant choices are
246
- always target maps. A compound either supplies a non-empty `className` target
247
- map, or pairs a primitive-string `className` with a non-empty `classKeys` array
248
- to broadcast that class to several effective named classes. `classKeys` may
249
- name declared or inherited classes and must be dense, unique, and free of
250
- unknown names. The two compound forms are mutually exclusive, and matching
251
- entries contribute in declaration order. A recipe call returns a readonly
252
- resolver for every name.
253
- Recipe-level selections are captured once. A resolver selection is local to
254
- that invocation, compounds are re-evaluated for it, and `className` appends only
255
- to that resolver. The one-sided `"true"` choice makes `disabled`
256
- boolean-capable: boolean `false` is a branchless state that contributes no
257
- fragment but can still drive defaults and compounds. Responsive behavior
258
- remains suffix-only inside static values, such as `p:4@md`; recipe props do not
259
- accept breakpoint objects.
260
-
261
- Every definition without `extend` requires its own `className` field. An
262
- extending child may omit `className` to inherit the parent's string or object
263
- mode, base fragments, and existing named classes. If a child declares
264
- `className`, it must keep that mode; an object child may add new names:
265
-
266
- ```ts
267
- const primaryButton = recipe({
268
- extend: button,
269
- variants: {
270
- emphasis: {
271
- strong: {
272
- container: "font-weight:700",
273
- },
274
- },
275
- },
276
- });
277
-
278
- const strongBadge = recipe({
279
- extend: badge,
280
- className: "font-weight:700",
281
- });
282
- ```
283
-
284
- `classKeys` is reserved as a variant name, while `parts`, `styles`, and
285
- `styleKeys` are available as ordinary variant names. Nested
286
- `compoundVariants[].classKeys` is supported; the retired top-level definition
287
- field `styles` and former nested `parts` selector are not compatibility aliases.
288
-
289
- The repeated `className` spelling is separated by boundary:
290
- `definition.className` supplies base classes and selects string or object mode,
291
- `compoundVariants[].className` supplies a compound output, and caller
292
- `className` is accepted by a single-element recipe call or one named resolver.
293
- A multi-element recipe call itself accepts shared selections only.
294
-
295
- `@teacss/classes` exports the factory rather than a pre-bound reciper. This
296
- integration creates its own `recipe` from the official `cn`; custom
297
- integrations follow the same boundary with their own merger:
298
-
299
- ```ts
300
- import { createReciper, createMerger } from "@teacss/classes";
301
-
302
- const merge = createMerger({ conflicts, plugins });
303
- export const recipe = createReciper({ merge });
304
- ```
305
-
306
- `createReciper` and its type-only `Reciper` return type are intentionally
307
- available only from `@teacss/classes`; the named return type keeps declarations
308
- for exported integration-owned recipers compact. Normal recipe libraries
309
- peer-depend on and externalize `teacss`. A custom integration peer-depends on
310
- `@teacss/classes` and exports the exact reciper used for extendable parents.
311
- Consumers deduplicate the owning integration. Recreating a reciper, loading
312
- another runtime copy or version, or resolving the parent and reciper from
313
- different provider-package instances breaks extension identity even if the
314
- declarations and merger are compatible. Deduplicating only `@teacss/classes`
315
- is insufficient for a duplicated custom-reciper provider. `VariantProps`
316
- extraction does not need runtime identity; `extend` does.
317
-
318
- ## Runtime Class Merging
319
-
320
- Use the application runtime merger for component class names. It understands the
321
- standard vocabulary and canonical `icon:<collection>-<icon-name>` utilities:
322
-
323
- ```ts
324
- import { cn } from "teacss";
325
-
326
- cn("p:4 d:flex", "p:8"); // "d:flex p:8"
327
- cn("p:4", "p:invalid"); // "p:invalid"
328
- cn("reset-list", "reset-heading"); // "reset-heading"
329
- cn("d:block", "reset-list"); // "d:block reset-list"
330
- ```
331
-
332
- The default `cn` is one direct merger composed from `pluginStandard` and
333
- `pluginIcon`; it does not chain preset-local mergers. Resolution is based
334
- on parsed shape, conditions, importance, and declared footprints. It does not
335
- validate values, so an unsupported winner may emit no CSS. The eight reset
336
- profiles apply to the current element and are bare class names, never
337
- `property:value` utilities: `reset-heading`, `reset-list`, `reset-button`,
338
- `reset-select`, `reset-textarea`, `reset-input`, `reset-checkbox`, and
339
- `reset-radio`. `reset-input` is only for text-like inputs; button-like input
340
- types use `reset-button`, and box controls take `reset-checkbox` /
341
- `reset-radio`.
342
- Element deltas expressible with ordinary utilities carry no profile — use
343
- `text-color:inherit decoration-line:none` for a link and
344
- `d:block text-align:unset` for a list item. Profiles replace one another as a
345
- single opaque family and never delete an unrelated utility. Document-root and shadow-host
346
- defaults come from the standard preset's automatic preflight.
347
-
348
- Generic class merging is a separate package for custom conflict metadata:
349
-
350
- Install `@teacss/classes` with the project's package manager.
351
-
352
- ```ts
353
- import { createMerger } from "@teacss/classes";
354
- ```
355
-
356
- ## Status
357
-
358
- TeaCSS is currently pre-1.0 and under active development.
80
+ `cn` understands Standard and canonical icon conflicts but does not validate
81
+ values. `recipe` supports string or named-element `className` definitions,
82
+ variants, compounds, and exact-reciper extension. Import low-level factories
83
+ such as `createMerger` and `createReciper` from `@teacss/classes`.
359
84
 
360
- Syntax, configuration, package boundaries, and public APIs may change before the first stable release.
85
+ Standard constant tables are re-exported from the root; there is no
86
+ `teacss/constants` subpath.
361
87
 
362
- ## License
88
+ Pre-1.0. Syntax, configuration, and APIs may change before the stable release.
363
89
 
364
- MIT. See [LICENSE](LICENSE).
90
+ [MIT](LICENSE)
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ClassProp, Merger, RecipeIntrospection, Reciper, VariantProps, omitAttributes } from "@teacss/classes";
2
2
  export * from "@teacss/preset-standard/constants";
3
3
  //#region src/index.d.ts
4
- declare const cn: Merger;
5
- declare const recipe: Reciper;
4
+ export declare const cn: Merger;
5
+ export declare const recipe: Reciper;
6
6
  //#endregion
7
- export { type ClassProp, type RecipeIntrospection, type VariantProps, cn, omitAttributes, recipe };
7
+ export { type ClassProp, type RecipeIntrospection, type VariantProps, omitAttributes };
@@ -0,0 +1,3 @@
1
+ import preset_shortcuts_default from "@teacss/preset-shortcuts";
2
+ export * from "@teacss/preset-shortcuts";
3
+ export { preset_shortcuts_default as default };
@@ -0,0 +1 @@
1
+ import e from"@teacss/preset-shortcuts";export*from"@teacss/preset-shortcuts";export{e as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teacss",
3
- "version": "0.4.6",
3
+ "version": "0.5.0",
4
4
  "description": "The TeaCSS application entry with the official `cn`, `recipe`, engine, and preset subpaths.",
5
5
  "homepage": "https://css.teasim.com",
6
6
  "funding": "https://github.com/sponsors/billgo",
@@ -11,8 +11,8 @@
11
11
  "exports": {
12
12
  ".": "./dist/index.js",
13
13
  "./core": "./dist/core.js",
14
- "./preset-articles": "./dist/preset-articles.js",
15
14
  "./preset-icons": "./dist/preset-icons.js",
15
+ "./preset-shortcuts": "./dist/preset-shortcuts.js",
16
16
  "./preset-standard": "./dist/preset-standard.js",
17
17
  "./package.json": "./package.json"
18
18
  },
@@ -26,11 +26,11 @@
26
26
  "dev": "tsdown --watch"
27
27
  },
28
28
  "dependencies": {
29
- "@teacss/classes": "0.4.6",
30
- "@teacss/core": "0.4.6",
31
- "@teacss/preset-articles": "0.4.6",
32
- "@teacss/preset-icons": "0.4.6",
33
- "@teacss/preset-standard": "0.4.6"
29
+ "@teacss/classes": "0.5.0",
30
+ "@teacss/core": "0.5.0",
31
+ "@teacss/preset-icons": "0.5.0",
32
+ "@teacss/preset-shortcuts": "0.5.0",
33
+ "@teacss/preset-standard": "0.5.0"
34
34
  },
35
35
  "engines": {
36
36
  "node": ">=22.12.0"
@@ -1,3 +0,0 @@
1
- import preset_articles_default from "@teacss/preset-articles";
2
- export * from "@teacss/preset-articles";
3
- export { preset_articles_default as default };
@@ -1 +0,0 @@
1
- import e from"@teacss/preset-articles";export*from"@teacss/preset-articles";export{e as default};