# Button Variants

> The classes behind Button, for a link that should look like a button. It works in a server file.

- Name: `button-variants`
- Status: beta
- Categories: actions
- File: the install writes `button-variants.tsx` to your `ui` alias, `@/components/ui` by default.
- npm packages: `class-variance-authority`. The install adds them.
- Gallery: https://arbokui.com/components/button-variants
- Registry item: https://arbokui.com/r/button-variants.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/button-variants
   ```

## Use it for

- A link to another page that should look like a button. Put buttonVariants() in its className.
- A server file, like a page or a layout. Import buttonVariants from here. Button runs in the browser, so a server file cannot call a function from it.
- The same options as Button: tone, emphasis, size, and iconOnly.

## Avoid it for

- Running an action on the page. Use Button. It brings the loading state, the word morph, and the texture.
- Words that may run long. A link styled this way does not cut its words, so keep them short.

## Props

- `buttonVariants`: `(options?: { tone?: "neutral" | "brand" | "danger" | "success" | "warning"; emphasis?: "solid" | "soft" | "outline" | "ghost"; size?: "sm" | "md" | "lg"; iconOnly?: boolean }) => string`. Helper. The classes for one look of Button. Defaults: tone "neutral", emphasis "solid", size "md", iconOnly false.

## Accessibility

- It only adds classes. The element keeps its own role, so a link is still read and used as a link.
- The focus ring, hover, and press are the same as Button's, and follow the --motion-\* tokens.
- An icon-only link needs an aria-label that names where it goes, and a Tooltip that shows the same words.

## Examples

### A link that looks like a soft brand button

```tsx
import Link from "next/link";
import { buttonVariants } from "@/components/ui/button-variants";

<Link href="/pricing" className={buttonVariants({ tone: "brand", emphasis: "soft" })}>
  See pricing
</Link>
```

### An icon-only link with a tooltip (needs @arbokui/tooltip)

```tsx
import Link from "next/link";
import { Settings } from "lucide-react";
import { buttonVariants } from "@/components/ui/button-variants";
import { Tooltip, TooltipPopup, TooltipTrigger } from "@/components/ui/tooltip";

<Tooltip>
  <TooltipTrigger render={<Link href="/settings" aria-label="Settings" className={buttonVariants({ emphasis: "ghost", iconOnly: true })} />}>
    <Settings />
  </TooltipTrigger>
  <TooltipPopup>Settings</TooltipPopup>
</Tooltip>
```
