Button group
Joins related buttons into one control, like a record's Edit, Clone and More.
Installation
The CLI installs the Radix or Base UI file to match your project, with what it builds on: separator.
If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.
When to use
Use it
- A few related actions sit together, like a record's Edit, Clone and Delete.
- A main action has a menu of related ones beside it, as a split button.
- An input needs a fixed prefix and an action, like a web address with Visit.
Don't use it
- The buttons stay pressed to show a choice. Use Toggle Group.
- The actions aren't related, or there are more than about four. Use separate buttons, or Dropdown Menu for the rest.
- An input needs icons or buttons inside its frame. Use Input Group.
Usage
import { Button } from "@/components/ui/button"
import {
ButtonGroup,
ButtonGroupSeparator,
ButtonGroupText,
} from "@/components/ui/button-group"ButtonGroup
├── ButtonGroupText (optional, fixed text before an Input)
├── Button
├── ButtonGroupSeparator (between filled buttons)
└── DropdownMenuTrigger (optional, a menu at the end)<ButtonGroup aria-label="Approval">
<Button variant="outline">Approve</Button>
<Button variant="outline">Reject</Button>
</ButtonGroup>Style a menu trigger in the group with className={buttonVariants({ variant: "outline", size: "icon" })}, as the Record actions example does. A ButtonGroup inside another keeps two sets apart, as Nested shows.
Examples
Brand
Two brand buttons, with the inset line the group draws between them.
Split button
A brand button and its options button, split by a `ButtonGroupSeparator`.
Nested
Two `ButtonGroup`s inside a third, kept apart, one with a disabled button.
Text
Fixed text in `ButtonGroupText`, an `Input` that takes the space left, and a button.
Vertical
Two icon buttons stacked with `orientation="vertical"` on `ButtonGroup`.
API reference
| Part | Built on |
|---|---|
ButtonGroup | <div> (opens in a new tab) |
ButtonGroupText | <div> (opens in a new tab) |
ButtonGroupSeparator | Separator |
ButtonGroup
| Prop | Type | Default |
|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" |
ButtonGroupText
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Renders the child element in its place, with the props merged onto it. |
ButtonGroupSeparator
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | "vertical" | Either vertical or horizontal. |
SLDS mapping
ButtonGroup is slds-button-group: the buttons join, inner corners square, each keeping its start border and all but the last dropping their end border. A focused button takes SLDS's group focus, a brand button after a brand button gets SLDS's inset line, and nested groups sit apart as .slds-button-group + .slds-button-group do.
Known gaps:
- SLDS has no text part.
ButtonGroupTextis a box joined to the buttons, in the neutral button's border and radius. SLDS's nearest pattern, fixed text beside an input (slds-form-element__addon), sits outside the field without a box. - SLDS has no separator element; between brand buttons it draws a line.
ButtonGroupSeparatordraws that line next to a filled button, and a border-colored one between bordered buttons. - SLDS has no vertical group.
orientation="vertical"mirrors the horizontal one. - In Lightning Blue, SLDS keeps the line between two brand buttons while the second is hovered. Ours drops it on hover.
| Prop | Value | SLDS | Notes |
|---|---|---|---|
orientation | horizontal | slds-button-group | Buttons joined in a row. ButtonGroupText and ButtonGroupSeparator have no SLDS counterpart. |
orientation | vertical | none | SLDS has no vertical group; it mirrors the horizontal one. |
Accessibility
- Name the group with
aria-label, like "Record actions". It has thegrouprole. - Name icon-only buttons and triggers with
aria-label. ButtonGroupTextis plain text, not a label. Name an input beside it witharia-labelor a Label.
Responsive behavior
- The group is as wide as its children and doesn't wrap. Give it a width and an
Inputinside takes the space left, as the Text example shows. - Keep groups to a few short labels, and move extra actions into a menu on narrow screens.
Rules
- Use
variant="outline"for a neutral group, and the brand variant only for the main action. - Don't restyle the buttons' borders or corners inside a group. The group sets them.
- Use
ButtonGroupSeparatorbetween filled buttons, as in a split button. Bordered buttons already share a border.
Related
- Toggle groupJoins toggles in a row, one or several pressed, like Day, Week and Month.
- Dropdown menuOpens a menu of actions or options from a button, like a record's row actions.
- Input groupPuts icons, text or buttons inside an input or textarea.
- ButtonRuns an action on the page, like Save, Edit or New.