Vai al contenuto

Varianti

variants() è un port PHP di CVA (Class Variance Authority). Trasforma una configurazione dichiarativa — una base, assi di varianti con nome e valori predefiniti — in una funzione che associa le props a una stringa di classi. Usatelo quando un componente ha dimensioni di stile, come dimensione e intento, da combinare.

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() restituisce un callable; chiamatelo con un array di props (o senza argomenti) per ottenere la stringa risolta.

Configurazione

Chiave Tipo Scopo
base string Classi applicate a ogni output.
variants array Assi con nome, ciascuno dei quali associa valori a stringhe di classi.
compoundVariants array Stringhe di classi applicate solo quando si combinano più valori di varianti.
defaultVariants array Valore per asse da usare quando una prop è omessa.

Tutte le chiavi sono facoltative. Senza variants, il risultato restituisce base insieme a eventuali classi personalizzate:

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

Un valore di variante può essere impostato su null per non aggiungere nulla: è utile come opzione esplicita di «nessun valore» per un asse.

Chiamare il risultato

Passate un unico array di props, come in CVA. Le chiavi corrispondono ai nomi degli assi delle varianti; gli assi omessi usano il valore predefinito 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'

La chiave class (e il suo alias className) viene aggiunta alla fine dell'output. Aggiungerla non basta a risolvere i conflitti: per farlo, consultate lo schema del componente qui sotto.

compoundVariants

Ogni voce di compoundVariants è un array di condizioni per le varianti seguito da class (o className) di classi aggiuntive. Le classi vengono applicate solo quando tutte le condizioni corrispondono alle props risolte, valori predefiniti inclusi. Il valore di una condizione può essere una singola stringa o un array di stringhe per corrispondere a più valori possibili.

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'

Schema del componente

variants() aggiunge solo class; per permettere ai chiamanti di sovrascrivere davvero i valori predefiniti delle varianti, racchiudete l'output in cn(), così in caso di conflitto prevalgono le classi del chiamante.

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']);

La cache static $styles crea la configurazione delle varianti una sola volta e la riutilizza nelle chiamate successive.

compose()

compose() combina più componenti con varianti in uno solo. La funzione composta inoltra ogni prop a ciascun componente, raccoglie i risultati e aggiunge eventuali 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'

In questo modo gli assi riutilizzabili (spaziatura, elevazione, layout) restano in definizioni separate e si combinano in base al componente.

Importazioni

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

Entrambi sono disponibili nello spazio dei nomi principale TailwindPHP e sono inclusi nel pacchetto: port PHP di CVA di Joe Bell.