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