ButtonGroup
Joins several Buttons into one set. The corners that face a neighbour are squared off, and shared props are set once on the group.
tsx
import { Button, ButtonGroup } from 'neba';
<ButtonGroup variant="outline">
<Button>Day</Button>
<Button>Week</Button>
<Button>Month</Button>
</ButtonGroup>;Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variantshared | 'solid' | 'outline' | 'text' | — | Applied to every button in the group. Unset means the Button's own default stands |
| sizeshared | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | — | Height and type scale for every button in the group |
| colorshared | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | — | Colour role for every button in the group. A button's own prop still wins |
| densityshared | 'default' | 'compact' | — | Horizontal padding for every button in the group |
| elevationshared | 0 | 1 | 2 | 3 | — | Drop shadow depth for every button in the group |
| orientationshared | 'horizontal' | 'vertical' | 'horizontal' | Which way the buttons run. Vertical flattens the top and bottom corners instead |
| disabled | boolean | — | Disables every button in the group at once |
| fullWidth | boolean | false | Stretches to the container and divides the width evenly between the buttons |
| children | ReactNode | — | The buttons. The shared props reach them even through a wrapper |
Every native <div> attribute passes straight through, minus color.
Examples
Shared props
variant · size · color · density · elevation · disabled set on the group reach every child Button. A value set on a button overrides the group's, so one danger button can sit in a row of secondary actions.
tsx
import { Button, ButtonGroup } from 'neba';
export default function ButtonGroupShared() {
return (
<div className="flex flex-col items-start gap-4">
{/* Set once for the whole group. */}
<ButtonGroup size="sm" variant="outline" color="secondary">
<Button>Copy</Button>
<Button>Duplicate</Button>
<Button>Archive</Button>
</ButtonGroup>
{/* A button can still override what the group said. */}
<ButtonGroup size="sm" variant="outline" color="secondary">
<Button>Copy</Button>
<Button>Duplicate</Button>
<Button color="danger">Delete</Button>
</ButtonGroup>
</div>
);
}orientation
vertical stacks the buttons and squares off the top and bottom corners instead.
tsx
import { Button, ButtonGroup } from 'neba';
export default function ButtonGroupOrientation() {
return (
<div className="flex flex-wrap items-start gap-8">
<ButtonGroup orientation="horizontal" variant="outline">
<Button>Left</Button>
<Button>Centre</Button>
<Button>Right</Button>
</ButtonGroup>
<ButtonGroup orientation="vertical" variant="outline">
<Button>Top</Button>
<Button>Middle</Button>
<Button>Bottom</Button>
</ButtonGroup>
</div>
);
}fullWidth
Stretches the group to the container width, with the buttons sharing the space equally.
tsx
import { Button, ButtonGroup } from 'neba';
export default function ButtonGroupFullWidth() {
return (
<div className="w-full max-w-md">
<ButtonGroup fullWidth variant="outline" color="secondary">
<Button>Cancel</Button>
<Button>Save draft</Button>
<Button>Publish</Button>
</ButtonGroup>
</div>
);
}Accessibility
- Renders
role="group". Give it anaria-labelwhen the button labels alone do not say what the set is for. - It does not manage selection. For one-of-a-set, use SegmentedButton or RadioGroup.
- The hovered or focused button is raised above its neighbours so its focus ring is never clipped.