shadcn.io is not affiliated with official shadcn/ui
Shadcn Button Group for React
Visually connected buttons and related controls.
Installation
bunx --bun shadcn@latest add https://kit.dev/r/radix/button-group.jsonnpx shadcn@latest add https://kit.dev/r/radix/button-group.jsonpnpm dlx shadcn@latest add https://kit.dev/r/radix/button-group.jsonyarn shadcn@latest add https://kit.dev/r/radix/button-group.jsonThis component depends on Separator. Install it first if you haven't already.
Install the following dependencies:
bun add radix-ui tailwind-variantsnpm install radix-ui tailwind-variantspnpm add radix-ui tailwind-variantsyarn add radix-ui tailwind-variantsCopy and paste the following code into your project.
import { Slot } from "radix-ui";
import type React from "react";
import { tv, type VariantProps } from "tailwind-variants";
import { cn } from "@/lib/utils";
import { Separator } from "@/registry/radix/components/separator";
export const buttonGroupVariants = tv({
base: "cn-button-group group/button-group flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
defaultVariants: {
orientation: "horizontal",
},
variants: {
orientation: {
horizontal:
"cn-button-group-orientation-horizontal [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
vertical:
"cn-button-group-orientation-vertical flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
},Update the import paths to match your project setup.
Usage
import {
ArchiveIcon,
ArrowLeftIcon,
CalendarPlusIcon,
ClockIcon,
ListFilterIcon,
MailCheckIcon,
MoreHorizontalIcon,
TagIcon,
Trash2Icon,
} from "lucide-react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { ButtonGroup } from "@/components/ui/button-group";
import {
Menu,
MenuContent,
MenuGroup,
MenuItem,
MenuRadioGroup,
MenuRadioItem,
MenuSeparator,
MenuSub,
MenuSubContent,
MenuSubTrigger,
MenuTrigger,
} from "@/components/ui/menu";const ButtonGroupDemo = () => {
const [label, setLabel] = useState("personal");
const handleLabelChange = (details: { value: string }) => {
setLabel(details.value);
};
return (
<ButtonGroup>
<ButtonGroup className="hidden sm:flex">
<Button aria-label="Go Back" size="icon-md" variant="outline">
<ArrowLeftIcon aria-hidden="true" />
</Button>
</ButtonGroup>
<ButtonGroup>
<Button variant="outline">Archive</Button>
<Button variant="outline">Report</Button>
</ButtonGroup>
<ButtonGroup>
<Button variant="outline">Snooze</Button>
<Menu>
<MenuTrigger asChild>
<Button aria-label="More Options" size="icon-md" variant="outline">
<MoreHorizontalIcon aria-hidden="true" />
</Button>
</MenuTrigger>
<MenuContent className="w-40">
<MenuGroup>
<MenuItem value="mark-as-read">
<MailCheckIcon aria-hidden="true" />
Mark as Read
</MenuItem>
<MenuItem value="archive">
<ArchiveIcon aria-hidden="true" />
Archive
</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuItem value="snooze">
<ClockIcon aria-hidden="true" />
Snooze
</MenuItem>
<MenuItem value="add-to-calendar">
<CalendarPlusIcon aria-hidden="true" />
Add to Calendar
</MenuItem>
<MenuItem value="add-to-list">
<ListFilterIcon aria-hidden="true" />
Add to List
</MenuItem>
<MenuSub>
<MenuSubTrigger>
<TagIcon aria-hidden="true" />
Label As...
</MenuSubTrigger>
<MenuSubContent>
<MenuRadioGroup
onValueChange={handleLabelChange}
value={label}
>
<MenuRadioItem value="personal">Personal</MenuRadioItem>
<MenuRadioItem value="work">Work</MenuRadioItem>
<MenuRadioItem value="other">Other</MenuRadioItem>
</MenuRadioGroup>
</MenuSubContent>
</MenuSub>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuItem value="trash" variant="destructive">
<Trash2Icon aria-hidden="true" />
Trash
</MenuItem>
</MenuGroup>
</MenuContent>
</Menu>
</ButtonGroup>
</ButtonGroup>
);
};
Accessibility
| Key | Description |
|---|---|
Enter | Activate the focused control. |
Space | Activate the focused control. |
ArrowDown | Move down. |
ArrowUp | Move up. |
ArrowLeft | Move left. |
ArrowRight | Move right. |
Home | Go to the start. |
End | Go to the end. |
Demos
Orientation
Set the orientation prop to change the button group layout.
Size
Control the size of buttons using the size prop on individual buttons.
Nested
Nest ButtonGroup components to create button groups with spacing.
Separator
ButtonGroupSeparator visually divides buttons within a group.
Split
Create a split button group with ButtonGroupSeparator.
Input
Wrap an Input component with buttons.
Input Group
Wrap an InputGroup to create complex input layouts.
Dropdown
Create a split button group with a Menu.
Select
Pair with a Select component.
Popover
Use with a Popover component.
Rtl
Right-to-left button group. See the RTL configuration guide for document direction.
API Reference
ButtonGroup
PropType
AttributeType
ButtonGroupText
PropType
AttributeType
ButtonGroupSeparator
PropType
AttributeType