Button Variants
betaThe classes behind Button, for a link that should look like a button. It works in a server file.
Preview
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the component.
npx shadcn@latest add @txbrendan/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
Helper. The classes for one look of Button. Defaults: tone "neutral", emphasis "solid", size "md", iconOnly false.
(options?: { tone?: "neutral" | "brand" | "danger" | "success" | "warning"; emphasis?: "solid" | "soft" | "outline" | "ghost"; size?: "sm" | "md" | "lg"; iconOnly?: boolean }) => string
| Prop | Type | Default | What it does |
|---|---|---|---|
| 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
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 @txbrendan/tooltip)
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>