[]previous and next page

The class attribute

class takes a string, a number, a nested array, or an object.

For agentsUpdated

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.