add-class-values
v0.1.0
Published
Compose deduplicated CSS class names from typed values
Maintainers
Readme
add-class-values
A zero-dependency TypeScript utility for composing CSS class names from strings, numbers, arrays, objects, and functions. It removes duplicate tokens while preserving their original order.
Installation
npm install add-class-valuesThe package includes TypeScript declarations and works with both ES modules and CommonJS.
Basic usage
import { addClass } from "add-class-values";
const className = addClass(
"button",
"button-primary",
{ "is-disabled": false, "is-active": true },
["button-large", null, undefined],
);
// "button button-primary is-active button-large"The first argument is the base class string. Every following argument can be:
| Value | Behavior |
| --- | --- |
| string | Split on whitespace and add every token |
| number | Convert to a string, including 0 |
| false, null, undefined | Ignore |
| object | Add keys whose values are truthy |
| array | Recursively process every item |
| function | Call it and recursively process its return value |
Boolean true is intentionally not accepted by the TypeScript API because it
does not identify a class name.
Conditional classes
import { addClass } from "add-class-values";
const isSelected = true;
const isDisabled = false;
addClass("menu-item", {
"menu-item-selected": isSelected,
"menu-item-disabled": isDisabled,
});
// "menu-item menu-item-selected"Arrays and lazy values
Arrays can be nested. Functions are useful when a class should be calculated only when the class list is created.
addClass(
"card",
["card-bordered", [false, "card-raised"]],
() => "card-ready",
);
// "card card-bordered card-raised card-ready"Circular arrays and functions that return themselves throw a TypeError rather
than looping forever.
Prefixing added classes
addClassWithPrefix prefixes each additional class token. The base string is
left unchanged.
import { addClassWithPrefix } from "add-class-values";
addClassWithPrefix(
"button external-class",
"app-",
"primary large",
{ active: true },
);
// "button external-class app-primary app-large app-active"Its signature is:
addClassWithPrefix(base, prefix, ...values);Optional String methods
Projects that prefer the original prototype-style API can enable it explicitly:
import "add-class-values/prototype";
"button".addClass("primary", { active: true });
// "button primary active"
"button".addClassWithPrefix("app-", "primary", { active: true });
// "button app-primary app-active"The import augments the global TypeScript String interface and installs
non-enumerable addClass and addClassWithPrefix methods. Libraries should
prefer the function API so that importing them does not modify global objects.
CommonJS
const { addClass } = require("add-class-values");
addClass("button", { active: true });
// "button active"API
type ClassDictionary = Readonly<Record<string, unknown>>;
type ClassValue =
| string
| number
| false
| null
| undefined
| ClassDictionary
| readonly ClassValue[]
| (() => ClassValue);
function addClass(base: string, ...values: ClassValue[]): string;
function addClassWithPrefix(
base: string,
prefix: string,
...values: ClassValue[]
): string;Runtime support
The published package has no runtime dependencies and supports Node.js 18 or newer. It can also be bundled for modern browsers.
Development uses Node.js 20.19 or newer because that version is required by the build tools.
Development
npm install
npm run checknpm run check runs ESLint, TypeScript, the test suite, and the production
build.
