
# Varianter

`variants()` är en PHP-port av [CVA (Class Variance Authority)](https://github.com/joe-bell/cva). Den omvandlar en deklarativ konfiguration — en bas, namngivna variantaxlar och standardvärden — till en anropsbar funktion som mappar props till en klasssträng. Använd den när en komponent har stilvarianter som storlek och avsikt som ska kombineras.

```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()` returnerar en `callable`; anropa den med en props-array (eller utan argument) för att få den lösta strängen.

## Konfiguration

| Nyckel | Typ | Syfte |
|-----|------|---------|
| `base` | `string` | Klasser som används i varje utdata. |
| `variants` | `array` | Namngivna axlar, där varje axel mappar värdenamn till klasssträngar. |
| `compoundVariants` | `array` | Klasssträngar som används endast när flera variantvärden kombineras. |
| `defaultVariants` | `array` | Värde per axel som används när en prop utelämnas. |

Alla nycklar är valfria. Utan `variants` returneras `base` samt eventuella anpassade klasser:

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

Ett variantvärde kan mappas till `null` för att inte bidra med något — användbart som ett uttryckligt alternativ för att avmarkera en axel.

## Anropa resultatet

Skicka in en enda props-array, enligt CVA-stil. Nycklarna motsvarar variantaxlarnas namn; utelämnade axlar använder `defaultVariants` som reservvärde.

```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'
```

Nyckeln `class` (och dess alias `className`) läggs till sist i utdata. Att lägga till klasser löser inte i sig konflikter — se komponentmönstret nedan.

## compoundVariants

Varje post i `compoundVariants` är en array med variantvillkor och ett `class` (eller `className`) med extra klasser. Klasserna används endast när alla villkor stämmer med de lösta propsen, inklusive standardvärden. Ett villkorsvärde kan vara en enda sträng eller en array med strängar som matchar ett av flera värden.

```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'
```

## Komponentmönster

`variants()` lägger bara till `class`; om anropare verkligen ska kunna åsidosätta variantstandardvärden omsluter du utdata med [cn()](https://tailwindphp.inline0.dev/sv/docs/class-utilities) så att konflikter löses till anroparens fördel.

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

Cachen `static $styles` bygger variantkonfigurationen en gång och återanvänder den vid efterföljande anrop.

## compose()

`compose()` slår ihop flera variantkomponenter till en. Den sammansatta anropsbara funktionen skickar varje prop vidare till alla komponenter, samlar in deras utdata och lägger till eventuella `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'
```

Detta håller återanvändbara axlar (avstånd, höjd, layout) i separata definitioner och kombinerar dem per komponent.

## Importer

```php
use function TailwindPHP\variants;
use function TailwindPHP\compose;
```

Båda finns i huvudnamnrymden `TailwindPHP` och följer med paketet — en PHP-port av CVA av Joe Bell.
