TGViewer
Frontend | Иван Усынин Frontend | Иван Усынин @usyninis_dev · 118 subscribers
Post #229 25
cva: когда обычного сlsx уже мало

Пока у кнопки два состояния — «обычная» и «выключенная» — легко склеить классы через clsx:
<button className={clsx("btn", isDisabled && "btn-disabled")} />

Но стоит появиться трём размерам и трём цветам, как в className начинается каша из условий. cva (class-variance-authority) помогает удобно описывать варианты стилей компонента — размеры, цвета, состояния. Внутри он использует clsx, так что это не замена, а надстройка над ним.

Основная идея

cva предлагает описать все варианты один раз и в понятном виде:
- variants — какие вообще варианты есть (размер, цвет и т.д.);
- defaultVariants — что ставить, если ничего не передали;
- compoundVariants — особые классы для конкретных сочетаний;
- VariantProps — готовые типы для пропсов компонента.

В ответ получаем функцию: передали в неё варианты — получили готовую строку классов. clsx при этом никуда не делся — cva склеивает классы через него.

Пример

import { cva, type VariantProps } from "class-variance-authority";

const button = cva("btn", {
variants: {
intent: {
primary: "btn-primary",
danger: "btn-danger",
},
size: {
sm: "btn-sm",
md: "btn-md",
},
},
compoundVariants: [
{ intent: "primary", size: "sm", className: "btn-uppercase" },
],
defaultVariants: { intent: "primary", size: "md" },
});

// выводим типы из описания вариантов
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
VariantProps<typeof button>;

export function Button({ intent, size, className, ...props }: ButtonProps) {
return <button className={button({ intent, size, className })} {...props} />;
}


Частые ошибки


- Тянуть cva туда, где хватает одного-двух условий, — обычный clsx проще и легче.
- Забыть про defaultVariants — и в каждом месте вызова вручную передавать одни и те же варианты.
- Продублировать описание вариантов в нескольких компонентах вместо одного общего.

Итог

clsx отвечает на вопрос «добавить ли этот класс?», а cva — «как устроены все варианты компонента?». Если условий одно-два, clsx вполне хватает. 👉 Как только появились размеры, цвета, дефолты и сочетания — используем cva.

#js #javascript #typescript #frontend #фронтенд #разработка #dev #webdev #react
  • 🔥 2
More from @usyninis_dev
  1. Jul 25, 2026RBAC и permission-based проверки на frontend: как мы управляем доступом на проекте 🔐 В бо…
  2. Jul 17, 2026Remotion: make videos programmatically 📹 Remotion — это программный фреймворк, который по…
  3. Apr 12, 2026Выступил с лекцией в ITHub В минувшую субботу в колледже информационных и креативных техно…
  4. Mar 8, 2026Поздравляю прекрасных дам с 8 Марта! Пусть весна цветет не только на улице, но и в душе! Н…
  5. Mar 2, 2026React.lazy — еще один полезный сценарий 🚀 Одни из самых популярных кейсов использования R…
  6. Feb 7, 2026TanStack Query — польза инструмента на практике Более 2 лет назад мы стартанули с нуля раз…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →