Capítulo 21 de 108

Button Group

Core Idea

ButtonGroup visually clusters related action buttons (and other controls like Input/InputGroup/Select/DropdownMenu) with consistent connected styling. Use it for buttons that perform actions; use ToggleGroup instead when the buttons toggle state.

Key Concepts

  • orientation: "horizontal" | "vertical" (default horizontal) on ButtonGroup.
  • Composition: ButtonGroup can hold Button, Input, InputGroup, Select, DropdownMenu, Popover triggers, ButtonGroupSeparator, ButtonGroupText.
  • Nesting for spacing: nest <ButtonGroup> inside <ButtonGroup> to get visual gaps between sub-clusters while each sub-cluster stays visually connected.
  • ButtonGroupSeparator: visual divider between buttons within a group; own orientation prop defaults to "vertical" (opposite the group's default).
  • ButtonGroupText: non-button text/label slot inside the group; accepts a render prop to render as e.g. a Label.
  • Accessibility: root has role="group"; use aria-label/aria-labelledby to label the group; Tab navigates between buttons.

Code Examples

<ButtonGroup aria-label="Button group">
  <Button>Button 1</Button>
  <Button>Button 2</Button>
</ButtonGroup>
<ButtonGroup orientation="vertical" aria-label="Media controls" className="h-fit">
  <Button variant="outline" size="icon"><PlusIcon /></Button>
  <Button variant="outline" size="icon"><MinusIcon /></Button>
</ButtonGroup>
  • O que demonstra: uso básico e a variante vertical (ex. controles de zoom/volume).
<ButtonGroup>
  <ButtonGroup>
    <Button variant="outline" size="icon"><PlusIcon /></Button>
  </ButtonGroup>
  <ButtonGroup>
    <InputGroup>
      <InputGroupInput placeholder="Send a message..." />
      <InputGroupAddon align="inline-end"><AudioLinesIcon /></InputGroupAddon>
    </InputGroup>
  </ButtonGroup>
</ButtonGroup>
  • O que demonstra: nesting para separar visualmente um botão isolado de um InputGroup, dentro do mesmo grupo lógico.
<ButtonGroup>
  <Button>Button 1</Button>
  <ButtonGroupSeparator />
  <Button>Button 2</Button>
</ButtonGroup>
<ButtonGroup>
  <ButtonGroupText render={<Label htmlFor="name" />}>Text</ButtonGroupText>
  <Input placeholder="Type something here..." id="name" />
</ButtonGroup>
  • O que demonstra: separador visual e slot de texto/label combinado com Input.

Reference Tables

ComponentPropTypeDefault
ButtonGrouporientation"horizontal" | "vertical""horizontal"
ButtonGroupSeparatororientation"horizontal" | "vertical""vertical"
ButtonGroupTextrenderReact.ReactElement

Anti-patterns

  • Using ButtonGroup for state-toggling controls (like filter chips): use ToggleGroup instead, semantically distinct from action buttons.
  • Forgetting aria-label on an icon-only button-group: the group and its buttons need accessible names.

Key Takeaways

  1. ButtonGroup accepts more than Button: Input, InputGroup, Select, DropdownMenu triggers, and Popover triggers all compose inside it (see the Dropdown Menu/Select/Popover sections of the full docs for those patterns).
  2. Individual Button size props control the group's visual size, there's no group-level size prop, size each button consistently by hand.
  3. Nesting groups is the documented way to introduce spacing between sub-clusters without breaking the "connected" visual style within each sub-cluster.
  4. RTL support follows the same convention as other components; see the RTL configuration guide.

Connects To

  • components-button: the primary child component.
  • components-input-group: composes inside ButtonGroup for combined input+action patterns.