@teacss/preset-standard
v0.4.3
Published
The standard utility vocabulary for TeaCSS — spacing, sizing, color, layout, typography, and more.
Readme
@teacss/preset-standard
The standard TeaCSS vocabulary.
Purpose
@teacss/preset-standard is the official general-purpose vocabulary for
application authors who want TeaCSS utilities for layout, spacing, sizing,
typography, color, interaction, and related everyday CSS. It provides the
preset factory, theme defaults, condition aliases, shortcuts, preflights,
public value constants, and Standard-specific class-merge metadata.
This package defines vocabulary and preset behavior, not the engine or config
loader: @teacss/core owns parsing, rule matching, and CSS generation, while
@teacss/config resolves CSS-entry directives for integrations. The
article:base long-form content utility and the
icon:<collection>-<icon> vocabulary remain opt-in features of
@teacss/preset-articles and @teacss/preset-icons; this preset does not
bundle either one.
Usage
bun add @teacss/preset-standard@preset "standard";
@source "./src/**/*.{ts,tsx}";
@teacss;import { cn } from "@teacss/preset-standard/merge";
cn("p:4 d:flex", "p:8"); // "d:flex p:8"
cn("p:4", "p:invalid"); // "p:invalid"
cn("reset-list", "reset-heading"); // "reset-heading"
cn("float:left", "reset-list"); // "float:left reset-list"
cn("reset-list", "float:left"); // "reset-list float:left"Property value constants are available from the dedicated public entry:
import { boxDecorationValues, globalKeywords, multiplierKeywords } from "@teacss/preset-standard/constants";Each *Values export contains only the property's common values.
globalKeywords is exported separately; the preset's rule layer adds those
CSS-wide keywords centrally at runtime. multiplierKeywords is the supported
name for the 1x through 9x scale; the misspelled multiplerKeywords export
remains as a deprecated compatibility alias.
Layout Shortcuts
Official preset-owned shortcuts use bare class names without :. This preset
includes four fixed, theme-neutral flexbox shortcuts:
| Shortcut | Expansion |
| --- | --- |
| hstack | d:flex flex-direction:row align-items:center |
| vstack | d:flex flex-direction:column |
| centered | d:flex align-items:center justify-content:center |
| inline-centered | d:inline-flex align-items:center justify-content:center |
They emit in the built-in shortcuts layer. Compose spacing, sizing, wrapping,
and responsive changes with ordinary utilities; the later utilities layer can
override a shortcut default:
<div class="hstack gap:3x flex-direction:column@sm">
...
</div>The four layout shortcuts are one mutually exclusive merge family when their conditions and importance are equal. They add no gap, size, wrapping, theme, or component styling.
Text Shortcut
truncate is the fixed single-line truncation Shortcut:
truncate -> overflow:hidden text-overflow:ellipsis white-space:nowrapIt emits in the built-in shortcuts layer, so later ordinary utilities can
override any default. The property-shaped text-overflow:truncate spelling is
unmatched; use text-overflow:clip or text-overflow:ellipsis when only the
native marker should change.
Skeleton Shortcut
skeleton is the fixed visual loading-placeholder Shortcut. It has this exact
TeaCSS expansion:
rd:1x
border-style:none!
bg-image:none!
bg-clip:border-box!
shadow:none!
box-decoration-break:clone!
text-color:transparent!
outline-style:none!
user-select:none!
pointer-events:none!
cursor:default!
animation:skeleton!
vis:hidden!@::after
vis:hidden!@::before
vis:hidden!@>*
d:block@empty
h:3x@empty
rd-l:inherit@[:where(:first-child)]
rd-r:inherit@[:where(:nth-last-child(2))]
line-height:1@[:where([data-inline-skeleton])]
font-family:sans@[:where([data-inline-skeleton])]Use the bare class on an empty block placeholder or on an inline placeholder whose text supplies its shape:
<div class="skeleton" aria-hidden="true"></div>
<span class="skeleton" data-inline-skeleton aria-hidden="true">Loading</span>Empty skeletons become blocks with a 3x height. Direct children and the two
pseudo-elements are hidden, and data-inline-skeleton applies a direct line
height of 1 plus the standard sans family. The structural conditions inherit
the left radius on a first child and the right radius on a second-to-last
child. animation:skeleton! reuses the standard gray skeleton animation.
Core emits these components in rule-priority order, so the generated CSS uses
several .skeleton rules instead of one contiguous block. The
@keyframes skeleton rule remains top-level and unconditional: outer
conditions and ! apply only to the shortcut declarations, and later
interaction-reset rules may appear after the keyframes.
The Shortcut emits in the built-in shortcuts layer. Its important visual
reset declarations intentionally resist ordinary non-important utilities;
non-important radius, empty sizing, and inline typography declarations retain
normal layer precedence. CSS does not add loading or accessibility semantics,
so components remain responsible for aria-busy, aria-hidden, inert, and
replacement-content behavior where appropriate. There are no skeleton:*
variants or compatibility aliases.
Arrow Shortcuts
Two families draw a directional mark on the element's ::after.
chevron-up, chevron-down, chevron-left, and chevron-right are stroked: a
square showing only its right and bottom borders, so the visible ink is one
corner, rotated until that corner points where the name says. The corner rests
pointing south-east and rotate turns clockwise, so chevron-down is 45deg and
each further quarter turn moves one step round.
triangle-up, triangle-down, triangle-left, and triangle-right are solid:
the same box filled and clipped to three corners. clip-path rather than the
zero-size border trick, so w and h still mean the mark's size and bg-color
still means its color, and both families compose with the same utilities.
<span class="chevron-right">Continue</span>
<span class="triangle-down">More</span>The mark follows the surrounding text color, and display:inline-block sizes it
on an ordinary inline host rather than only inside a flex row. Neither family
carries spacing, opacity, or a size beyond the square.
Every declaration lands on the host's ::after, so a utility aimed at the mark
carries an @::after condition; a bare one styles the host box instead. The
mark inherits the host's color, so text-color: needs no condition:
<span class="hstack gap:2x triangle-right w:4@::after opacity:80@::after">More</span>
<span class="triangle-up text-color:red-700">Rising</span>transition-property:transform covers rotate in this preset, so a state that
re-rotates a mark animates, and motion-reduce turns that off. All eight are one
mutually exclusive merge family, because they own the same ::after:
cn("chevron-up", "triangle-down") keeps only the later.
Preflight
The standard preset emits a low-specificity foundational reset and its theme
CSS variables by default. The reset applies border-box sizing to every
element, its ::before and ::after pseudo-elements, and ::backdrop; it also
sets every element's margin and padding to zero and establishes a zero-width
solid border. The document root and shadow host receive a 1.5 line height,
text-size and tab normalization, the configurable --font-family-sans stack,
normal font feature and variation settings, and a transparent tap highlight. In
the programmatic preset API,
preflight: false disables both. preflight: "on-demand" keeps the foundational
reset while limiting theme variables to keys referenced by generated utilities
or by the reset itself.
The reset profiles apply explicit element-specific deltas on top of that
foundational preflight. They are preset-owned shortcuts with bare class names,
never property:value utilities: reset is not a CSS property, and each
profile is an opaque bundle whose output cannot be inferred from its name.
They expand to declarations rather than to a token list because no token
spells -webkit-appearance, font: inherit, font: unset, or the
list-style shorthand.
| Profile | Emits |
| --- | --- |
| reset-heading | font: unset |
| reset-list | list-style: none |
| reset-button, reset-select, reset-textarea, reset-input | native-control neutralization |
| reset-checkbox, reset-radio | box-control neutralization, square or round |
A profile exists only where ordinary utilities cannot express the delta:
reset-heading needs the font shorthand, reset-list the list-style
shorthand, and the control profiles -webkit-appearance and font: inherit.
reset-checkbox and reset-radio drop the typography half of the control
bundle — a void element renders no text — and differ only by the radius that
keeps each shape.
Element deltas that are plain token combinations carry no profile — write
text-color:inherit decoration-line:none for a link and
d:block text-align:unset for a list item.
The deltas remove selected browser defaults with explicit declarations without
repeating the preflight's shared box-model, spacing, border, or inherited
tap-highlight baseline. They do not expose a generic CSS all reset, emit
focus/state/placeholder selector rules, or reset outline. Use
reset-input only on text-like inputs, use reset-button for button-like
input types, and use reset-checkbox / reset-radio for those two. Other
specialized controls such as file, range, and color inputs have no profile:
their native rendering is not a shared shape, so compose the declarations the
design actually needs.
This is a TeaCSS-specific subset inspired by the
Radix Themes 3.3.0 Reset,
adapted to named atomic profiles and TeaCSS merge semantics rather than copied
as a component class. These element-specific rules are not emitted by the
preflight. They still generate when preflight: false disables the automatic
baseline, but then emit only the element-specific delta; provide an equivalent
baseline when a complete reset is required. Root and shadow-host defaults are
preflight-only.
The merger uses parsed utility shape and declared footprints; it does not ask the generator whether a value is supported. An unsupported or empty later value can therefore replace an earlier token and then emit no CSS. Reset profiles form one opaque merge family: one profile can replace another, but the merger does not expand their declarations into conflicts with unrelated utilities. An important utility removes a non-important overlap only when its footprint fully covers the token being removed; partial shorthand/longhand overlaps survive.
The /merge entry exports the self-contained pluginStandard, a lazy
standard-only cn, and the compatibility createStandardMerger() factory.
pluginStandard publishes resolver-family scope metadata so unrelated repeated
static prefixes stay on the linear merge path.
Compose official plugins directly when building a unified merger:
bun add @teacss/classes @teacss/preset-iconsimport { createMerger } from "@teacss/classes";
import { pluginIcon } from "@teacss/preset-icons/merge";
import { pluginStandard } from "@teacss/preset-standard/merge";
const cn = createMerger({ plugins: [pluginStandard, pluginIcon] });Existing code may still use
createStandardMerger({ plugins: [pluginIcon] }); it delegates to that
same direct plugin composition without hidden transforms or metadata. The
zero-config cn from this package remains standard-only. The application
cn from teacss includes the official icon plugin by default.
Vocabulary
The preset covers layout, spacing, sizing, positioning, typography, color, border, shadow, transform, transition, animation, SVG, accessibility, and interaction utilities.
Bare keywords are a closed standard-preset vocabulary:
hstack vstack centered inline-centered
truncate skeleton
chevron-up chevron-down chevron-left chevron-right
triangle-up triangle-down triangle-left triangle-right
sr-only sr-visible
transition-none transition-all transition-colors transition-opacity transition-shadow transition-transform
reset-heading reset-list
reset-button reset-select reset-textarea reset-input
reset-checkbox reset-radio
mask-g-linear mask-g-radial mask-g-conic
divide-x divide-y
space-x-reverse space-y-reverse space-a-reverse space-c-reverseThe layout keywords are fixed shortcuts. truncate is the fixed single-line
text Shortcut, and skeleton is the fixed visual loading-placeholder Shortcut.
sr-only and sr-visible are the fixed screen-reader visibility Shortcuts.
The transition-* keywords are fixed transition presets that expand to
transition-property:<preset> transition-timing:ease transition-duration:150.
The mask keywords activate additive generated-mask families. The divide
keywords create 1px physical separators. The spacing keywords are independent
reverse modifiers that coexist with space-*:<size>. Do not infer other bare
utilities from CSS keywords.
Withdrawn draft property names are not retained as compatibility utilities.
Use scroll-initial-target:*, not scroll-start-target:*; the removed Grid 3
proposal names item-direction:*, item-track:*, item-wrap:*,
item-cross:*, and item-pack:* generate no CSS.
Values support theme references, arbitrary values, CSS-wide keywords, the
trailing ! important marker, and stacked @ conditions.
Conditions are suffix-only: write p:4@hover or content:empty@::before, not
property-side forms such as hover:p:4 or before:content:empty.
Representable suffix/self conditions, query-bearing at-rule parents, and media
types such as @!print support @! negation. Prefix relations/direction, target
combinators, pseudo-elements, and at-rules without a negatable prelude such as
@starting-style remain unmatched when negated.
Color theme data is split into colors for stepped palette tokens such
as --color-red-500 and semanticColors for role tokens such as
--color-background, --color-foreground, --color-border, and
--color-emphasis. Mode
overrides can define either namespace.
Status
Pre-1.0. Keep tests and docs aligned when adding or changing utilities.
