👨🏻💻 TechLead Frontend в Альфа-Банк. Запускал проекты в production до того, как это стало мейнстримом.
💡 На канале: рабочие заметки, решение возникающих проблем, полезные материалы про Frontend
Связаться: @usyninis
Post #229
25
cva: когда обычного сlsx уже мало
Пока у кнопки два состояния — «обычная» и «выключенная» — легко склеить классы через
Но стоит появиться трём размерам и трём цветам, как в
Основная идея
-
-
-
-
В ответ получаем функцию: передали в неё варианты — получили готовую строку классов.
Пример
Частые ошибки
- Тянуть
- Забыть про
- Продублировать описание вариантов в нескольких компонентах вместо одного общего.
Итог
#js #javascript #typescript #frontend #фронтенд #разработка #dev #webdev #react
Пока у кнопки два состояния — «обычная» и «выключенная» — легко склеить классы через
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













