Button

PreviousNext

Displays a button or a component that looks like a button.

import { ArrowUpIcon } from "lucide-react"

import { Button } from "@/components/ui/button"

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

Installation

pnpm dlx shadcn@latest add button

Usage

import { Button } from "@/components/ui/button"
<Button variant="outline">Button</Button>

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

import { ArrowUpRightIcon } from "lucide-react"

import { Button } from "@/components/ui/button"

export function ButtonSize() {
  return (
    <div className="flex flex-col items-start gap-8 sm:flex-row">
      <div className="flex items-start gap-2">
        <Button size="sm" variant="outline">
          Small
        </Button>
        <Button size="icon-sm" aria-label="Submit" variant="outline">
          <ArrowUpRightIcon />
        </Button>
      </div>
      <div className="flex items-start gap-2">
        <Button variant="outline">Default</Button>
        <Button size="icon" aria-label="Submit" variant="outline">
          <ArrowUpRightIcon />
        </Button>
      </div>
      <div className="flex items-start gap-2">
        <Button variant="outline" size="lg">
          Large
        </Button>
        <Button size="icon-lg" aria-label="Submit" variant="outline">
          <ArrowUpRightIcon />
        </Button>
      </div>
    </div>
  )
}

Default

import { Button } from "@/components/ui/button"

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

Outline

import { Button } from "@/components/ui/button"

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

Secondary

import { Button } from "@/components/ui/button"

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

Ghost

import { Button } from "@/components/ui/button"

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

Destructive

import { Button } from "@/components/ui/button"

export function ButtonDestructive() {
  return <Button variant="destructive">Destructive</Button>
}
import { Button } from "@/components/ui/button"

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

Icon

import { CircleFadingArrowUpIcon } from "lucide-react"

import { Button } from "@/components/ui/button"

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

With Icon

The spacing between the icon and the text is automatically adjusted based on the size of the button. You do not need any margin on the icon.

import { IconGitBranch } from "@tabler/icons-react"

import { Button } from "@/components/ui/button"

export function ButtonWithIcon() {
  return (
    <Button variant="outline" size="sm">
      <IconGitBranch /> New Branch
    </Button>
  )
}

Rounded

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

import { ArrowUpIcon } from "lucide-react"

import { Button } from "@/components/ui/button"

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

Spinner

import { Button } from "@/components/ui/button"
import { Spinner } from "@/components/ui/spinner"

export function ButtonLoading() {
  return (
    <Button size="sm" variant="outline" disabled>
      <Spinner />
      Submit
    </Button>
  )
}

Button Group

To create a button group, use the ButtonGroup component. See the Button Group documentation for more details.

"use client"

import * as React from "react"
import {
  ArchiveIcon,
  ArrowLeftIcon,
  CalendarPlusIcon,
  ClockIcon,
  ListFilterPlusIcon,
  MailCheckIcon,
  MoreHorizontalIcon,
  TagIcon,
  Trash2Icon,
} from "lucide-react"
import { SubmenuTrigger } from "react-aria-components"

import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
import {
  Menu,
  MenuItem,
  MenuSeparator,
  MenuTrigger,
} from "@/components/ui/menu"

export function ButtonGroupDemo() {
  return (
    <ButtonGroup>
      <ButtonGroup className="hidden sm:flex">
        <Button variant="outline" size="icon" aria-label="Go Back">
          <ArrowLeftIcon />
        </Button>
      </ButtonGroup>
      <ButtonGroup>
        <Button variant="outline">Archive</Button>
        <Button variant="outline">Report</Button>
      </ButtonGroup>
      <ButtonGroup>
        <Button variant="outline">Snooze</Button>
        <MenuTrigger>
          <Button variant="outline" size="icon" aria-label="More Options">
            <MoreHorizontalIcon />
          </Button>
          <Menu placement="bottom end" className="w-52" selectionMode="single">
            <MenuItem>
              <MailCheckIcon />
              Mark as Read
            </MenuItem>
            <MenuItem>
              <ArchiveIcon />
              Archive
            </MenuItem>
            <MenuSeparator />
            <MenuItem>
              <ClockIcon />
              Snooze
            </MenuItem>
            <MenuItem>
              <CalendarPlusIcon />
              Add to Calendar
            </MenuItem>
            <MenuItem>
              <ListFilterPlusIcon />
              Add to List
            </MenuItem>
            <SubmenuTrigger>
              <MenuItem>
                <TagIcon />
                Label As...
              </MenuItem>
              <Menu selectionMode="single" defaultSelectedKeys={["personal"]}>
                <MenuItem id="personal">Personal</MenuItem>
                <MenuItem id="work">Work</MenuItem>
                <MenuItem id="other">Other</MenuItem>
              </Menu>
            </SubmenuTrigger>
            <MenuSeparator />
            <MenuItem className="text-destructive focus:bg-destructive/10 dark:focus:bg-destructive/20 focus:text-destructive">
              <Trash2Icon />
              Trash
            </MenuItem>
          </Menu>
        </MenuTrigger>
      </ButtonGroup>
    </ButtonGroup>
  )
}

react-aria-components don't support asChild for the Button component. You can use the LinkButton component instead for.

<LinkButton href="/login">Login</LinkButton>

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" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg""default"

Apart from the props above, the Button component also supports the props from the react-aria-components Button component. Check the react-aria-components documentation for more details.