Pitsi UI
  • Home
  • Docs
1
1
Sections
  • Get Started
  • Components
  • Animations
  • MCP Server
  • Changelog
Get Started
  • Installation
  • CLI
  • llms.txt
Components
  • Accordion
  • Alert Dialog
  • Alert
  • Aspect Ratio
  • Avatar
  • Badge
  • Breadcrumb
  • Button Group
  • Button
  • Card
  • Carousel
  • Checkbox
  • Collapsible
  • Combobox
  • Command
  • Container
  • Context Menu
  • Data Table
  • Dialog
  • Drawer
  • Dropdown Menu
  • Empty
  • Field
  • Flex
  • Form
  • Grid
  • Hero Button
  • Hover Card
  • Input Group
  • Input OTP
  • Input
  • Item
  • Kbd
  • Label
  • Menubar
  • Native Select
  • Navigation Menu
  • Pagination
  • Popover
  • Progress
  • Radio Group
  • Resizable
  • Responsive
  • Scroll Area
  • Segmented Control
  • Select
  • Separator
  • Sheet
  • Sidebar
  • Skeleton
  • Slider
  • Sonner
  • Spacer
  • Spinner
  • Squircle
  • Switch
  • Table
  • Tabs
  • Textarea
  • Theme Toggle
  • Toggle Group
  • Toggle
  • Tooltip
  • Typography
  • Unicorn Wrapper
Animations
  • Background Image Parallax
  • Card Swipe Carousel
  • Cards Parallax
  • Parallax Scroll
  • Perspective Carousel
  • Perspective Section Transition
  • Scroll Expand
  • Scroll Fade
  • Scroll Scale
  • Slide Down
  • Slide Up
  • Smooth Parallax Scroll
  • Smooth Scroll
  • Sticky Footer
  • Text Along Path
  • Text Gradient Opacity
  • Text Parallax
  • Transforms 3d
  • Zoom Parallax

Button

PreviousNext

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

Powered by
shadcn/ui

Updated: We have updated the button component to add new sizes: icon-sm and icon-lg. See the changelog for more details. Follow the instructions to update your project.

import { ArrowUp } 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">
        <ArrowUp />
      </Button>
    </div>
  )
}
<Button variant="outline">Button</Button>
<Button variant="outline" size="icon" aria-label="Submit">
  <ArrowUpIcon />
</Button>

Installation

pnpm dlx pitsi@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 { ArrowUpRight } 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">
          <ArrowUpRight />
        </Button>
      </div>
      <div className="flex items-start gap-2">
        <Button variant="outline">Default</Button>
        <Button size="icon" aria-label="Submit" variant="outline">
          <ArrowUpRight />
        </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">
          <ArrowUpRight />
        </Button>
      </div>
    </div>
  )
}
// Small
<Button size="sm" variant="outline">Small</Button>
<Button size="icon-sm" aria-label="Submit" variant="outline">
  <ArrowUpRightIcon />
</Button>
 
// Medium
<Button variant="outline">Default</Button>
<Button size="icon" aria-label="Submit" variant="outline">
  <ArrowUpRightIcon />
</Button>
 
// Large
<Button size="lg" variant="outline">Large</Button>
<Button size="icon-lg" aria-label="Submit" variant="outline">
  <ArrowUpRightIcon />
</Button>

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>
}
<Button variant="secondary">Secondary</Button>

Ghost

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

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

Destructive

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

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

Link

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

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

Icon

import { ArrowUpCircle } from "lucide-react"

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

export function ButtonIcon() {
  return (
    <Button variant="outline" size="icon">
      <ArrowUpCircle />
    </Button>
  )
}
<Button variant="outline" size="icon" aria-label="Submit">
  <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>
  )
}
<Button variant="outline" size="sm">
  <IconGitBranch /> New Branch
</Button>

Rounded

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

import { ArrowUp } 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">
        <ArrowUp />
      </Button>
    </div>
  )
}
<Button variant="outline" size="icon" className="rounded-full">
  <ArrowUpRightIcon />
</Button>

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 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 {
  Archive,
  ArrowLeft,
  CalendarDays,
  Clock,
  ListPlus,
  MailCheck,
  MoreHorizontal,
  Tag,
  Trash2,
} from "lucide-react"

import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSeparator,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

export function ButtonGroupDemo() {
  const [label, setLabel] = React.useState("personal")

  return (
    <ButtonGroup>
      <ButtonGroup className="hidden sm:flex">
        <Button variant="outline" size="icon" aria-label="Go Back">
          <ArrowLeft />
        </Button>
      </ButtonGroup>
      <ButtonGroup>
        <Button variant="outline">Archive</Button>
        <Button variant="outline">Report</Button>
      </ButtonGroup>
      <ButtonGroup>
        <Button variant="outline">Snooze</Button>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="outline" size="icon" aria-label="More Options">
              <MoreHorizontal />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" className="w-52">
            <DropdownMenuGroup>
              <DropdownMenuItem>
                <MailCheck />
                Mark as Read
              </DropdownMenuItem>
              <DropdownMenuItem>
                <Archive />
                Archive
              </DropdownMenuItem>
            </DropdownMenuGroup>
            <DropdownMenuSeparator />
            <DropdownMenuGroup>
              <DropdownMenuItem>
                <Clock />
                Snooze
              </DropdownMenuItem>
              <DropdownMenuItem>
                <CalendarDays />
                Add to Calendar
              </DropdownMenuItem>
              <DropdownMenuItem>
                <ListPlus />
                Add to List
              </DropdownMenuItem>
              <DropdownMenuSub>
                <DropdownMenuSubTrigger>
                  <Tag />
                  Label As...
                </DropdownMenuSubTrigger>
                <DropdownMenuSubContent>
                  <DropdownMenuRadioGroup
                    value={label}
                    onValueChange={setLabel}
                  >
                    <DropdownMenuRadioItem value="personal">
                      Personal
                    </DropdownMenuRadioItem>
                    <DropdownMenuRadioItem value="work">
                      Work
                    </DropdownMenuRadioItem>
                    <DropdownMenuRadioItem value="other">
                      Other
                    </DropdownMenuRadioItem>
                  </DropdownMenuRadioGroup>
                </DropdownMenuSubContent>
              </DropdownMenuSub>
            </DropdownMenuGroup>
            <DropdownMenuSeparator />
            <DropdownMenuGroup>
              <DropdownMenuItem variant="destructive">
                <Trash2 />
                Trash
              </DropdownMenuItem>
            </DropdownMenuGroup>
          </DropdownMenuContent>
        </DropdownMenu>
      </ButtonGroup>
    </ButtonGroup>
  )
}
<ButtonGroup>
  <ButtonGroup>
    <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>
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="outline" size="icon" aria-label="More Options">
          <MoreHorizontalIcon />
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent />
    </DropdownMenu>
  </ButtonGroup>
</ButtonGroup>

Link

You can use the asChild prop 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 "@/components/ui/button"
 
export function LinkAsButton() {
  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" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg""default"
asChildbooleanfalse

Changelog

2025-09-24 New sizes

We have added two new sizes to the button component: icon-sm and icon-lg. These sizes are used to create icon buttons. To add them, edit button.tsx and add the following code under size in buttonVariants:

components/ui/button.tsx
const buttonVariants = cva("...", {
  variants: {
    size: {
      // ...
      "icon-sm": "size-8",
      "icon-lg": "size-10",
      // ...
    },
  },
})
Button GroupCard

On This Page

InstallationUsageCursorExamplesSizeDefaultOutlineSecondaryGhostDestructiveLinkIconWith IconRoundedSpinnerButton GroupLinkAPI ReferenceButtonChangelog2025-09-24 New sizes

© 2025 pitsi/ui. All rights reserved.

Sign In