@teacss/preset-standard 0.4.7 → 0.5.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 CHANGED
@@ -1,22 +1,9 @@
1
1
  # @teacss/preset-standard
2
2
 
3
- **The standard TeaCSS vocabulary.**
3
+ The standard TeaCSS utility vocabulary, theme, conditions, and preflight.
4
4
 
5
- ## Purpose
6
-
7
- `@teacss/preset-standard` is the official general-purpose vocabulary for
8
- application authors who want TeaCSS utilities for layout, spacing, sizing,
9
- typography, color, interaction, and related everyday CSS. It provides the
10
- preset factory, theme defaults, condition aliases, shortcuts, preflights,
11
- public value constants, and Standard-specific class-merge metadata.
12
-
13
- This package defines vocabulary and preset behavior, not the engine or config
14
- loader: `@teacss/core` owns parsing, rule matching, and CSS generation, while
15
- `@teacss/config` resolves CSS-entry directives for integrations. The
16
- `article:base` long-form content utility and the
17
- `icon:<collection>-<icon>` vocabulary remain opt-in features of
18
- `@teacss/preset-articles` and `@teacss/preset-icons`; this preset does not
19
- bundle either one.
5
+ Standard intentionally owns no shortcuts. Define product compositions with
6
+ `@shortcut` or enable `@teacss/preset-official` separately.
20
7
 
21
8
  ## Usage
22
9
 
@@ -30,266 +17,78 @@ bun add @teacss/preset-standard
30
17
  @teacss;
31
18
  ```
32
19
 
33
- ```ts
34
- import { cn } from "@teacss/preset-standard/merge";
35
-
36
- cn("p:4 d:flex", "p:8"); // "d:flex p:8"
37
- cn("p:4", "p:invalid"); // "p:invalid"
38
- cn("reset-list", "reset-heading"); // "reset-heading"
39
- cn("float:left", "reset-list"); // "float:left reset-list"
40
- cn("reset-list", "float:left"); // "reset-list float:left"
41
- ```
42
-
43
- Property value constants are available from the dedicated public entry:
20
+ Programmatic consumers use `presetStandard()`. Public value tables are
21
+ available from `@teacss/preset-standard/constants`:
44
22
 
45
23
  ```ts
46
- import { boxDecorationValues, globalKeywords, multiplierKeywords } from "@teacss/preset-standard/constants";
47
- ```
48
-
49
- Each `*Values` export contains only the property's common values.
50
- `globalKeywords` is exported separately; the preset's rule layer adds those
51
- CSS-wide keywords centrally at runtime. `multiplierKeywords` is the supported
52
- name for the `1x` through `9x` scale; the misspelled `multiplerKeywords` export
53
- remains as a deprecated compatibility alias.
54
-
55
- ## Layout Shortcuts
56
-
57
- Official preset-owned shortcuts use bare class names without `:`. This preset
58
- includes four fixed, theme-neutral flexbox shortcuts:
59
-
60
- | Shortcut | Expansion |
61
- | --- | --- |
62
- | `hstack` | `d:flex flex-direction:row align-items:center` |
63
- | `vstack` | `d:flex flex-direction:column` |
64
- | `centered` | `d:flex align-items:center justify-content:center` |
65
- | `inline-centered` | `d:inline-flex align-items:center justify-content:center` |
66
-
67
- They emit in the built-in `shortcuts` layer. Compose spacing, sizing, wrapping,
68
- and responsive changes with ordinary utilities; the later `utilities` layer can
69
- override a shortcut default:
70
-
71
- ```html
72
- <div class="hstack gap:3x flex-direction:column@sm">
73
- ...
74
- </div>
75
- ```
76
-
77
- The four layout shortcuts are one mutually exclusive merge family when their
78
- conditions and importance are equal. They add no gap, size, wrapping, theme, or
79
- component styling.
80
-
81
- ## Text Shortcut
82
-
83
- `truncate` is the fixed single-line truncation Shortcut:
84
-
85
- ```txt
86
- truncate -> overflow:hidden text-overflow:ellipsis white-space:nowrap
87
- ```
88
-
89
- It emits in the built-in `shortcuts` layer, so later ordinary utilities can
90
- override any default. The property-shaped `text-overflow:truncate` spelling is
91
- unmatched; use `text-overflow:clip` or `text-overflow:ellipsis` when only the
92
- native marker should change.
93
-
94
- ## Skeleton Shortcut
95
-
96
- `skeleton` is the fixed visual loading-placeholder Shortcut. It has this exact
97
- TeaCSS expansion:
98
-
99
- ```txt
100
- rd:1x
101
- border-style:none!
102
- bg-image:none!
103
- bg-clip:border-box!
104
- shadow:none!
105
- box-decoration-break:clone!
106
- text-color:transparent!
107
- outline-style:none!
108
- user-select:none!
109
- pointer-events:none!
110
- cursor:default!
111
- animation:skeleton!
112
-
113
- vis:hidden!@::after
114
- vis:hidden!@::before
115
- vis:hidden!@>*
116
-
117
- d:block@empty
118
- h:3x@empty
119
-
120
- rd-l:inherit@[:where(:first-child)]
121
- rd-r:inherit@[:where(:nth-last-child(2))]
122
-
123
- line-height:1@[:where([data-inline-skeleton])]
124
- font-family:sans@[:where([data-inline-skeleton])]
24
+ import {
25
+ boxDecorationValues,
26
+ globalKeywords,
27
+ multiplierKeywords,
28
+ } from "@teacss/preset-standard/constants";
125
29
  ```
126
30
 
127
- Use the bare class on an empty block placeholder or on an inline placeholder
128
- whose text supplies its shape:
31
+ Each `*Values` export contains common property values. CSS-wide keywords are
32
+ separate. `multiplerKeywords` remains a deprecated alias for
33
+ `multiplierKeywords`.
129
34
 
130
- ```html
131
- <div class="skeleton" aria-hidden="true"></div>
132
- <span class="skeleton" data-inline-skeleton aria-hidden="true">Loading</span>
133
- ```
134
-
135
- Empty skeletons become blocks with a `3x` height. Direct children and the two
136
- pseudo-elements are hidden, and `data-inline-skeleton` applies a direct line
137
- height of `1` plus the standard sans family. The structural conditions inherit
138
- the left radius on a first child and the right radius on a second-to-last
139
- child. `animation:skeleton!` reuses the standard gray skeleton animation.
140
- Core emits these components in rule-priority order, so the generated CSS uses
141
- several `.skeleton` rules instead of one contiguous block. The
142
- `@keyframes skeleton` rule remains top-level and unconditional: outer
143
- conditions and `!` apply only to the shortcut declarations, and later
144
- interaction-reset rules may appear after the keyframes.
145
-
146
- The Shortcut emits in the built-in `shortcuts` layer. Its important visual
147
- reset declarations intentionally resist ordinary non-important utilities;
148
- non-important radius, empty sizing, and inline typography declarations retain
149
- normal layer precedence. CSS does not add loading or accessibility semantics,
150
- so components remain responsible for `aria-busy`, `aria-hidden`, `inert`, and
151
- replacement-content behavior where appropriate. There are no `skeleton:*`
152
- variants or compatibility aliases.
153
-
154
- ## Arrow Shortcuts
35
+ ## Application shortcuts
155
36
 
156
- Two families draw a directional mark on the element's `::after`.
157
-
158
- `chevron-up`, `chevron-down`, `chevron-left`, and `chevron-right` are stroked: a
159
- square showing only its right and bottom borders, so the visible ink is one
160
- corner, rotated until that corner points where the name says. The corner rests
161
- pointing south-east and `rotate` turns clockwise, so `chevron-down` is 45deg and
162
- each further quarter turn moves one step round.
163
-
164
- `triangle-up`, `triangle-down`, `triangle-left`, and `triangle-right` are solid:
165
- the same box filled and clipped to three corners. `clip-path` rather than the
166
- zero-size border trick, so `w` and `h` still mean the mark's size and `bg-color`
167
- still means its color, and both families compose with the same utilities.
168
-
169
- ```html
170
- <span class="chevron-right">Continue</span>
171
- <span class="triangle-down">More</span>
37
+ ```css
38
+ @shortcut hstack "d:flex flex-direction:row align-items:center";
39
+ @shortcut truncate "overflow:hidden text-overflow:ellipsis white-space:nowrap";
172
40
  ```
173
41
 
174
- The mark follows the surrounding text color, and `display:inline-block` sizes it
175
- on an ordinary inline host rather than only inside a flex row. Neither family
176
- carries spacing, opacity, or a size beyond the square.
42
+ Declarations may live in the CSS entry, imported CSS, or CSS matched by
43
+ `@source`. Conditions remain valid on use, and the last declaration of a name
44
+ wins. Programmatic shortcuts use Core's generic `UserConfig` types.
45
+
46
+ ## Preflight and themes
47
+
48
+ Preflight emits low-specificity reset rules and theme variables. Set
49
+ `preflight: false` to disable both, or `preflight: "on-demand"` to keep the
50
+ reset while limiting variables to referenced keys (including the reset's sans
51
+ and monospace families).
52
+
53
+ Selecting `@preset "standard"` also normalizes headings, links, lists, media,
54
+ tables, horizontal rules, code typography, and form-control typography. Headings
55
+ inherit size and weight; links inherit color and decoration; lists lose their
56
+ markers; images and videos fit their container without losing aspect ratio.
57
+ Use utilities or Shortcuts' `prose` family to author their visible presentation.
58
+
59
+ Small text, sub/sup, titled abbreviations, and progress have consistent baselines.
60
+ Dialogs and popovers retain native auto-margin centering after the universal
61
+ spacing reset; opening and closing remain browser-controlled.
62
+ File-selector buttons inherit input typography and color while keeping native
63
+ appearance. Fieldsets use `min-inline-size: 0` so their boxes can shrink inside
64
+ narrow containers; oversized descendants still need responsive sizing.
65
+ Grouped options in `select[multiple]` and `select[size]` retain a 20px
66
+ inline-start indent, following text direction and allowing utility overrides.
67
+ Hidden elements remain hidden despite media/summary display resets, while
68
+ `hidden="until-found"` (case-insensitive) retains native discovery behavior.
69
+ Explicit display utilities can still override this low-specificity baseline.
70
+
71
+ Native control appearance, focus outlines, disabled state, and disclosure
72
+ behavior remain intact. Marker-free semantic lists should use `role="list"`
73
+ for Safari/VoiceOver. The reset adds no brand palette or global motion policy.
74
+ Element-local `reset-*` shortcuts remain in the optional Shortcuts preset;
75
+ Standard does not register those classes.
76
+
77
+ CSS entries declare named variants with `@custom theme <name> {}`. Each emits
78
+ zero-specificity variable overrides and a dynamic `theme-<name>` class.
79
+ Preset-aware merging treats those classes as one opaque family.
80
+
81
+ ## Class merging
177
82
 
178
- Every declaration lands on the host's `::after`, so a utility aimed at the mark
179
- carries an `@::after` condition; a bare one styles the host box instead. The
180
- mark inherits the host's color, so `text-color:` needs no condition:
83
+ ```ts
84
+ import { cn, pluginStandard } from "@teacss/preset-standard/merge";
181
85
 
182
- ```html
183
- <span class="hstack gap:2x triangle-right w:4@::after opacity:80@::after">More</span>
184
- <span class="triangle-up text-color:red-700">Rising</span>
86
+ cn("p:4 d:flex", "p:8"); // "d:flex p:8"
87
+ cn("p:4", "p:invalid"); // "p:invalid"
185
88
  ```
186
89
 
187
- `transition-property:transform` covers `rotate` in this preset, so a state that
188
- re-rotates a mark animates, and `motion-reduce` turns that off. All eight are one
189
- mutually exclusive merge family, because they own the same `::after`:
190
- `cn("chevron-up", "triangle-down")` keeps only the later.
191
-
192
- ## Preflight
193
-
194
- The standard preset emits a low-specificity foundational reset and its theme
195
- CSS variables by default. The reset applies `border-box` sizing to every
196
- element, its `::before` and `::after` pseudo-elements, and `::backdrop`; it also
197
- sets every element's margin and padding to zero and establishes a zero-width
198
- solid border. The document root and shadow host receive a `1.5` line height,
199
- text-size and tab normalization, the configurable `--font-family-sans` stack,
200
- normal font feature and variation settings, and a transparent tap highlight. In
201
- the programmatic preset API,
202
- `preflight: false` disables both. `preflight: "on-demand"` keeps the foundational
203
- reset while limiting theme variables to keys referenced by generated utilities
204
- or by the reset itself.
205
-
206
- The reset profiles apply explicit element-specific deltas on top of that
207
- foundational preflight. They are preset-owned shortcuts with bare class names,
208
- never `property:value` utilities: `reset` is not a CSS property, and each
209
- profile is an opaque bundle whose output cannot be inferred from its name.
210
- They expand to declarations rather than to a token list because no token
211
- spells `-webkit-appearance`, `font: inherit`, `font: unset`, or the
212
- `list-style` shorthand.
213
-
214
- | Profile | Emits |
215
- | --- | --- |
216
- | `reset-heading` | `font: unset` |
217
- | `reset-list` | `list-style: none` |
218
- | `reset-button`, `reset-select`, `reset-textarea`, `reset-input` | native-control neutralization |
219
- | `reset-checkbox`, `reset-radio` | box-control neutralization, square or round |
220
-
221
- A profile exists only where ordinary utilities cannot express the delta:
222
- `reset-heading` needs the `font` shorthand, `reset-list` the `list-style`
223
- shorthand, and the control profiles `-webkit-appearance` and `font: inherit`.
224
- `reset-checkbox` and `reset-radio` drop the typography half of the control
225
- bundle — a void element renders no text — and differ only by the radius that
226
- keeps each shape.
227
- Element deltas that are plain token combinations carry no profile — write
228
- `text-color:inherit decoration-line:none` for a link and
229
- `d:block text-align:unset` for a list item.
230
-
231
- The deltas remove selected browser defaults with explicit declarations without
232
- repeating the preflight's shared box-model, spacing, border, or inherited
233
- tap-highlight baseline. They do not expose a generic CSS `all` reset, emit
234
- focus/state/placeholder selector rules, or reset `outline`. Use
235
- `reset-input` only on text-like inputs, use `reset-button` for button-like
236
- input types, and use `reset-checkbox` / `reset-radio` for those two. Other
237
- specialized controls such as file, range, and color inputs have no profile:
238
- their native rendering is not a shared shape, so compose the declarations the
239
- design actually needs.
240
-
241
- ## Theme Variants
242
-
243
- Named theme variants live in `theme.themes` (applications declare them with
244
- `@custom theme <name> {}` / `@custom theme <name> dark {}` in the CSS entry;
245
- the preset default is an empty record). The theme preflight emits each variant
246
- after the base `:root` and mode blocks as a zero-specificity
247
- `:where(.theme-<name>){…}` variable-override block, and each of its
248
- non-default modes last as
249
- `:where(<mode> .theme-<name>,.theme-<name>:is(<mode>),.theme-<name> <mode>){…}`
250
- with the configured mode selector — mode-above, same-element, and mode-below
251
- arrangements all covered. Toggling the single `theme-<name>` class re-skins a
252
- subtree with no regeneration; custom-property inheritance resolves nested
253
- scopes, and `preflight: "on-demand"` filters variant entries like mode
254
- entries.
255
-
256
- The bare `theme-<name>` class is a dynamic rule that matches declared variants
257
- only and emits one internal indicator declaration, `--T-theme: <name>`, so
258
- the token stays matched and devtools show the active variant; the override CSS
259
- itself comes from the preflight. Activate themes with the literal class in
260
- markup — `@apply theme-<name>` (and compile-class strings) inline only that
261
- indicator declaration, never the variant's variables. In the preset-aware merger, bare kebab
262
- `theme-*` classes form one opaque merge family like the reset profiles: a
263
- later theme class replaces an earlier one and never conflicts with ordinary
264
- property utilities. `@teacss/config` enforces the variant contract — a
265
- variant may only override values the base theme declares.
266
-
267
- This is a TeaCSS-specific subset inspired by the
268
- [Radix Themes 3.3.0 Reset](https://github.com/radix-ui/themes/blob/3.3.0/packages/radix-ui-themes/src/components/reset.css),
269
- adapted to named atomic profiles and TeaCSS merge semantics rather than copied
270
- as a component class. These element-specific rules are not emitted by the
271
- preflight. They still generate when `preflight: false` disables the automatic
272
- baseline, but then emit only the element-specific delta; provide an equivalent
273
- baseline when a complete reset is required. Root and shadow-host defaults are
274
- preflight-only.
275
-
276
- The merger uses parsed utility shape and declared footprints; it does not ask
277
- the generator whether a value is supported. An unsupported or empty later value
278
- can therefore replace an earlier token and then emit no CSS. Reset profiles form
279
- one opaque merge family: one profile can replace another, but the merger does
280
- not expand their declarations into conflicts with unrelated utilities. An
281
- important utility removes a non-important overlap only when its footprint fully
282
- covers the token being removed; partial shorthand/longhand overlaps survive.
283
-
284
- The `/merge` entry exports the self-contained `pluginStandard`, a lazy
285
- standard-only `cn`, and the compatibility `createStandardMerger()` factory.
286
- `pluginStandard` publishes resolver-family scope metadata so unrelated repeated
287
- static prefixes stay on the linear merge path.
288
- Compose official plugins directly when building a unified merger:
289
-
290
- ```sh
291
- bun add @teacss/classes @teacss/preset-icons
292
- ```
90
+ The `/merge` entry also exports `createStandardMerger()`. Merge uses token
91
+ shape and does not validate values. Combine preset plugins for a wider merger:
293
92
 
294
93
  ```ts
295
94
  import { createMerger } from "@teacss/classes";
@@ -299,65 +98,33 @@ import { pluginStandard } from "@teacss/preset-standard/merge";
299
98
  const cn = createMerger({ plugins: [pluginStandard, pluginIcon] });
300
99
  ```
301
100
 
302
- Existing code may still use
303
- `createStandardMerger({ plugins: [pluginIcon] })`; it delegates to that
304
- same direct plugin composition without hidden transforms or metadata. The
305
- zero-config `cn` from this package remains standard-only. The application
306
- `cn` from `teacss` includes the official icon plugin by default.
101
+ Native shorthands are emitted before their component overrides. For example,
102
+ `cn("border:[1px_solid_red]", "border-t-width:4")` retains both classes and
103
+ produces a 4px top border. Reversing those arguments leaves only the shorthand.
307
104
 
308
- ## Vocabulary
105
+ ## Value and composition boundaries
309
106
 
310
- The preset covers layout, spacing, sizing, positioning, typography, color,
311
- border, shadow, transform, transition, animation, SVG, accessibility, and
312
- interaction utilities.
107
+ - Logical border width/style pairs accept two arbitrary components, such as
108
+ `border-a-width:[1px_2px]`; physical x/y and single-edge forms accept one.
109
+ - `[…]` keeps structurally valid arbitrary CSS, including
110
+ `animation-name:[var(--name)]`. It does not guarantee browser support.
111
+ - Bare background/mask sizes cannot be negative.
112
+ - Border-spacing axis variables do not inherit into nested tables.
113
+ - Gradient properties are registered on demand, retaining shared fallbacks
114
+ and neutral additive-mask layers without registering unrelated families.
313
115
 
314
- Bare keywords are a closed standard-preset vocabulary:
116
+ ## Bare utilities
117
+
118
+ The closed built-in bare-token inventory is:
315
119
 
316
120
  ```txt
317
- hstack vstack centered inline-centered
318
- truncate skeleton
319
- chevron-up chevron-down chevron-left chevron-right
320
- triangle-up triangle-down triangle-left triangle-right
321
- sr-only sr-visible
322
- transition-none transition-all transition-colors transition-opacity transition-shadow transition-transform
323
- reset-heading reset-list
324
- reset-button reset-select reset-textarea reset-input
325
- reset-checkbox reset-radio
326
121
  mask-g-linear mask-g-radial mask-g-conic
327
122
  divide-x divide-y
328
123
  space-x-reverse space-y-reverse space-a-reverse space-c-reverse
329
124
  ```
330
125
 
331
- The layout keywords are fixed shortcuts. `truncate` is the fixed single-line
332
- text Shortcut, and `skeleton` is the fixed visual loading-placeholder Shortcut.
333
- `sr-only` and `sr-visible` are the fixed screen-reader visibility Shortcuts.
334
- The `transition-*` keywords are fixed transition presets that expand to
335
- `transition-property:<preset> transition-timing:ease transition-duration:150`.
336
- The mask keywords activate additive generated-mask families. The divide
337
- keywords create `1px` physical separators. The spacing keywords are independent
338
- reverse modifiers that coexist with `space-*:<size>`. Do not infer other bare
339
- utilities from CSS keywords.
340
-
341
- Withdrawn draft property names are not retained as compatibility utilities.
342
- Use `scroll-initial-target:*`, not `scroll-start-target:*`; the removed Grid 3
343
- proposal names `item-direction:*`, `item-track:*`, `item-wrap:*`,
344
- `item-cross:*`, and `item-pack:*` generate no CSS.
345
-
346
- Values support theme references, arbitrary values, CSS-wide keywords, the
347
- trailing `!` important marker, and stacked `@` conditions.
348
- Conditions are suffix-only: write `p:4@hover` or `content:empty@::before`, not
349
- property-side forms such as `hover:p:4` or `before:content:empty`.
350
- Representable suffix/self conditions, query-bearing at-rule parents, and media
351
- types such as `@!print` support `@!` negation. Prefix relations/direction, target
352
- combinators, pseudo-elements, and at-rules without a negatable prelude such as
353
- `@starting-style` remain unmatched when negated.
354
-
355
- Color theme data is split into `colors` for stepped palette tokens such
356
- as `--color-red-500` and `semanticColors` for role tokens such as
357
- `--color-background`, `--color-foreground`, `--color-border`, and
358
- `--color-emphasis`. Mode
359
- overrides can define either namespace.
360
-
361
- ## Status
126
+ All other Standard utilities use `property:value`. Values are prefix-specific
127
+ and may support theme references, arbitrary values, CSS-wide keywords, `!`, and
128
+ trailing conditions.
362
129
 
363
- Pre-1.0. Keep tests and docs aligned when adding or changing utilities.
130
+ Pre-1.0. Keep tests and documentation aligned when changing vocabulary.