Button

Displays a button with built-in misclick prevention.

import { Button } from "@chadcn/ui"
import { ArrowUpIcon } from "lucide-react"

export function ButtonDemo() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <Button variant="outline">Button</Button>
      <Button variant="outline" size="icon" aria-label="Submit">
        <ArrowUpIcon />
      </Button>
    </div>
  )
}

How it works

This component accepts the same props as the shadcn/ui Button (variant, size, asChild), with built-in misclick prevention. The button repositions itself away from the cursor on hover using translate, so the layout is unaffected. After 2 attempts, it stays in place to allow interaction.

Installation

Coming SoonPackage not yet published on npm.
pnpm add @chadcn/ui

Usage

import "@chadcn/ui/styles.css"
import { Button } from "@chadcn/ui"
<Button variant="outline">Button</Button>
Coming SoonPackage not yet published on npm.

Cursor

Tailwind v4 switched from cursor: pointer to cursor: default for the button component.

If you want to keep the cursor: pointer behavior, add the following code to your CSS file:

globals.css
@layer base {
  button:not(:disabled),
  [role="button"]:not(:disabled) {
    cursor: pointer;
  }
}

Examples

Size

Use the size prop to change the size of the button.

import { Button } from "@chadcn/ui"
import { ArrowUpRightIcon } from "lucide-react"

export function ButtonSize() {
  return (
    <div className="flex flex-wrap items-center gap-4">
      <Button size="xs">Extra Small</Button>
      <Button size="xs" variant="outline"><ArrowUpRightIcon /></Button>
      <Button size="sm">Small</Button>
      <Button size="default">Default</Button>
      <Button size="lg">Large</Button>
    </div>
  )
}

Default

import { Button } from "@chadcn/ui"

export function ButtonDefault() {
  return <Button>Default</Button>
}

Outline

import { Button } from "@chadcn/ui"

export function ButtonOutline() {
  return <Button variant="outline">Outline</Button>
}

Secondary

import { Button } from "@chadcn/ui"

export function ButtonSecondary() {
  return <Button variant="secondary">Secondary</Button>
}

Ghost

import { Button } from "@chadcn/ui"

export function ButtonGhost() {
  return <Button variant="ghost">Ghost</Button>
}

Destructive

import { Button } from "@chadcn/ui"

export function ButtonDestructive() {
  return <Button variant="destructive">Destructive</Button>
}

Link

import { Button } from "@chadcn/ui"

export function ButtonLink() {
  return <Button variant="link">Link</Button>
}

Icon

import { Button } from "@chadcn/ui"
import { CircleFadingArrowUpIcon } from "lucide-react"

export function ButtonIcon() {
  return (
    <Button variant="outline" size="icon">
      <CircleFadingArrowUpIcon />
    </Button>
  )
}

With Icon

Remember to add the data-icon="inline-start" or data-icon="inline-end" attribute to the icon for the correct spacing.

import { Button } from "@chadcn/ui"
import { GitBranchIcon } from "lucide-react"

export function ButtonWithIcon() {
  return (
    <Button>
      <GitBranchIcon data-icon="inline-start" />
      New Branch
    </Button>
  )
}

Rounded

Use the rounded-full class to make the button rounded.

import { Button } from "@chadcn/ui"
import { ArrowUpIcon } from "lucide-react"

export function ButtonRounded() {
  return (
    <Button className="rounded-full" size="icon" variant="outline">
      <ArrowUpIcon />
    </Button>
  )
}

As Child

You can use the asChild prop on <Button /> to make another component look like a button. Here's an example of a link that looks like a button.

import Link from "next/link"
import { Button } from "@chadcn/ui"

export function ButtonAsChild() {
  return (
    <Button asChild>
      <Link href="/login">Login</Link>
    </Button>
  )
}

API Reference

Button

The Button component is a wrapper around the button element that adds a variety of styles and functionality.

PropTypeDefault
variant"default" | "outline" | "ghost" | "destructive" | "secondary" | "link""default"
size"default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg""default"
asChildbooleanfalse