ButtonGroup
button-groupJoins related buttons into a segmented horizontal or vertical control.
Usage
Continuous row icon group
Default attached: The sub-buttons are integrated into one, the inner corners are smoothed, and the borders are merged. Subitem variant recommends the same.
<ButtonGroup aria-label="Alignment">
<Button variant="outline" size="icon" aria-label="Left aligned"><AlignLeft className="size-4" /></Button>
<Button variant="outline" size="icon" aria-label="center"><AlignCenter className="size-4" /></Button>
<Button variant="outline" size="icon" aria-label="right aligned"><AlignRight className="size-4" /></Button>
</ButtonGroup>Icon + text segmentation
Toolbar-style segmented operation, with copywriting for each segment icon.
<ButtonGroup aria-label="Text Format">
<Button variant="outline"><Bold className="size-4" />Bold</Button>
<Button variant="outline"><Italic className="size-4" />italic</Button>
<Button variant="outline"><Underline className="size-4" />underscore</Button>
</ButtonGroup>Split button
Main operation + a drop-down triggered "More", commonly seen in save/submit scenarios.
<ButtonGroup aria-label="Save">
<Button>Save</Button>
<Button size="icon" aria-label="More saving options"><ChevronDown className="size-4" /></Button>
</ButtonGroup>Vertically arranged
orientation="vertical" Change to upper and lower rows, smooth the upper and lower inner fillets.
<ButtonGroup orientation="vertical" aria-label="Tools">
<Button variant="outline">Copy</Button>
<Button variant="outline">Paste</Button>
<Button variant="outline">Delete</Button>
</ButtonGroup>Separate grouping
When attached={false}, gap is left between the sub-buttons, which is only used for semantic/alignment grouping and does not fit.
<ButtonGroup attached={false} aria-label="Operation">
<Button variant="outline">Cancel</Button>
<Button>OK</Button>
</ButtonGroup>When to use
Use ButtonGroup for related Buttons, such as toolbar segments, a split button with a primary action and menu, or a decrement/value/increment stepper. The default attached mode joins adjacent controls; pass attached={false} to preserve spacing while keeping the semantic group. ButtonGroup only provides layout and does not override each child's variant or size. Use Button directly for a standalone action.
Import
import { ButtonGroup } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| orientation | "horizontal" | "vertical" | "horizontal" | Layout direction. |
| attached | boolean | true | Joins child controls by removing inner radii and merging adjacent borders. Pass false to keep the configured gap. |
| gap | "sm" | "md" | "sm" | Gap between children when attached={false}. |
| className | string | - | Additional class name for the root element. |
| aria-label | string | - | Accessible label for the group. |
Slots
| Slot | Type | Description |
|---|---|---|
| children | ReactNode | Usually <Button> elements; trigger buttons wrapped by Dropdown or Tooltip are also supported. |
Usage guidelines
- Members must share the same height, especially in attached mode. Attaching works by pulling each neighbor over with
-ml-pxso their borders overlap, and that seam assumes every member is the same height; once heights differ, the shorter ones leave a visible step above and below. In Button's size scale, every icon size matches the text size of the same name (iconSm/sm32,icon/md40,iconLg/lg48), so pick the matching pair when mixing icons and labels. Mixing across steps (a defaultmd<Button>next tosize="iconSm", say) still leaves an 8px step. Before 0.26.0,iconwas an isolated 36px that matched no text size (#97); after upgrading, existing markup of this shape lines up on its own. - You cannot spot the above by reading the code: all three buttons say
variant="outline"and either omitsizeor set it on just one of them, which reads perfectly tidy. The middle one being 4px taller only shows up once rendered. The classic case is a−/value/+stepper. gaponly applies whenattached={false}. In attached mode, the component joins corners and borders without adding margins between child controls.
Related
Button · ShimmerButton · RainbowButton · PulsatingButton · RippleButton · SocialButton
Playground
<ButtonGroup>
<Button variant="outline">one</Button>
<Button variant="outline">two</Button>
<Button variant="outline">three</Button>
</ButtonGroup>