Installation
Complete project setup first. Your configuration
must select react/base and include your Design System ID.
pnpm exec frontfriend download button-group -f react --primitive baseReview dependencies reported by the downloader and keep your source changes in version control.
Usage
import { ButtonGroup } from "@/components/ui/button-group";
import { Button } from "@/components/ui/button";
<ButtonGroup orientation="horizontal" aria-label="Button group">
<Button variant="tertiary">Button 1</Button>
<Button variant="tertiary">Button 2</Button>
</ButtonGroup>; Examples
Default
import { ButtonGroup } from "@/components/ui/button-group";
import { Button } from "@/components/ui/button";
<ButtonGroup aria-label="Button group">
<Button variant="tertiary">Button 1</Button>
<Button variant="tertiary">Button 2</Button>
</ButtonGroup>; Orientation
import { ButtonGroup } from "@/components/ui/button-group";
import { Button } from "@/components/ui/button";
import { Icon } from "@/components/ui/icon";
<ButtonGroup
orientation="vertical"
aria-label="Media controls"
className="h-fit"
>
<Button variant="tertiary" size="icon" aria-label="Increase">
<Icon name="Plus" size="4" />
</Button>
<Button variant="tertiary" size="icon" aria-label="Decrease">
<Icon name="Minus" size="4" />
</Button>
</ButtonGroup>; Size
import { ButtonGroup } from "@/components/ui/button-group";
import { Button } from "@/components/ui/button";
<div className="flex flex-col items-start gap-8">
<ButtonGroup>
<Button variant="tertiary" size="sm">
Small
</Button>
<Button variant="tertiary" size="sm">
Button
</Button>
<Button variant="tertiary" size="sm">
Group
</Button>
</ButtonGroup>
<ButtonGroup>
<Button variant="tertiary">Default</Button>
<Button variant="tertiary">Button</Button>
<Button variant="tertiary">Group</Button>
</ButtonGroup>
<ButtonGroup>
<Button variant="tertiary" size="lg">
Large
</Button>
<Button variant="tertiary" size="lg">
Button
</Button>
<Button variant="tertiary" size="lg">
Group
</Button>
</ButtonGroup>
</div>; Nested
import { ButtonGroup } from "@/components/ui/button-group";
import { Button } from "@/components/ui/button";
import { Icon } from "@/components/ui/icon";
<ButtonGroup>
<ButtonGroup>
{[1, 2, 3, 4, 5].map((value) => (
<Button key={value} variant="tertiary" size="sm">
{value}
</Button>
))}
</ButtonGroup>
<ButtonGroup>
<Button variant="tertiary" size="icon" aria-label="Previous">
<Icon name="ArrowLeft" size="4" />
</Button>
<Button variant="tertiary" size="icon" aria-label="Next">
<Icon name="ArrowRight" size="4" />
</Button>
</ButtonGroup>
</ButtonGroup>; Separator
import {
ButtonGroup,
ButtonGroupSeparator,
} from "@/components/ui/button-group";
import { Button } from "@/components/ui/button";
<ButtonGroup>
<Button variant="secondary" size="sm">
Copy
</Button>
<ButtonGroupSeparator />
<Button variant="secondary" size="sm">
Paste
</Button>
</ButtonGroup>; Split
import {
ButtonGroup,
ButtonGroupSeparator,
} from "@/components/ui/button-group";
import { Button } from "@/components/ui/button";
import { Icon } from "@/components/ui/icon";
<ButtonGroup>
<Button variant="secondary">Button</Button>
<ButtonGroupSeparator />
<Button size="icon" variant="secondary" aria-label="Add">
<Icon name="Plus" size="4" />
</Button>
</ButtonGroup>; With Input
import { ButtonGroup } from "@/components/ui/button-group";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Icon } from "@/components/ui/icon";
<ButtonGroup>
<Input placeholder="Search..." />
<Button variant="tertiary" aria-label="Search">
<Icon name="Search" size="4" />
</Button>
</ButtonGroup>; With Input Group
import { ButtonGroup } from "@/components/ui/button-group";
import { Button } from "@/components/ui/button";
import { Icon } from "@/components/ui/icon";
import {
InputGroup,
InputGroupInput,
InputGroupAddon,
InputGroupButton,
} from "@/components/ui/input-group";
<ButtonGroup>
<ButtonGroup>
<Button variant="tertiary" size="icon" aria-label="Add">
<Icon name="Plus" size="4" />
</Button>
</ButtonGroup>
<ButtonGroup>
<InputGroup>
<InputGroupInput placeholder="Send a message..." />
<InputGroupAddon align="inline-end">
<InputGroupButton size="icon-xs" aria-label="Share">
<Icon name="Share" size="4" />
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
</ButtonGroup>
</ButtonGroup>; Dropdown
import { ButtonGroup } from "@/components/ui/button-group";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuSeparator,
} from "@/components/ui/dropdown-menu";
import { Icon } from "@/components/ui/icon";
<ButtonGroup>
<Button variant="tertiary">Follow</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="tertiary" className="pl-2" aria-label="More">
<Icon name="ChevronDown" size="4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuGroup>
<DropdownMenuItem>
<Icon name="VolumeOff" size="4" />
Mute Conversation
</DropdownMenuItem>
<DropdownMenuItem>
<Icon name="Check" size="4" />
Mark as Read
</DropdownMenuItem>
<DropdownMenuItem>
<Icon name="Share" size="4" />
Share Conversation
</DropdownMenuItem>
<DropdownMenuItem>
<Icon name="Copy" size="4" />
Copy Conversation
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem variant="destructive">
<Icon name="Trash" size="4" />
Delete Conversation
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</ButtonGroup>; Select Pairing
import { ButtonGroup } from "@/components/ui/button-group";
import {
Select,
SelectTrigger,
SelectContent,
SelectItem,
} from "@/components/ui/select";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Icon } from "@/components/ui/icon";
<ButtonGroup>
<ButtonGroup>
<Select defaultValue="$">
<SelectTrigger className="font-mono">$</SelectTrigger>
<SelectContent className="min-w-24">
<SelectItem value="$">
$ <span className="text-neutral-mid">US Dollar</span>
</SelectItem>
<SelectItem value="€">
€ <span className="text-neutral-mid">Euro</span>
</SelectItem>
<SelectItem value="£">
£ <span className="text-neutral-mid">British Pound</span>
</SelectItem>
</SelectContent>
</Select>
<Input placeholder="10.00" pattern="[0-9]*" />
</ButtonGroup>
<ButtonGroup>
<Button aria-label="Send" size="icon" variant="tertiary">
<Icon name="ArrowRight" size="4" />
</Button>
</ButtonGroup>
</ButtonGroup>; Popover Pairing
import { ButtonGroup } from "@/components/ui/button-group";
import { Button } from "@/components/ui/button";
import { Icon } from "@/components/ui/icon";
import {
Popover,
PopoverTrigger,
PopoverContent,
} from "@/components/ui/popover";
import { Textarea } from "@/components/ui/textarea";
<ButtonGroup>
<Button variant="tertiary">
<Icon name="Bot" size="4" /> Copilot
</Button>
<Popover>
<PopoverTrigger asChild>
<Button variant="tertiary" size="icon" aria-label="Open Popover">
<Icon name="ChevronDown" size="4" />
</Button>
</PopoverTrigger>
<PopoverContent align="end" padding={false}>
<div className="px-4 py-3">
<div className="text-sm font-medium">Agent Tasks</div>
</div>
<div className="border-t border-neutral-subtle p-4 text-sm">
<Textarea
placeholder="Describe your task in natural language."
className="mb-4 resize-none"
/>
<p className="font-medium">Start a new task with Copilot</p>
<p className="text-neutral-mid">
Describe your task in natural language.
</p>
</div>
</PopoverContent>
</Popover>
</ButtonGroup>; Text As Child
import { ButtonGroup, ButtonGroupText } from "@/components/ui/button-group";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
<ButtonGroup>
<ButtonGroupText asChild>
<Label htmlFor="url">https://</Label>
</ButtonGroupText>
<Input id="url" placeholder="frontfriend" />
<ButtonGroupText>.dev</ButtonGroupText>
</ButtonGroup>; API reference
Frontfriend-owned props. Native HTML and inherited primitive props remain documented by Base UI.
ButtonGroup
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | — | Set the button group layout. |
ButtonGroupSeparator
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | "vertical" |
ButtonGroupText
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false |
Configuration determines the actual classes and available styling hooks. See Theming & component configuration before introducing a repeated local override.