RadCN
Inputsreadycomponentready

Button Group

A grouped control primitive for joined buttons, split actions, nested toolbars, and form-control compositions.

Importimport { ButtonGroup, ButtonGroupSeparator, ButtonGroupText } from 'radcn/button-group'
Preview

Live package example

Compose nested groups, split buttons, inputs, selects, dropdowns, popovers, separators, and size variants with package primitives.

Example Parity

Compose nested groups, split buttons, inputs, selects, dropdowns, popovers, separators, and size variants with package primitives.

Preview
import { Button } from 'radcn/button'
import { ButtonGroup, ButtonGroupSeparator } from 'radcn/button-group'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from 'radcn/dropdown-menu'
import { Input } from 'radcn/input'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from 'radcn/select'

export function ButtonGroupPreview() {
  return (
    <div class="button-group-preview">
      <ButtonGroup ariaLabel="Message actions" class="radcn-button-group--clustered">
        <ButtonGroup>
          <Button ariaLabel="Go back" size="icon" variant="outline">←</Button>
        </ButtonGroup>
        <ButtonGroup>
          <Button variant="outline">Archive</Button>
          <Button variant="outline">Report</Button>
        </ButtonGroup>
        <ButtonGroup>
          <Button variant="outline">Snooze</Button>
          <DropdownMenu>
            <DropdownMenuTrigger ariaLabel="More options">•••</DropdownMenuTrigger>
            <DropdownMenuContent>
              <DropdownMenuItem>Mark as Read</DropdownMenuItem>
              <DropdownMenuItem>Archive</DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </ButtonGroup>
      </ButtonGroup>

      <ButtonGroup>
        <Input name="search" placeholder="Search..." />
        <Button ariaLabel="Search" variant="outline">⌕</Button>
      </ButtonGroup>

      <ButtonGroup>
        <Select defaultValue="usd" name="currency">
          <SelectTrigger ariaLabel="Currency"><SelectValue>USD</SelectValue></SelectTrigger>
          <SelectContent><SelectItem value="usd">USD</SelectItem></SelectContent>
        </Select>
        <Input name="amount" value="10.00" />
        <Button ariaLabel="Send" size="icon" variant="outline">→</Button>
      </ButtonGroup>

      <ButtonGroup>
        <Button variant="secondary">Button</Button>
        <ButtonGroupSeparator />
        <Button ariaLabel="Add" size="icon" variant="secondary">+</Button>
      </ButtonGroup>
    </div>
  )
}

Installation

Intended future install command. RadCN is private and not published to npm yet, so this snippet documents the target user-facing API rather than something external consumers can run today.

pnpm add radcn # intended future package
import { ButtonGroup, ButtonGroupSeparator, ButtonGroupText } from 'radcn/button-group'

Theming

RadCN tokens read the resolved theme from the document. Store the user's preference separately, then resolve system preferences to a concrete light or dark theme before setting package tokens.

<html data-radcn-theme-mode="system" data-radcn-theme="dark">
  ...
</html>

Accessibility

  • ButtonGroup renders role="group" and supports ariaLabel or ariaLabelledby for grouped icon controls.
  • Icon-only actions use Button ariaLabel while visual glyphs remain presentation.
  • DropdownMenu, Popover, Select, Tooltip, Input, and InputGroup keep their own accessible roles and labels when composed inside ButtonGroup.

Customization

  • ButtonGroup exposes data-radcn-button-group and data-orientation hooks for horizontal and vertical layouts.
  • Nested ButtonGroups keep visible spacing between child groups while inner controls stay joined.
  • ButtonGroupSeparator and ButtonGroupText remain token-driven parts for split actions and inline metadata.
  • Input, InputGroup, Select, DropdownMenu trigger, and Popover trigger composition can be styled through the existing public RadCN hooks.

Remix 3 Notes

  • shadcn/ui examples use React asChild for overlay triggers. RadCN maps that to explicit DropdownMenuTrigger and PopoverTrigger components.
  • React useState examples map to server-provided defaults, native submitted values, route state, or app-owned dependency-free enhancement.
  • ButtonGroup is a layout primitive; it composes controls but does not own select, menu, popover, tooltip, or input state.