Button Group

Group related actions, inputs, and menus with shared borders and focus rings.

<ButtonGroup>  <Button variant="outline">Archive</Button>  <Button variant="outline">Report</Button></ButtonGroup>

Usage

import {
  ButtonGroup,
  ButtonGroupSeparator,
  ButtonGroupText,
} from "@reva/ui";

Icon-only controls in a group use Icon Button (Reva does not use shadcn Button size="icon" / icon-sm).

Composition

Use the following composition to build a ButtonGroup:

ButtonGroup
├── Button or Input
├── ButtonGroupSeparator
└── ButtonGroupText

Nest ButtonGroup to cluster controls with spacing between clusters (see Toolbar below).

Examples

Toolbar

Nested groups and a Dropdown Menu with a radio sub-menu—adapted from shadcn. Keep Button and IconButton on the same size in a cluster (here, sm). Add useState for label / setLabel, import icons from @phosphor-icons/react/ssr, and mark the file "use client" when you copy this pattern.

<ButtonGroup>  <ButtonGroup className="hidden sm:flex">    <IconButton variant="outline" size="sm" aria-label="Go Back">      <ArrowLeft />    </IconButton>  </ButtonGroup>  <ButtonGroup>    <Button variant="outline" size="sm">Archive</Button>    <Button variant="outline" size="sm">Report</Button>  </ButtonGroup>  <ButtonGroup>    <Button variant="outline" size="sm">Snooze</Button>    <DropdownMenu>      <DropdownMenuTrigger asChild>        <IconButton variant="outline" size="sm" aria-label="More Options">          <DotsThree />        </IconButton>      </DropdownMenuTrigger>      <DropdownMenuContent align="end" className="w-40">        <DropdownMenuGroup>          <DropdownMenuItem>            <EnvelopeOpen />            Mark as Read          </DropdownMenuItem>          <DropdownMenuItem>            <Archive />            Archive          </DropdownMenuItem>        </DropdownMenuGroup>        <DropdownMenuSeparator />        <DropdownMenuGroup>          <DropdownMenuItem>            <Clock />            Snooze          </DropdownMenuItem>          <DropdownMenuItem>            <CalendarPlus />            Add to Calendar          </DropdownMenuItem>          <DropdownMenuItem>            <FunnelSimple />            Add to List          </DropdownMenuItem>          <DropdownMenuSub>            <DropdownMenuSubTrigger>              <Tag />              Label As...            </DropdownMenuSubTrigger>            <DropdownMenuSubContent>              <DropdownMenuRadioGroup value={label} onValueChange={setLabel}>                <DropdownMenuRadioItem value="personal">Personal</DropdownMenuRadioItem>                <DropdownMenuRadioItem value="work">Work</DropdownMenuRadioItem>                <DropdownMenuRadioItem value="other">Other</DropdownMenuRadioItem>              </DropdownMenuRadioGroup>            </DropdownMenuSubContent>          </DropdownMenuSub>        </DropdownMenuGroup>        <DropdownMenuSeparator />        <DropdownMenuGroup>          <DropdownMenuItem variant="destructive">            <TrashSimple />            Trash          </DropdownMenuItem>        </DropdownMenuGroup>      </DropdownMenuContent>    </DropdownMenu>  </ButtonGroup></ButtonGroup>

Orientation

Set orientation to vertical for a stacked group.

<ButtonGroup orientation="vertical" aria-label="Media controls" className="h-fit">  <IconButton variant="outline" size="sm" aria-label="Increase">    <Plus />  </IconButton>  <IconButton variant="outline" size="sm" aria-label="Decrease">    <Minus />  </IconButton></ButtonGroup>

Size

Control size with each Button or IconButton size prop (xs | sm | default | lg).

<div className="flex flex-col items-center justify-center gap-8">  <ButtonGroup>    <Button variant="outline" size="xs">Extra small</Button>    <Button variant="outline" size="xs">Button</Button>    <Button variant="outline" size="xs">Group</Button>    <IconButton variant="outline" size="xs" aria-label="Add">      <Plus />    </IconButton>  </ButtonGroup>  <ButtonGroup>    <Button variant="outline" size="sm">Small</Button>    <Button variant="outline" size="sm">Button</Button>    <Button variant="outline" size="sm">Group</Button>    <IconButton variant="outline" size="sm" aria-label="Add">      <Plus />    </IconButton>  </ButtonGroup>  <ButtonGroup>    <Button variant="outline">Default</Button>    <Button variant="outline">Button</Button>    <Button variant="outline">Group</Button>    <IconButton variant="outline" aria-label="Add">      <Plus />    </IconButton>  </ButtonGroup></div>

Separator

ButtonGroupSeparator divides controls. Outline buttons often read clearly without one; filled variants benefit from a separator.

<ButtonGroup>  <Button variant="secondary" size="sm">Copy</Button>  <ButtonGroupSeparator />  <Button variant="secondary" size="sm">Paste</Button></ButtonGroup>

Split

Primary action plus a trailing icon action, separated by ButtonGroupSeparator.

<ButtonGroup>  <Button variant="secondary">Button</Button>  <ButtonGroupSeparator />  <IconButton variant="secondary" aria-label="Add">    <Plus />  </IconButton></ButtonGroup>

Split Follow with a menu trigger—adapted from shadcn.

<ButtonGroup>  <Button variant="outline">Follow</Button>  <DropdownMenu>    <DropdownMenuTrigger asChild>      <IconButton variant="outline" aria-label="More options">        <CaretDown />      </IconButton>    </DropdownMenuTrigger>    <DropdownMenuContent align="end" className="w-44">{/* items */}</DropdownMenuContent>  </DropdownMenu></ButtonGroup>

Props

ButtonGroup

PropTypeDefaultDescription
orientation"horizontal" | "vertical""horizontal"Layout of child controls.
classNamestringMerged with buttonGroupVariants.

Also accepts standard div attributes (role defaults to group via implementation).

ButtonGroupSeparator

PropTypeDefaultDescription
orientation"horizontal" | "vertical""vertical"Passed to underlying Separator.

ButtonGroupText

PropTypeDefaultDescription
asChildbooleanfalseMerge props onto child via Slot.

On this page