✨ Working with PDFs, images or videos? Discover 145+ free web apps built for everyday tasks

Button Group

Grouped actions for toolbars, split buttons, and menus.

Loading preview...

Examples

Practical examples and common states for the same installable component.

Default

Related actions share one boundary, separators, and a single overflow menu.

examples/button-group-default.tsx
"use client";
import {
IconChevronLeft,
IconCopy,
IconDots,
IconFileExport,
IconHistory,
IconShare3,
IconTrash,
} from "@tabler/icons-react";
import {
ButtonGroup,
ButtonGroupItem,
ButtonGroupMenu,
ButtonGroupMenuContent,
ButtonGroupMenuItem,
ButtonGroupMenuLabel,
ButtonGroupMenuSeparator,
ButtonGroupMenuTrigger,
ButtonGroupSeparator,
} from "@/components/wensity/button-group";
export function DraftActions() {
return (
<ButtonGroup aria-label="Draft actions">
<ButtonGroupItem size="icon" aria-label="Previous draft">
<IconChevronLeft />
</ButtonGroupItem>
<ButtonGroupSeparator />
<ButtonGroupItem>Save draft</ButtonGroupItem>
<ButtonGroupSeparator />
<ButtonGroupItem>Publish</ButtonGroupItem>
<ButtonGroupSeparator />
<ButtonGroupItem>Share</ButtonGroupItem>
<ButtonGroupSeparator />
<ButtonGroupMenu>
<ButtonGroupMenuTrigger size="icon" aria-label="More draft actions">
<IconDots />
</ButtonGroupMenuTrigger>
<ButtonGroupMenuContent align="end">
<ButtonGroupMenuLabel>Draft</ButtonGroupMenuLabel>
<ButtonGroupMenuItem icon={<IconCopy />} shortcut="Cmd+D">
Duplicate
</ButtonGroupMenuItem>
<ButtonGroupMenuItem icon={<IconHistory />}>
Version history
</ButtonGroupMenuItem>
<ButtonGroupMenuItem icon={<IconFileExport />}>
Export as PDF
</ButtonGroupMenuItem>
<ButtonGroupMenuSeparator />
<ButtonGroupMenuItem icon={<IconShare3 />}>
Copy invite link
</ButtonGroupMenuItem>
<ButtonGroupMenuSeparator />
<ButtonGroupMenuItem destructive icon={<IconTrash />}>
Delete draft
</ButtonGroupMenuItem>
</ButtonGroupMenuContent>
</ButtonGroupMenu>
</ButtonGroup>
);
}

Split Action

Primary action plus menu trigger, clipped to one rounded control.

examples/button-group-split.tsx
import { IconChevronDown, IconMessageCircle } from "@tabler/icons-react";
import {
ButtonGroup,
ButtonGroupItem,
ButtonGroupMenu,
ButtonGroupMenuContent,
ButtonGroupMenuItem,
ButtonGroupMenuTrigger,
ButtonGroupSeparator,
} from "@/components/wensity/button-group";
export function ConversationActions() {
return (
<ButtonGroup aria-label="Conversation actions">
<ButtonGroupItem leftIcon={<IconMessageCircle />}>
Message
</ButtonGroupItem>
<ButtonGroupSeparator />
<ButtonGroupMenu>
<ButtonGroupMenuTrigger size="icon" aria-label="Conversation options">
<IconChevronDown />
</ButtonGroupMenuTrigger>
<ButtonGroupMenuContent align="end">
<ButtonGroupMenuItem>Rename thread</ButtonGroupMenuItem>
<ButtonGroupMenuItem>Copy thread link</ButtonGroupMenuItem>
</ButtonGroupMenuContent>
</ButtonGroupMenu>
</ButtonGroup>
);
}

Icon Group

Icon-only actions keep fixed dimensions and accessible labels.

examples/button-group-icons.tsx
import {
IconChevronLeft,
IconChevronRight,
IconLayoutSidebarLeftCollapse,
IconLayoutSidebarRightCollapse,
} from "@tabler/icons-react";
import {
ButtonGroup,
ButtonGroupItem,
ButtonGroupSeparator,
} from "@/components/wensity/button-group";
export function PanelActions() {
return (
<ButtonGroup aria-label="Panel layout">
<ButtonGroupItem size="icon" aria-label="Collapse left panel">
<IconLayoutSidebarLeftCollapse />
</ButtonGroupItem>
<ButtonGroupSeparator />
<ButtonGroupItem size="icon" aria-label="Previous item">
<IconChevronLeft />
</ButtonGroupItem>
<ButtonGroupSeparator />
<ButtonGroupItem size="icon" aria-label="Next item">
<IconChevronRight />
</ButtonGroupItem>
<ButtonGroupSeparator />
<ButtonGroupItem size="icon" aria-label="Collapse right panel">
<IconLayoutSidebarRightCollapse />
</ButtonGroupItem>
</ButtonGroup>
);
}

Variants

Group items keep Button variants while the shell owns the shared boundary.

examples/button-group-variants.tsx
import {
ButtonGroup,
ButtonGroupItem,
ButtonGroupSeparator,
} from "@/components/wensity/button-group";
export function ButtonGroupVariants() {
return (
<ButtonGroup aria-label="View density">
<ButtonGroupItem>Default</ButtonGroupItem>
<ButtonGroupSeparator />
<ButtonGroupItem variant="secondary">Secondary</ButtonGroupItem>
<ButtonGroupSeparator />
<ButtonGroupItem variant="ghost">Ghost</ButtonGroupItem>
</ButtonGroup>
);
}

Vertical

Stacked groups use horizontal separators and the same item API.

examples/button-group-vertical.tsx
import {
ButtonGroup,
ButtonGroupItem,
ButtonGroupSeparator,
} from "@/components/wensity/button-group";
export function VerticalActions() {
return (
<ButtonGroup orientation="vertical" aria-label="Stacked actions">
<ButtonGroupItem>Rename</ButtonGroupItem>
<ButtonGroupSeparator orientation="horizontal" />
<ButtonGroupItem>Duplicate</ButtonGroupItem>
<ButtonGroupSeparator orientation="horizontal" />
<ButtonGroupItem variant="destructive">Delete</ButtonGroupItem>
</ButtonGroup>
);
}