Налаштування під себе

Кожен компонент, доданий через npx @voltui/cli add , копіюється у ваш проєкт звичайним вихідним кодом. Немає пакета, з якого треба «викидатися», і немає API перевизначень, який треба вивчати — ви редагуєте файл так само, як будь-який власноруч написаний компонент.

Редагування скопійованого компонента

Після volt add button файл src/app/ui/button/button.ts належить вам (або там, куди вказує конфігурація вашого CLI). Потрібен четвертий розмір кнопки? Додайте його напряму — більше нічого перегенеровувати чи синхронізувати не треба.

// ui/button/variants.ts
export const buttonVariants = cva('...', {
  variants: {
    size: {
      sm: 'h-8 rounded-md px-3 text-xs',
      md: 'h-10 rounded-md px-4 text-sm',
      lg: 'h-11 rounded-md px-8 text-base',
      icon: 'h-9 w-9 rounded-md',
      xl: 'h-12 rounded-md px-10 text-base',   // <- added
    },
  },
});

Тип ButtonVariants['size'] виводиться з цього об'єкта через VariantProps<typeof buttonVariants> , тож <volt-button size="xl"> повністю типізовано щойно ви збережете файл — окремої декларації типу оновлювати не потрібно.

Як тут працюють варіанти CVA

Компоненти з візуальними варіантами (button, badge, toast, ...) виносять стилі в сусідній variants.ts за допомогою class-variance-authority. Сам компонент лише обчислює, який варіант активний, і ніколи не прописує умовні класи в шаблоні:

// button.ts
protected readonly classes = computed(() =>
  cn(buttonVariants({ variant: this.variant(), size: this.size() }), this.class())
);

Додавання цілком нової групи варіантів (а не просто ще одного значення в наявній — наприклад, варіанта tone поряд із variant і size ) робиться за тим самим зразком: додайте ключ до variants у variants.ts , потім додайте readonly tone = input<...>('default') і прокиньте його в computed() вище.

Перевизначення класів через cn()

Більшість компонентів мають вхід class , що проходить через cn() : clsx для умовного склеювання і tailwind-merge для розв'язання конфліктів, щоб перемагала остання утиліта, а не обидві опинялися у списку класів:

// utils.ts — this ships with every component that imports it
export function cn(...inputs: ClassValue[]): string {
  return twMerge(clsx(inputs));
}
<volt-button class="w-full">Continue</volt-button>   // adds w-full; doesn't fight the variant's own width classes

Оскільки під капотом tailwind-merge , class="bg-red-500" надійно перекриває власну утиліту фону варіанта, а не породжує два конфліктні класи bg-* у підсумковому виводі.

Колір і форма проти структури

Перш ніж правити класи Tailwind у компоненті заради кольору чи радіуса рамки, перевірте, чи цього вже не покриває пресет теми : bg-primary , rounded-md і shadow-lg розв'язуються через токени --volt-* , які вже змінюються залежно від кольорового чи стильового пресета. Жорстко прописаний bg-indigo-600 у скопійованому компоненті виводить саме цей компонент із перемикання тем; коли зміна має діяти всюди, беріть власний кольоровий або стильовий пресет. Правки компонента — для структурних змін: нових варіантів, нових слотів, іншої розмітки, яких жоден токен не виразить.