# Extending (https://www.tailwind-variants.org/docs/extending)

Compose component recipes with extend — inherit base styles, variants, slots, and defaults without copying definitions.

`extend` merges one recipe into another. Start from a base button, then add icon-only sizing or new variant tokens without copying the whole definition.

## Basic extend
Pass a parent recipe via the `extend` option:

```ts
import { tv } from 'tailwind-variants';

const baseButton = tv({
  base: 'inline-flex cursor-pointer items-center justify-center rounded-full font-medium select-none transition-colors',
  variants: {
    variant: {
      primary: 'bg-zinc-900 text-white',
      secondary: 'border border-zinc-300 bg-zinc-50 text-zinc-900',
      tertiary: 'text-zinc-700'
    },
    size: {
      sm: 'h-8 px-3 text-sm',
      md: 'h-10 px-4 text-sm'
    }
  },
  defaultVariants: {
    variant: 'primary',
    size: 'md'
  }
});

const iconButton = tv({
  extend: baseButton,
  base: 'gap-2',
  variants: {
    iconOnly: {
      true: 'aspect-square px-0',
      false: ''
    }
  }
});
```

## Merge behavior
`extend` deep-merges:

* **base** — concatenated
* **slots** — merged by key
* **variants** — merged by axis; new keys add axes, existing keys add values
* **defaultVariants** — child overrides parent for matching keys
* **compoundVariants** — arrays concatenated
* **compoundSlots** — arrays concatenated

The returned object exposes merged metadata: `variants`, `variantKeys`, `defaultVariants`, and slot keys reflect the full composed recipe.

## Extending slotted recipes
Slots merge by key. Child recipes can add slots or override styles on inherited ones:

```ts
import { tv } from 'tailwind-variants';

const card = tv({
  slots: {
    base: 'rounded-xl border p-4',
    title: 'text-sm font-medium',
    description: 'text-sm text-zinc-500'
  }
});

const mediaCard = tv({
  extend: card,
  slots: {
    media: 'mb-3 aspect-video rounded-lg bg-zinc-100',
    title: 'text-base font-semibold'
  }
});

const { base, media, title, description } = mediaCard();
```

`mediaCard` keeps `base` / `description` from `card`, adds `media`, and tightens `title`.

## One parent at a time
You can only `extend` one recipe per definition. To combine multiple bases, call them manually or chain extends:

```ts
const extended = tv({ extend: baseButton });
const final = tv({ extend: extended /* ... */ });
```
