Skip to content
txbrendan/ui

Button Variants

beta

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

Preview

Install

  1. 1. Add the registry to components.json, once per app. Without it, the shadcn CLI looks up @txbrendan in a public list that txbrendan/ui does not control.

    npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"
  2. 2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.

    npx shadcn@latest add @txbrendan/theme
  3. 3. 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

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>