Repository: ui
Issue: [feat]: Dynamic add new variants
Labels: area: request

### Feature description

### Problem

Currently some component have fixed variant. For example: `const badgeVariants = cva(`, `const buttonVariants = cva(` so I find some solution to add dynamic variant with `minimum cost` to modify ShadCN UI code.

I don't know if this is a good idea before proceeding to modify the code and create a pull request.

This solution need update any component in `/components/ui` that used `= cva(`. So the end-user (developer) cant override variant by update ONLY 1 file `custom-vars.ts`. It need `shadcn tool (npx shadcn@latest)` create/update (question) `/components/ui/custom-vars.ts` if file not exits.

### This is example for update component button

#### Add merge variant function / customVars

For example `customVars.button` is override `button` variants. I use chat GPT, so maybe `_deepMerge` fn work not correctly.

```ts
// /src/components/ui/custom-vars.ts
type GetObjDifferentKeys<
  T,
  U,
  T0 = Omit<T, keyof U> & Omit<U, keyof T>,
  T1 = {
    [K in keyof T0]: T0[K];
  },
> = T1;

type GetObjSameKeys<T, U> = Omit<T | U, keyof GetObjDifferentKeys<T, U>>;

type MergeTwoObjects<
  T,
  U,
  T0 = GetObjDifferentKeys<T, U> & { [K in keyof GetObjSameKeys<T, U>]: DeepMergeTwoTypes<T[K], U[K]> },
  T1 = { [K in keyof T0]: T0[K] },
> = T1;

export type DeepMergeTwoTypes<T, U> = [T, U] extends [{ [key: string]: unknown }, { [key: string]: unknown }]
  ? MergeTwoObjects<NonNullable<T>, NonNullable<U>>
  : NonNullable<T> | NonNullable<U>;

function _deepMerge<T extends object, U extends object>(target: T, source: U): DeepMergeTwoTypes<T, U> {
  for (const key of Object.keys(source) as Array<keyof U>) {
    if (source[key] instanceof Object && key in target) {
      (target as any)[key] = _deepMerge((target as any)[key], source[key] as any);
    } else {
      (target as any)[key] = source[key];
    }
  }

  return target as any;
}

export function mergeVariants<T, U>(baseConfig: T, customConfig: U): DeepMergeTwoTypes<T, U> {
  return _deepMerge(baseConfig as any, customConfig as any) as any;
}

export const customVars = {
  button: {
    variants: {
      variant: {
        success: 'bg-success text-white hover:bg-success/80',
      },
    },
  },
};
```

#### Modify button.tsx

```ts
import { cn } from '@/lib/utils';
import { Slot } from '@radix-ui/react-slot';
import { cva, type VariantProps } from 'class-variance-authority';
import * as React from 'react';

// UPDATE: Import fn
import { customVars, mergeVariants } from './custom-vars';

const buttonVariants = cva(
  'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
  // UPDATED: do mergeVariants
  mergeVariants(
    {
      variants: {
        variant: {
          default: 'bg-primary text-primary-foreground hover:bg-primary/90',
          destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
          outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
          secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
          ghost: 'hover:bg-accent hover:text-accent-foreground',
          link: 'text-primary underline-offset-4 hover:underline',
        },
        size: {
          default: 'h-10 px-4 py-2',
          sm: 'h-9 rounded-md px-3',
          lg: 'h-11 rounded-md px-8',
          icon: 'h-10 w-10',
        },
      },
      defaultVariants: {
        variant: 'default',
        size: 'default',
      },
    },
    customVars.button || {},
  ),
);
```

#### Usage button

Expected: Code should not throw error for `variant='success'`

```tsx
<Button variant='success'>Success</Button>
```
#### Update CSS

```css
@layer base {
  :root {
    /* Define new variables */   
    --success: 100 77% 44%;
    --success-foreground: 102 85% 34%;
  }
}
```

Update tailwind.config.js
```ts
/** @type {import('tailwindcss').Config} */
export default {
  theme: {
    extend: {
      colors: {
       
        success: {
          DEFAULT: 'hsl(var(--success))',
          foreground: 'hsl(var(--success-foreground))',
        },
      }
    }
  }
}
```

### Affected component/components

Alert, Badge, Button, Label, Sheet, Toast, Toggle

### Additional Context

Additional details here...

### Before submitting

- [X] I've made research efforts and searched the documentation
- [X] I've searched for existing issues and PRs