Use one button for everything from primary actions to quiet icon controls. Change its emphasis and dimensions with variant and size.
import { Button } from "@/components/ui/button"export function Example() { return ( <> <Button variant="outline">Button</Button> <Button variant="outline" size="icon" aria-label="Upload"> <ArrowUpIcon /> </Button> </> )}Installation
npx @arctis-sh/@arctis-sh/ui@latest add buttonUsage
import { Button, ButtonGroup, buttonVariants } from "@/components/ui/button"<Button variant="outline">Button</Button><Button variant="default | secondary | destructive | outline | ghost | link"> Button</Button>Size
Use size for text buttons. Dedicated icon-only sizes are covered below.
import { Button } from "@/components/ui/button"export function Example() { return ( <> <Button size="xs"> Extra Small <ArrowUpRightIcon data-icon="inline-end" /> </Button> <Button size="sm"> Small <ArrowUpRightIcon data-icon="inline-end" /> </Button> <Button> Default <ArrowUpRightIcon data-icon="inline-end" /> </Button> <Button size="lg"> Large <ArrowUpRightIcon data-icon="inline-end" /> </Button> </> )}Default
A solid treatment for the primary action.
import { Button } from "@/components/ui/button"export function Example() { return <Button>Button</Button>}Outline
A bordered treatment with a transparent fill and accent hover.
import { Button } from "@/components/ui/button"export function Example() { return <Button variant="outline">Outline</Button>}Secondary
A softer fill for supporting actions.
import { Button } from "@/components/ui/button"export function Example() { return <Button variant="secondary">Secondary</Button>}Ghost
No fill until hover. A good fit for toolbars and compact interfaces.
import { Button } from "@/components/ui/button"export function Example() { return <Button variant="ghost">Ghost</Button>}Destructive
Use for deletion and other irreversible actions.
import { Button } from "@/components/ui/button"export function Example() { return <Button variant="destructive">Destructive</Button>}Link
An inline text treatment with an underline on hover.
import { Button } from "@/components/ui/button"export function Example() { return <Button variant="link">Link</Button>}Icon
Use the square sizes for icon-only controls, and always provide an aria-label.
import { Button } from "@/components/ui/button"export function Example() { return ( <> <Button size="icon-xs" aria-label="Update"> <CircleFadingArrowUpIcon /> </Button> <Button size="icon-sm" aria-label="Update"> <CircleFadingArrowUpIcon /> </Button> <Button size="icon" aria-label="Update"> <CircleFadingArrowUpIcon /> </Button> <Button size="icon-lg" aria-label="Update"> <CircleFadingArrowUpIcon /> </Button> </> )}With icon
Place an SVG inside the button. Add data-icon="inline-start" or data-icon="inline-end" to tighten spacing on that side.
import { Button } from "@/components/ui/button"export function Example() { return ( <> <Button variant="outline"> <GitBranchIcon data-icon="inline-start" /> New Branch </Button> <Button variant="outline"> <GitForkIcon data-icon="inline-start" /> Fork </Button> </> )}Rounded
Add !rounded-full for a pill shape. It overrides the default rounded-md.
import { Button } from "@/components/ui/button"export function Example() { return ( <> <Button className="!rounded-full">Get Started</Button> <Button className="!rounded-full" size="icon" aria-label="Upload"> <ArrowUpIcon /> </Button> </> )}Spinner
Set loading to replace the label with a centered spinner. The button keeps its width and remains disabled while loading.
import { useState } from "react"import { Button } from "@/components/ui/button"export function Example() { const [loading, setLoading] = useState(false) return ( <Button loading={loading} onClick={() => { setLoading(true) window.setTimeout(() => setLoading(false), 1600) }} > Submit </Button> )}Button group
Wrap related buttons in ButtonGroup to join their edges into one compact control.
import { Button, ButtonGroup, buttonVariants,} from "@/components/ui/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger,} from "@/components/ui/dropdown-menu"export function Example() { return ( <div className="flex flex-wrap items-center gap-2"> <Button variant="outline" size="icon" aria-label="Back"> <ArrowLeftIcon /> </Button> <ButtonGroup> <Button variant="outline">Archive</Button> <Button variant="outline">Report</Button> </ButtonGroup> <ButtonGroup> <Button variant="outline">Snooze</Button> <DropdownMenu> <DropdownMenuTrigger aria-label="More actions" className={buttonVariants({ variant: "outline", size: "icon" })} > <MoreHorizontalIcon /> </DropdownMenuTrigger> <DropdownMenuContent align="end"> <DropdownMenuItem> <CheckIcon /> Mark as done </DropdownMenuItem> <DropdownMenuItem> <ArchiveIcon /> Move to archive </DropdownMenuItem> <DropdownMenuSeparator /> <DropdownMenuItem> <ClockIcon /> Remind me later </DropdownMenuItem> <DropdownMenuItem> <PinIcon /> Pin this scene </DropdownMenuItem> <DropdownMenuItem> <ShareIcon /> Copy share link </DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> </ButtonGroup> </div> )}import { Button, ButtonGroup } from "@/components/ui/button"<ButtonGroup> <Button variant="outline">Archive</Button> <Button variant="outline">Report</Button></ButtonGroup>As link
Use buttonVariants on an anchor when the action navigates. This keeps the correct link semantics while matching the button styles.
import { buttonVariants } from "@/components/ui/button"export function Example() { return ( <a href="#login" className={buttonVariants()}> Login </a> )}API Reference
Button
| Prop | Type | Default |
|---|---|---|
| variant | "default" | "secondary" | "destructive" | "outline" | "ghost" | "link" | "default" |
| size | "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | "default" |
| loading | boolean | false |
| className | string | — |
<Button variant="outline">Save</Button>buttonVariants
Returns the same classes as Button for links and other elements.
| Prop | Type | Default |
|---|---|---|
| variant | "default" | "secondary" | "destructive" | "outline" | "ghost" | "link" | "default" |
| size | "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | "default" |
| className | string | — |
<a className={buttonVariants({ variant: "outline" })} href="/docs"> Docs</a>ButtonGroup
Also exported from @arctis-sh/ui/button. See Button Group.
| Prop | Type | Default |
|---|---|---|
| orientation | "horizontal" | "vertical" | "horizontal" |
| className | string | — |
<ButtonGroup> <Button variant="outline">Left</Button> <Button variant="outline">Right</Button></ButtonGroup>