The class attribute
class takes a string, a number, a nested array, or an object.
class takes a string, a number, a nested array, or an object. This is the clsx convention, built
into the runtime, so no helper library is needed:
| Value | Class text |
|---|---|
"a b" |
a b (used as is) |
["a", false, "b", null] |
a b (falsy entries are skipped) |
{ a: true, b: 0, "c d": 1 } |
a c d (truthy keys; a key may hold several names) |
["a", ["b", { c: true }]] |
a b c (arrays nest) |
0, NaN, "" |
nothing |
[], {} |
nothing is written |
null, undefined, false |
the class attribute is removed |
src/button.tsxtsx
import { useStore } from "@shadow-js/core";
export function Button(props: { variant: "primary" | "ghost" }) {
const [pressed, setPressed] = useStore(false);
return (
<button
type="button"
class={["btn", `btn-${props.variant}`, { "btn-pressed": pressed() }]}
onClick={() => setPressed((value) => !value)}
>
toggle
</button>
);
}
The binding re-evaluates the whole expression when pressed() changes and writes el.className
once, only when the resulting text differs from the current one. Nested arrays are walked
iteratively and an array that contains itself throws a TypeError.
class or className#
The JSX types accept both and the compiler writes the same class attribute for both. Use class
in new code; className exists so code that is migrated from React type-checks and runs unchanged.
htmlFor is likewise an alias of for on label and output.