Overview

classes(input) is an element directive that owns a set of class tokens and diffs them on each update — only tokens that changed are added or removed.

Input can be a string, a Record<string, any> (truthy values apply the key), or an array of strings, falsy skips, and tuples [cond, class] / [cond, a, b].

classes vs classMap vs class=

API
Position
Notes
class=${…} Attribute binding Full class string each render — you manage the whole value.
classMap({…}) class= binding lit-html directive. Use as class=${classMap(...)}. See /docs/lit-html/directives.
${classes(...)} Element directive Mates directive inside the opening tag. Diffs owned tokens; supports array tuples.

Dynamic class bindings

The classes directive is applied directly on an element attribute slot. Pass an object — keys are class names, values are booleans — or a mixed array of strings and conditionals. Only the diff is applied to the DOM.

import { html, atom, classes, renderApp } from 'mates';

const App = () => {
const active = atom(false);
const size = atom('md');
return () => html`
<div class="m-col m-gap m-items-start">
<button
${classes({ primary: active(), sm: size() === 'sm', ghost: !active() })}
@click=${() => active.set(v => !v)}
>
${active() ? 'Active' : 'Inactive'} button
</button>
<div class="m-flex m-items-center m-justify-center m-gap-sm">
${['sm', 'md', 'lg'].map(s => html`
<button
class=${size() === s ? 'btn-primary' : 'btn-ghost'}
@click=${() => size.set(s)}
>${s}</button>
`)}
</div>
<p class="label">
Classes applied: ${active() ? 'primary' : 'ghost'}, ${size()}
</p>
</div>
`;
};
renderApp(App, document.getElementById('app'));

Array + tuple form

Mix strings, falsy skips, and [cond, a, b] ternaries in one classes() call.

import { html, atom, classes, renderApp } from 'mates';

const App = () => {
const on = atom(true);
return () => html`
<div class="m-col m-gap m-items-start">
<div ${classes(['card', 'card-body', [on(), 'primary', 'ghost']])}>
${on() ? 'primary' : 'ghost'} via tuple
</div>
<button @click=${() => on.set(v => !v)}>Toggle</button>
</div>
`;
};
renderApp(App, document.getElementById('app'));