cx, cn, cvcssints itself. import { cx } from "cssints" has no attribute and is the only code that ships to the browser, together with the few lines the plugin puts in place of each cv(). @cssints/variants is gone.cx(...) joins strings, skips falsy values and flattens nested arrays: cx(base, on && p(4), [a, b]). It takes no clsx-style objects; write cond && style instead.cn(...) runs at build time only. Under the attribute, cn(p(4), bg("red")) becomes one class string, and nothing is left at runtime.cv(config) takes css.* values, so types check them, and is the function you call: one call, no wrapper. The plugin replaces the site by a call of the small runtime (and imports it for you; _cv is not exported any more) with a config of class strings. The props are typed from variants: a name or a value that is not there is a type error, in the props and in defaultVariants and compoundVariants alike.import { const cn: (...styles: Style[]) => Stylecn, const cv: <V extends Record<string, Record<string, Style>> = Record<never, never>>(config: CvConfig<V>) => (props?: CvProps<V>) => stringThe plugin replaces the call by a runtime function of class strings: `button({ size: "lg" })` gives the class names.cv, const fontSize: Prop<"font-size">`<absolute-size> | <relative-size> | <length-percentage [0,∞]> | math`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/font-size)fontSize, const opacity: Prop<"opacity">`<opacity-value>`. Chrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/opacity)opacity, const p: Prop<"padding">`<'padding-top'>{1,4}`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/padding)p } from "cssints" with { type: "cssints" };
const const button: (props?: CvProps<{
size: {
sm: Style;
lg: Style;
};
disabled: {
true: Style;
false: Style;
};
}> | undefined) => string
button = cv<{
size: {
sm: Style;
lg: Style;
};
disabled: {
true: Style;
false: Style;
};
}>(config: CvConfig<{
size: {
sm: Style;
lg: Style;
};
disabled: {
true: Style;
false: Style;
};
}>): (props?: CvProps<{
size: {
sm: Style;
lg: Style;
};
disabled: {
true: Style;
false: Style;
};
}> | undefined) => string
The plugin replaces the call by a runtime function of class strings: `button({ size: "lg" })` gives the class names.cv({
CvConfig<V extends Record<string, Record<string, Style>>>.base?: Style | undefinedbase: function cn(...styles: Style[]): Stylecn(p<readonly [2]>(parts_0: 2): Style`<'padding-top'>{1,4}`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/padding)p(2), fontSize<readonly ["1rem"]>(parts_0: "1rem"): Style`<absolute-size> | <relative-size> | <length-percentage [0,∞]> | math`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/font-size)fontSize("1rem")),
CvConfig<{ size: { sm: Style; lg: Style; }; disabled: { true: Style; false: Style; }; }>.variants?: {
size: {
sm: Style;
lg: Style;
};
disabled: {
true: Style;
false: Style;
};
} | undefined
variants: {
size: {
sm: Style;
lg: Style;
}
size: { sm: Stylesm: p<readonly [1]>(parts_0: 1): Style`<'padding-top'>{1,4}`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/padding)p(1), lg: Stylelg: function cn(...styles: Style[]): Stylecn(p<readonly [4]>(parts_0: 4): Style`<'padding-top'>{1,4}`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/padding)p(4), fontSize<readonly ["1.25rem"]>(parts_0: "1.25rem"): Style`<absolute-size> | <relative-size> | <length-percentage [0,∞]> | math`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/font-size)fontSize("1.25rem")) },
disabled: {
true: Style;
false: Style;
}
disabled: { true: Styletrue: opacity<readonly [0.5]>(parts_0: 0.5): Style`<opacity-value>`. Chrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/opacity)opacity(0.5), false: Stylefalse: opacity<readonly [1]>(parts_0: 1): Style`<opacity-value>`. Chrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/opacity)opacity(1) },
},
CvConfig<{ size: { sm: Style; lg: Style; }; disabled: { true: Style; false: Style; }; }>.defaultVariants?: CvProps<NoInfer<{
size: {
sm: Style;
lg: Style;
};
disabled: {
true: Style;
false: Style;
};
}>> | undefined
defaultVariants: { size?: "sm" | "lg" | undefinedsize: "sm", disabled?: boolean | undefineddisabled: false },
CvConfig<{ size: { sm: Style; lg: Style; }; disabled: { true: Style; false: Style; }; }>.compoundVariants?: (CvProps<NoInfer<{
size: {
sm: Style;
lg: Style;
};
disabled: {
true: Style;
false: Style;
};
}>> & {
class: Style;
})[] | undefined
Styles added when every value named here is active, and that win over the variants they combine.compoundVariants: [{ size?: "sm" | "lg" | undefinedsize: "lg", disabled?: boolean | undefineddisabled: true, class: Styleclass: opacity<readonly [0.3]>(parts_0: 0.3): Style`<opacity-value>`. Chrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/opacity)opacity(0.3) }],
});
export const const classes: () => stringclasses = () => const button: (props?: CvProps<{
size: {
sm: Style;
lg: Style;
};
disabled: {
true: Style;
false: Style;
};
}> | undefined) => string
button({ size?: "sm" | "lg" | undefinedsize: "lg" }); // "_lwugp7 _z6yj9k _1t0bw2x"
export const const off: () => stringoff = () => const button: (props?: CvProps<{
size: {
sm: Style;
lg: Style;
};
disabled: {
true: Style;
false: Style;
};
}> | undefined) => string
button({ size?: "sm" | "lg" | undefinedsize: "lg", disabled?: boolean | undefineddisabled: true });
export const const bad: () => stringbad = () => const button: (props?: CvProps<{
size: {
sm: Style;
lg: Style;
};
disabled: {
true: Style;
false: Style;
};
}> | undefined) => string
button({ size: "xl" }); // error: not a sizeexport const const bad2: (props?: CvProps<Record<never, never>> | undefined) => stringbad2 = cv<Record<never, never>>(config: CvConfig<Record<never, never>>): (props?: CvProps<Record<never, never>> | undefined) => stringThe plugin replaces the call by a runtime function of class strings: `button({ size: "lg" })` gives the class names.cv({ base: "padding: 1rem" }); // error: a base is a css value, not a CSS stringWhat ships for button is __cv({ base: "_1t8gqy5 _6tpir7", variants: { size: { sm: "_lqk467", lg: "_lwugp7 _z6yj9k" }, ... }, defaultVariants: { size: "sm", disabled: false }, ... }) with import { _cv as __cv } from "cssints" added to the module: class strings only. cv() works in a function, at the top of a module and in a library.
Old code. import { _cv } from "cssints" is a type error (no such export) and, in a module the plugin handles, a build error at the import: cssints: <file> imports _cv from "cssints", which is gone: cv({ ... }) is the function now. Write const button = cv({ base, variants }) .... It does not keep working for a release: _cv(cv(...)) would hand a function to the runtime, and a shim would keep two spellings of one thing. The fix is mechanical: drop _cv( and its closing bracket. A library built the old way fails with the same error, naming its file.
Boolean variants. A variant whose keys are true and false (or only one of them) takes a boolean: button({ disabled: true }), and a default is a boolean too. false is a value, not a missing one: button({ disabled: false }) selects the false key even when the default is true. undefined is the default.
compoundVariants as in cva: each entry names values (any of the variants, a boolean for a boolean one) and the style that is added when all of them are active. The key is class, as in cva, since what the entry adds is a class (a cx or style() key would suggest an inline style, and cssints has style() for that; css is the namespace). Its value is a css.* style like the others, not a string. The values of an entry are one value each, not a list of values.
Values of base and of each variant are one property, cn(...), or a flex()/grid() chain. A CSS string is a build error that shows the new form: cv() base must be a css.* value (cn(...), a flex() chain or one property), got "padding: 1rem". CSS strings are gone: write cn(p(4), fontSize("1rem")).
The variant wins. The function joins the base and the variants that are active at runtime, so the build compares them. Under one condition, a variant that sets what the base sets (the same property, an alias, or a shorthand over a base longhand: pl(2) in the base, p(4) in the variant) replaces it: the base class is dropped from the string while that value is active, which the runtime does from a drops entry in the config (drops: { size: { lg: "_77ujlx" } }, only where there is one). Which rule comes later in the sheet does not decide. A variant longhand inside a base shorthand needs no drop, since the sheet puts a longhand after its shorthand: base border(...) with active: { yes: borderBottomColor(...) } is fine. Under different conditions both stay, as in cn().
Overlap is an error, as in cn(). A base property and a variant property that overlap without one containing the other are a build error at the cv() call: cssints: cv() base and variant active.yes: border-bottom and border-color overlap without one containing the other, so the sheet cannot order them: set one of them, or the longhands (both set border-bottom-color; write borderBottomColor in the variant). The same holds for two variants of different keys, which can be active together. Two such variants that set the same property are an error too, since nothing says which wins: cssints: cv() variants a.x and b.x both set color and can be active together, so nothing says which wins: set it in one of them, or in the base. Values of one key are never compared, since only one is active.
A compound wins over what it combines. It is the most specific style, so under one condition it replaces what it sets again in the base and in the variant values it names (the same rule as a variant over the base): compoundVariants: [{ size: "lg", tone: "loud", class: p(6) }] drops the base's padding, size.lg's padding and tone.loud's padding while both are active, in the compound entry of the config ({ when: { size: "lg", tone: "loud" }, class: "_x", drops: "_a _b" }). The sheet order never decides. What a compound shares with other things that can be active together is compared as for variants: an overlap without containment is an error, and so is the same property in a compound and a variant of a key it does not name (it is active with any of its values), or in two compounds that can be active together (no key they both name with different values). Write the property in one of them, or in the base.
Slot variants (scv) are not part of 0.1.