Button Group
A container that groups related buttons together with consistent styling.
ButtonGroupExample
Examples
Orientation
Set orientation="vertical" to stack buttons instead of placing them in a row.
ButtonGroupOrientationExample
Separator
Use ButtonGroupSeparator to visually divide buttons. The outline variant already has borders, so separators are most useful for solid variants.
ButtonGroupSeparatorExample
Text
Use ButtonGroupText for static prefixes and suffixes, and mix in an Input to build composed fields.
ButtonGroupTextExample
Nested
Nest multiple ButtonGroup components to add spacing between clusters of related actions.
ButtonGroupNestedExample
Installation
Copy the source code below into your project:
import { mergeProps, useRender } from "@base-ui/react";
import { Separator } from "./separator";
import { cn } from "@/lib/utils";
import { cva } from "class-variance-authority";
import type { ComponentProps } from "react";
import type { VariantProps } from "class-variance-authority";
const buttonGroupVariants = cva(
"flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
{
defaultVariants: {
orientation: "horizontal",
},
variants: {
orientation: {
horizontal:
"[&>*:not(:first-child)]:-ms-px [&>*:not(:first-child)]:rounded-l-none [&>*:not(:last-child)]:rounded-r-none",
vertical:
"flex-col [&>*:not(:first-child)]:-mt-px [&>*:not(:first-child)]:rounded-t-none [&>*:not(:last-child)]:rounded-b-none",
},
},
},
);
function ButtonGroup({
className,
orientation = "horizontal",
...props
}: ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {
return (
<div
className={cn(buttonGroupVariants({ orientation }), className)}
data-orientation={orientation}
data-slot="button-group"
role="group"
{...props}
/>
);
}
function ButtonGroupText({ className, render, ...props }: useRender.ComponentProps<"div">) {
return useRender({
defaultTagName: "div",
props: {
...mergeProps<"div">(props, {
className: cn(
"flex items-center gap-2 rounded-lg border border-input bg-muted px-4 text-sm font-medium text-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
className,
),
}),
"data-slot": "button-group-text",
},
render,
});
}
function ButtonGroupSeparator({
className,
orientation = "vertical",
...props
}: ComponentProps<typeof Separator>) {
return (
<Separator
className={cn(
"relative m-0! self-stretch bg-border data-[orientation=vertical]:h-auto",
className,
)}
data-slot="button-group-separator"
orientation={orientation}
{...props}
/>
);
}
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants };API Reference
ButtonGroup
| Prop | Type | Default | Description |
|---|---|---|---|
| orientation | "horizontal" | "vertical" | "horizontal" | Layout direction of the grouped buttons. |
ButtonGroupSeparator
The ButtonGroupSeparator component extends the Ink UI Separator props and adds the following:
| Prop | Type | Default | Description |
|---|---|---|---|
| orientation | "horizontal" | "vertical" | "vertical" | Orientation of the separator within the group. |
ButtonGroupText
| Prop | Type | Default | Description |
|---|---|---|---|
| render | ReactElement | ((props, state) => ReactElement) | - | Render the text as a custom element instead of a div. |