Перейти к содержимому

Варианты

variants() — это PHP-порт CVA (Class Variance Authority). Он преобразует декларативную конфигурацию — базовый стиль, именованные оси вариантов и значения по умолчанию — в функцию, которая сопоставляет свойства со строкой классов. Используйте его, если у компонента есть сочетания параметров стиля, например размера и назначения.

PHP
use function TailwindPHP\variants;

$button = variants([
    'base' => 'btn font-semibold border rounded',
    'variants' => [
        'intent' => [
            'primary'   => 'bg-blue-500 text-white',
            'secondary' => 'bg-gray-200 text-gray-800',
        ],
        'size' => [
            'sm' => 'text-sm px-2 py-1',
            'md' => 'text-base px-4 py-2',
        ],
    ],
    'defaultVariants' => [
        'intent' => 'primary',
        'size'   => 'md',
    ],
]);

$button();
// => 'btn font-semibold border rounded bg-blue-500 text-white text-base px-4 py-2'

variants() возвращает значение типа callable; вызовите его с массивом свойств (или без аргументов), чтобы получить итоговую строку.

Конфигурация

Ключ Тип Назначение
base string Классы, применяемые ко всем результатам.
variants array Именованные оси, каждая сопоставляет названия значений строкам классов.
compoundVariants array Строки классов, применяемые только при сочетании нескольких значений вариантов.
defaultVariants array Значение для каждой оси, если свойство не указано.

Все ключи необязательны. Если variants не задан, результат возвращает base и любые пользовательские классы:

PHP
$x = variants(['base' => 'box']);
$x();                          // => 'box'
$x(['class' => 'p-4']);        // => 'box p-4'

Значение варианта можно сопоставить с null, чтобы оно ничего не добавляло, — это удобно для явного варианта «не задано» в оси.

Вызов результата

Передайте один массив свойств, как в CVA. Ключи должны совпадать с именами осей вариантов; если ось не указана, используется defaultVariants.

PHP
$button(['intent' => 'secondary']);
// => 'btn font-semibold border rounded bg-gray-200 text-gray-800 text-base px-4 py-2'

$button(['size' => 'sm', 'class' => 'mt-4']);
// => 'btn font-semibold border rounded bg-blue-500 text-white text-sm px-2 py-1 mt-4'

Ключ class (и его псевдоним className) добавляется в конец результата. Само по себе добавление не разрешает конфликты — см. шаблон компонента ниже.

compoundVariants

Каждая запись в compoundVariants — это массив условий вариантов и class (или className) дополнительных классов. Классы применяются, только если совпадают все условия с разрешенными свойствами (включая значения по умолчанию). Значением условия может быть одна строка или массив строк для совпадения с любым из нескольких значений.

PHP
$button = variants([
    'base' => 'btn',
    'variants' => [
        'intent' => [
            'primary' => 'bg-blue-500',
            'warning' => 'bg-yellow-500',
            'danger'  => 'bg-red-500',
        ],
        'size' => ['sm' => 'text-sm', 'md' => 'text-base'],
    ],
    'compoundVariants' => [
        // Applies only when intent=primary AND size=md
        ['intent' => 'primary', 'size' => 'md', 'class' => 'uppercase'],
        // Applies when intent is warning OR danger
        ['intent' => ['warning', 'danger'], 'class' => '!border-red-500'],
    ],
    'defaultVariants' => ['intent' => 'primary', 'size' => 'md'],
]);

$button();
// => 'btn bg-blue-500 text-base uppercase'

$button(['intent' => 'danger']);
// => 'btn bg-red-500 text-base !border-red-500'

Шаблон компонента

variants() только добавляет class; чтобы вызывающий код мог действительно переопределять варианты по умолчанию, оберните результат в cn(), чтобы конфликты разрешались в пользу вызывающего кода.

PHP
use function TailwindPHP\variants;
use function TailwindPHP\cn;

function Button(array $props = []): string {
    static $styles = null;
    $styles ??= variants([
        'base' => 'inline-flex items-center justify-center rounded-md font-medium',
        'variants' => [
            'variant' => [
                'default' => 'bg-primary text-primary-foreground hover:bg-primary/90',
                'outline' => 'border border-input bg-background hover:bg-accent',
                'ghost'   => 'hover:bg-accent hover:text-accent-foreground',
            ],
            'size' => [
                'default' => 'h-10 px-4 py-2',
                'sm'      => 'h-9 px-3',
                'lg'      => 'h-11 px-8',
            ],
        ],
        'defaultVariants' => ['variant' => 'default', 'size' => 'default'],
    ]);

    // cn() merges variant output with custom classes, resolving conflicts
    $class = cn($styles($props), $props['class'] ?? null);
    $text  = $props['children'] ?? 'Button';
    return "<button class=\"{$class}\">{$text}</button>";
}

// The custom px-8 wins over the variant's px-3 via cn()
Button(['variant' => 'outline', 'size' => 'sm', 'class' => 'mt-4 px-8']);

Кэш static $styles создает конфигурацию вариантов один раз и повторно использует ее при вызовах.

compose()

compose() объединяет несколько компонентов вариантов в один. Составная функция передает каждое свойство всем компонентам, собирает их результаты и добавляет любые class/className.

PHP
use function TailwindPHP\variants;
use function TailwindPHP\compose;

$box   = variants(['variants' => ['shadow' => ['sm' => 'shadow-sm', 'md' => 'shadow-md']]]);
$stack = variants(['variants' => ['gap' => ['1' => 'gap-1', '2' => 'gap-2']]]);
$card  = compose($box, $stack);

$card(['shadow' => 'md', 'gap' => '2']);
// => 'shadow-md gap-2'

Так повторно используемые оси (интервалы, высота, компоновка) остаются в отдельных определениях и объединяются для каждого компонента.

Импорты

PHP
use function TailwindPHP\variants;
use function TailwindPHP\compose;

Обе функции находятся в основном пространстве имен TailwindPHP и входят в состав пакета — это PHP-порт CVA Джо Белла.