Варианты
variants() — это PHP-порт CVA (Class Variance Authority). Он преобразует декларативную конфигурацию — базовый стиль, именованные оси вариантов и значения по умолчанию — в функцию, которая сопоставляет свойства со строкой классов. Используйте его, если у компонента есть сочетания параметров стиля, например размера и назначения.
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 и любые пользовательские классы:
$x = variants(['base' => 'box']);
$x(); // => 'box'
$x(['class' => 'p-4']); // => 'box p-4'
Значение варианта можно сопоставить с null, чтобы оно ничего не добавляло, — это удобно для явного варианта «не задано» в оси.
Вызов результата
Передайте один массив свойств, как в CVA. Ключи должны совпадать с именами осей вариантов; если ось не указана, используется defaultVariants.
$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) дополнительных классов. Классы применяются, только если совпадают все условия с разрешенными свойствами (включая значения по умолчанию). Значением условия может быть одна строка или массив строк для совпадения с любым из нескольких значений.
$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(), чтобы конфликты разрешались в пользу вызывающего кода.
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.
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'
Так повторно используемые оси (интервалы, высота, компоновка) остаются в отдельных определениях и объединяются для каждого компонента.
Импорты
use function TailwindPHP\variants;
use function TailwindPHP\compose;
Обе функции находятся в основном пространстве имен TailwindPHP и входят в состав пакета — это PHP-порт CVA Джо Белла.