Getting Started
Components52
- Accordion
- Alert
- Alert Dialog
- Attachment
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Checkbox
- Collapsible
- Command
- Context Menu
- Data Table
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Pagination
- Popover
- Progress
- Questionnaire
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
"use client"
import { ArrowLeftIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
export function ButtonGroupDemo() {
return (
<div className="flex flex-wrap items-center gap-2">
<ButtonGroup>
<Button variant="secondary" size="icon" aria-label="Go back">
<ArrowLeftIcon />
</Button>
<Button variant="secondary">Archive</Button>
<Button variant="secondary">Report</Button>
<Button variant="secondary">Snooze</Button>
</ButtonGroup>
<ButtonGroup>
<Button variant="outline">Day</Button>
<Button variant="outline">Week</Button>
<Button variant="outline">Month</Button>
</ButtonGroup>
</div>
)
}Installation#
pnpm dlx shadcn@latest add https://ui.ikramhasan.com/r/button-group.json
Usage#
import {
ButtonGroup,
ButtonGroupSeparator,
ButtonGroupText,
} from "@/components/ui/button-group"<ButtonGroup>
<Button>Button 1</Button>
<Button>Button 2</Button>
</ButtonGroup>Examples#
Nested#
"use client"
import { MinusIcon, PlusIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
export function ButtonGroupNested() {
return (
<ButtonGroup>
<ButtonGroup>
<Button variant="secondary" size="sm">
1
</Button>
<Button variant="secondary" size="sm">
2
</Button>
<Button variant="secondary" size="sm">
3
</Button>
</ButtonGroup>
<ButtonGroup>
<Button variant="secondary" size="icon-sm" aria-label="Previous">
<MinusIcon />
</Button>
<Button variant="secondary" size="icon-sm" aria-label="Next">
<PlusIcon />
</Button>
</ButtonGroup>
</ButtonGroup>
)
}Split button with a separator#
"use client"
import { ArchiveIcon, ChevronDownIcon, CopyIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup, ButtonGroupSeparator } from "@/components/ui/button-group"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
export function ButtonGroupSplit() {
return (
<div className="flex flex-wrap items-center gap-2">
<ButtonGroup>
<Button>
<CopyIcon data-icon="inline-start" />
Copy
</Button>
<ButtonGroupSeparator />
<DropdownMenu>
<DropdownMenuTrigger
render={<Button size="icon" aria-label="More copy options" />}
>
<ChevronDownIcon />
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-40">
<DropdownMenuItem>Copy link</DropdownMenuItem>
<DropdownMenuItem>Copy as Markdown</DropdownMenuItem>
<DropdownMenuItem>
<ArchiveIcon />
Archive
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</ButtonGroup>
<ButtonGroup>
<Button variant="secondary">Follow</Button>
<ButtonGroupSeparator />
<Button variant="secondary" size="icon" aria-label="More options">
<ChevronDownIcon />
</Button>
</ButtonGroup>
</div>
)
}With input, text and select#
.com
"use client"
import { SearchIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup, ButtonGroupText } from "@/components/ui/button-group"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
export function ButtonGroupInput() {
return (
<div className="flex flex-wrap items-center gap-2">
<ButtonGroup className="w-full max-w-xs">
<Input placeholder="Search…" aria-label="Search" />
<Button variant="secondary" size="icon" aria-label="Search">
<SearchIcon />
</Button>
</ButtonGroup>
<ButtonGroup>
<ButtonGroupText render={<Label htmlFor="bg-url" />}>
https://
</ButtonGroupText>
<Input id="bg-url" placeholder="example.com" className="w-40" />
<ButtonGroupText>.com</ButtonGroupText>
</ButtonGroup>
<ButtonGroup>
<Select items={currencies} defaultValue="usd">
<SelectTrigger aria-label="Currency">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{currencies.map((c) => (
<SelectItem key={c.value} value={c.value}>
{c.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<Input placeholder="10.00" aria-label="Amount" className="w-28" />
</ButtonGroup>
</div>
)
}
const currencies = [
{ label: "USD", value: "usd" },
{ label: "EUR", value: "eur" },
{ label: "GBP", value: "gbp" },
]Vertical#
"use client"
import { MinusIcon, PlusIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
export function ButtonGroupVertical() {
return (
<ButtonGroup orientation="vertical" aria-label="Zoom">
<Button variant="secondary" size="icon" aria-label="Zoom in">
<PlusIcon />
</Button>
<Button variant="secondary" size="icon" aria-label="Zoom out">
<MinusIcon />
</Button>
</ButtonGroup>
)
}API Reference#
ButtonGroup#
The ButtonGroup component is a container that groups related buttons together with consistent styling.
| Prop | Type | Default |
|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" |
<ButtonGroup>
<Button>Button 1</Button>
<Button>Button 2</Button>
</ButtonGroup>Nest multiple button groups to create complex layouts with spacing. See the nested example for more details.
<ButtonGroup>
<ButtonGroup />
<ButtonGroup />
</ButtonGroup>ButtonGroupSeparator#
The ButtonGroupSeparator component visually divides buttons within a group.
| Prop | Type | Default |
|---|---|---|
orientation | "horizontal" | "vertical" | "vertical" |
<ButtonGroup>
<Button>Button 1</Button>
<ButtonGroupSeparator />
<Button>Button 2</Button>
</ButtonGroup>ButtonGroupText#
Use this component to display text within a button group.
| Prop | Type | Default |
|---|---|---|
render | React.ReactElement |
<ButtonGroup>
<ButtonGroupText>Text</ButtonGroupText>
<Button>Button</Button>
</ButtonGroup>Use the render prop to render a custom component as the text, for example a label.
import { ButtonGroupText } from "@/components/ui/button-group"
import { Label } from "@/components/ui/label"
export function ButtonGroupTextDemo() {
return (
<ButtonGroup>
<ButtonGroupText render={<Label htmlFor="name" />}>Text</ButtonGroupText>
<Input placeholder="Type something here..." id="name" />
</ButtonGroup>
)
}