Aller au contenu

Variantes

variants() est un port PHP de CVA (Class Variance Authority). Il transforme une configuration déclarative — une base, des axes de variantes nommés et des valeurs par défaut — en une fonction qui associe les props à une chaîne de classes. Utilisez-le lorsqu'un composant possède des dimensions de style combinables, comme la taille et l'intention.

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() renvoie un callable ; appelez-le avec un tableau de props (ou sans argument) pour obtenir la chaîne résolue.

Configuration

Clé Type Fonction
base string Classes appliquées à chaque résultat.
variants array Axes nommés, chacun associant des noms de valeurs à des chaînes de classes.
compoundVariants array Chaînes de classes appliquées uniquement lorsque plusieurs valeurs de variantes sont combinées.
defaultVariants array Valeur utilisée par axe lorsqu'une prop est omise.

Toutes les clés sont facultatives. Sans variants, le résultat renvoie base ainsi que les classes personnalisées éventuelles :

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

Une valeur de variante peut être associée à null pour ne rien ajouter — pratique pour définir explicitement une option « non définie » sur un axe.

Appeler le résultat

Passez un seul tableau de props, comme avec CVA. Les clés correspondent aux noms de vos axes de variantes ; les axes omis prennent leurs valeurs dans 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 clé class (et son alias className) est ajoutée à la fin du résultat. Cet ajout seul ne résout pas les conflits — consultez le modèle de composant ci-dessous.

compoundVariants

Chaque entrée de compoundVariants est un tableau de conditions de variantes, suivi d'un class (ou className) de classes supplémentaires. Les classes s'appliquent uniquement si toutes les conditions correspondent aux props résolues, valeurs par défaut incluses. Une valeur de condition peut être une chaîne unique ou un tableau de chaînes pour correspondre à plusieurs valeurs.

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'

Modèle de composant

variants() ajoute seulement class ; pour permettre aux appelants de réellement remplacer les valeurs de variantes par défaut, enveloppez le résultat dans cn() afin que les conflits soient résolus en leur faveur.

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

Le cache static $styles construit la configuration de variantes une seule fois et la réutilise lors des appels suivants.

compose()

compose() fusionne plusieurs composants à variantes en un seul. La fonction composée transmet chaque prop à tous les composants, rassemble leurs résultats et ajoute tout class/className éventuel.

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'

Cela permet de définir séparément des axes réutilisables (espacement, élévation, mise en page), puis de les combiner pour chaque composant.

Imports

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

Les deux se trouvent dans l'espace de noms principal TailwindPHP et sont inclus avec le package — un port PHP de CVA par Joe Bell.