outclass v0.2.0
Outclass
Currently in pre-release version, expect breaking changes.
Outclass is a CSS class manipulation tool. It can be used to create strings of CSS classes dynamically, for example:
import { out } from "outclass";
// Generates a string of unique class names
out.parse("flex", "rounded", "flex");
// flex rounded
// Implements the builder pattern
out.set("blur w-4").remove("w-4").add("shadow w-2").parse();
// blur shadow w-2
// Has a variants system
out.variant({ sm: "p-2", lg: "p-4" }).choose("sm").parse();
// p-2
// Is patchable
const patch = out.remove("m-2").add("m-4");
out.set("border m-2").apply(patch).parse();
// border m-4
// All in a single call
out.parse({
add: "m-4",
apply: patch,
variant: { sm: "p-2", lg: "p-4" },
choose: "sm",
});
// m-4 p-2Installation
Outclass is available on npm as ECMAScript module (ESM) and works on any JavaScript runtime:
# Node.js
npm add outclass
pnpm add outclass
yarn add outclass
# Deno
deno add npm:outclass
# Bun
bun add outclassAnd in the browser:
<script type="module">
import { out } from "https://esm.sh/outclass";
</script>The out object can be imported from the outclass module:
import { out } from "outclass";Documentation
Outclass lets you to create strings of CSS classes. Internally it keeps a list of classes and offers methods to
manipulate it. The parse method returns a single string consisting of a space-separated list of unique CSS classes,
which can be used in the class attribute of HTML elements.
There are two main ways of use, which can be combined as desired:
- A builder: to programmatically add and remove classes
- A variant system: to specify and select style variants
Inputs
Most methods takes as arguments multiple strings and arrays of strings (infinitely nested):
out.parse("flex", ["grow"], [["p-2"]]);
// flex grow p-2Each input string is splitted into single classes on white-spaces:
out.add("flex grow").remove("grow").remove("flex").parse();
// ""It only understand string inputs, but for convenience it also takes, null, undefined and boolean values, so it
can be used with the && operator and ?. optional chaining:
const isMuted = false;
const props = { classes: "bg-slate-700" };
out.parse([
isMuted && "cursor-not-allowed",
props?.classes,
[null, undefined, false, true],
]);
// bg-slate-700 flex growImmutability
The out object is immutable, each call to its methods returns a new instance:
const style = out.add("text-end");
out.parse();
// ""
style.parse();
// text-endThis makes it more convenient as you can use it directly in method chaining without the need to create new instances of it every time:
out.set("box-content p-4").apply(out.remove("p-4")).parse();
// box-contentUsing the builder
The out object implements the builder pattern, the add and remove methods add and remove classes respectively,
the set method replaces the current list of classes with a new one:
out.add("flex").parse();
// flex
out.add("grow p-2").remove("grow").parse();
// p-2
out.add("flex").set("p-2").parse();
// p-2Using variants
The variant method is used to specify variants of style, for example a size variant can have options small and
large and a color variant can have options violet and blue. The choose method selects which variants to use.
Only one option per variant can be selected at a time:
out
.variant({ small: "p-2", large: "p-4" })
.variant({ violet: "bg-violet-500", blue: "bg-blue-500" })
.choose("small blue")
.parse();
// p-2 bg-violet-500Variants can have compound options, which are option with multiple names separated by spaces. Compound options are
selected when all names are passed to the choose method:
out
.variant({ small: "p-2", large: "p-4" })
.variant({ violet: "bg-violet-500", blue: "bg-blue-500" })
.variant({ "small violet": "rounded" })
.choose("small violet")
.parse();
// p-2 bg-violet-500 roundedThe choose method can be called multiple times to change the selected variants, this means that it can be used to
specify the default variant and then change it later:
out
.variant({ small: "p-2", large: "p-4" })
.choose("small")
.choose("large", "small")
.parse();
// p-2Patching
The apply method is used to apply patches to the list of classes. Patches are evaluated last, after manipulation of
the main object are, and the order they are applied is kept. A patch simply is a out object:
const patch = out.remove("m-2").add("m-4");
out.set("border m-2").apply(patch).parse();
// border m-4
const pick = out.choose("small");
out.variant({ small: "p-2", large: "p-4" }).choose("large").apply(pick).parse();
// p-2All in a single call
All functionality can be combined in a single call to the with method, which takes an object where each key is a
method name and the value is the arguments to pass to that method:
// All in a single call
out
.with({
set: "grid grow"
remove: "grid",
add: "flex",
apply: out.choose("small"),
variant: { sm: "p-2", lg: "p-4" },
choose: "large",
})
.parse();
// grow flex p-4The parse method
The parse can be called with no arguments to get the current list of classes, but it can also be called with a
string, in which case it acts as the add method, or with an object, in which case it acts as the with method:
out.set("flex").parse("grow");
// flex grow
out.set("flex").parse({
add: "m-4",
variant: { sm: "p-2", lg: "p-4" },
choose: "sm",
});
// flex m-4 p-2TailwindCSS
Outclass is especially useful when used with atomic or utility-first CSS frameworks such as TailwindCSS. To enable VS
Code IntelliSense for TailwindCSS classes, add this regex to your .vscode/settings.json:
{
"tailwindCSS.experimental.classRegex": [
// Enable IntelliSense on Outclass method calls outside "className" and "class" attributes
[
"\\.(?:parse|add|remove|set|with)\\s*\\(\\s*([\\s\\S]*?)\\s*\\)\\s*",
"[\"'`]([^\"'`]*)[\"'`]"
]
]
}Acknowledgements
Inspiration for this project comes mainly from the amazing job done by cva and clsx.