Primitives
Button group
Joined button group for toolbars, split actions, and segmented controls.
Composition
The preferred shape for composing the installed primitive from its exported parts.
Parts
Exported compound parts from the installed source.
ButtonGroup├── ButtonGroupText└── ButtonGroupSeparatorThe refined source installs this primitive from src/registry/sources/refined/ui/button-group.tsx. Install it on its own with the command above, or inspect the source below.
npx shadcn@latest add http://127.0.0.1:3000/r/refined/button-group.jsonRaw code
Primary installed primitive source
Button group slot
src/registry/sources/refined/ui/button-group.tsx
import { cva } from "class-variance-authority";import type { ComponentProps } from "react";import type { ButtonGroupProps, ButtonGroupSeparatorProps, ControlSize } from "@/components/refined-ui/contracts";import { controlSize } from "@/components/refined-ui/control-variants";import { cn } from "@/components/refined-ui/lib/cn";import { skinSlot } from "@/components/refined-ui/skin";// Plain-markup wrapper (no Base UI): collapses inner corners + overlaps borders (-ml-px/-mt-px) into one segmented control; focus-within:z-10 lifts ring above the overlap.const buttonGroupVariant = cva("inline-flex w-fit items-stretch [&>*]:relative [&>*]:focus-within:z-10", { variants: { orientation: { horizontal: "flex-row [&>*:not(:first-child)]:-ml-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", }, }, defaultVariants: { orientation: "horizontal", },});export function ButtonGroup({ orientation = "horizontal", className, ...props }: ButtonGroupProps) { return ( // biome-ignore lint/a11y/useSemanticElements: a segmented control is a labelled group, not a fieldset form group. <div role="group" data-ui="agent" data-slot="button-group" data-orientation={orientation} className={cn(buttonGroupVariant({ orientation }), skinSlot("button-group", { orientation }), className)} {...props} /> );}// Non-interactive addon label styled to fuse with the group, e.g. a `https://` prefix or unit suffix.type ButtonGroupTextProps = ComponentProps<"div"> & { size?: ControlSize;};export function ButtonGroupText({ size = "sm", className, ...props }: ButtonGroupTextProps) { return ( <div data-ui="agent" data-slot="button-group-text" data-size={size} className={cn( "inline-flex items-center whitespace-nowrap rounded-[var(--radius-control)] border bg-card/72 font-medium text-muted-foreground shadow-sm [&>svg]:pointer-events-none [&>svg]:size-4 [&>svg]:shrink-0", controlSize({ size }), skinSlot("button-group-text", {}), className, )} {...props} /> );}export function ButtonGroupSeparator({ orientation = "vertical", className, ...props }: ButtonGroupSeparatorProps) { return ( <div aria-hidden="true" data-ui="agent" data-slot="button-group-separator" data-orientation={orientation} className={cn("shrink-0 self-stretch bg-border", orientation === "vertical" ? "w-px" : "h-px w-full", className)} {...props} /> );}