suiss/ui · Component
Button Group
A container that joins related buttons, inputs and menus into a single connected control.
Button Group is an open-source component from suiss/ui for React, React Native, SwiftUI and Jetpack Compose. The @esuiss/ui CLI copies its source into your project, so you own the code.
A ButtonGroup lays out its children in a row or column and joins them visually: only the outer corners stay rounded, and borders between neighbors collapse. Use ButtonGroupSeparator to draw a divider between filled buttons, and ButtonGroupText to add a static label or prefix such as https://.
Groups can contain buttons, Input, InputGroup, Select triggers, and the triggers of dropdown menus and popovers. Nest ButtonGroup parts to create clusters with a gap between them. Use a button group for closely related actions, split buttons, or input-and-button combinations; for a set of toggleable options, use Toggle Group instead.
Installation
CLI
Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:
Manual
- Install the dependencies and add the
cnhelper:
-
Add the pieces it builds on: Separator.
-
Copy the source into
components/ui/button-group.tsx:
- Update the import paths to match your project.
Usage
Elements are joined only when they expose a data-slot attribute, as the library's components do.
When a group contains other ButtonGroup parts, the outer group adds a gap between them instead of joining them.
ButtonGroupSeparator is vertical by default. In a vertical group, pass orientation="horizontal". Separators are most useful between secondary or default buttons; outline buttons already show their borders.
Give the group an aria-label when its purpose is not clear from its contents, as in the pagination and media control examples.
Examples
Outline
The same toolbar built with outline buttons and no separators.
Orientation
Stacks zoom buttons vertically with orientation="vertical".
Sizes
Groups of sm, default and lg buttons.
Nested
Nests groups to separate page numbers from previous and next buttons.
With separator
Divides two secondary buttons with ButtonGroupSeparator.
Plain
Groups plain buttons with leading and trailing icons.
Split button
Pairs a primary action with an icon button for more options.
With input
Attaches a search button to an Input.
With input group
Combines an add button with an InputGroup that has an inline voice button.
With text
Prefixes an input with a ButtonGroupText label and ends with a save button.
With dropdown menu
Opens a dropdown menu from the second half of a split button.
With select
Joins a currency Select to an amount input.
With popover
Opens a popover from the second half of a split button.
Pagination
A labelled group of page buttons that marks the current page with aria-current.
API Reference
ButtonGroup
The container that joins its children and sets the orientation.
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" | Direction of the group. horizontal joins items in a row with pill ends; vertical stacks them with rounded top and bottom. |
Also accepts the props of React.ComponentProps<"div">.
ButtonGroupText
A static, button-shaped label for text or icons.
Also accepts the props of useRender.ComponentProps<"div">.
ButtonGroupSeparator
A thin divider between adjacent items.
Also accepts the props of React.ComponentProps<typeof Separator>.
Accessibility
ButtonGrouprenders withrole="group"; add anaria-labelto name it.- Each button, input and trigger remains a separate tab stop in document order.
- Icon-only buttons inside a group need an
aria-label. ButtonGroupTextrenders adivand is not focusable; userenderto render alabelelement if it labels an input.
Notes
- Styling hooks:
data-slot="button-group","button-group-text"and"button-group-separator", plusdata-orientationon the group. - Focused items are raised with
z-10so their focus ring is not clipped by neighbors. - In groups containing
outlinebuttons, inputs, input groups and select triggers also get theborder-bordercolor.

ButtonGroup is a View with the group role that joins its children: only the outer ends keep their rounded corners and the shared borders collapse. It works with Button and with other controls such as inputs, selects and menu triggers. ghost and plain buttons are left unjoined.
Nest groups to keep separate clusters in one row with a gap between them. ButtonGroupSeparator draws a divider between joined buttons, and ButtonGroupText shows a label or icon in the same pill shape.
Installation
The CLI also adds what it builds on: Button, Icon, Separator, Text.
Manual
- Install the dependencies:
-
Add the pieces it builds on: Button, Icon, Separator, Text, and the primitives
components/primitives/types.tsx,components/primitives/use-render.tsx. -
Copy the source into
components/ui/button-group.tsx:
- Update the import paths to match your project.
- Install the dependencies:
-
Add the pieces it builds on: Button, Icon, Separator, Text, and the primitives
components/primitives/types.tsx,components/primitives/use-render.tsx. -
Copy the source into
components/ui/button-group.tsx:
- Update the import paths to match your project.
-
Target iOS 17 or later.
-
Copy the theme files every view uses:
- Copy the source and every file it uses:
- Add the files to your app target.
- Set
minSdkto 24 or higher and add the dependencies:
- Copy the theme files every view uses:
- Copy the source and every file it uses:
- Update the
com.esuiss.uipackage names to match your project.
Usage
Set orientation="vertical" to stack the buttons. Use a separator between buttons of the same filled variant, such as in a split button, where there is no border to divide them.
Give icon-only buttons an accessibilityLabel, and give the group one when its purpose is not clear from its contents.
Examples
Outline
Nested groups of outline buttons.

Orientation
A vertical group of zoom buttons with a horizontal separator.

Sizes
Groups at different button sizes.

Nested
Groups inside a group, spaced apart.

With separator
Buttons divided by ButtonGroupSeparator.

Plain
plain buttons, which stay unjoined.

Split button
A main action with a joined icon button for more options.

With input
An input joined to a search button.

With input group
An input group joined with buttons.

With text
A ButtonGroupText URL prefix joined to an input and a save button.

With dropdown menu
A button joined to a dropdown menu trigger.

With select
A select joined to an input for a currency amount.

With popover
A button joined to a popover trigger.

Pagination
Page buttons with previous and next arrows.

API Reference
ButtonGroup
Container that joins its children.
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" | horizontal or vertical. Defaults to horizontal. |
Also accepts the props of ViewProps.
ButtonGroupText
Pill-shaped label or icon slot.
| Prop | Type | Default | Description |
|---|---|---|---|
render | RenderProp<Record<string, unknown>, Record<string, never>> | - | Element to render instead of the default View. |
Also accepts the props of ViewProps.
ButtonGroupSeparator
Divider between joined buttons.
Also accepts the props of React.ComponentProps<typeof Separator>.
Accessibility
- The container has the
grouprole. - Each button keeps its own role and state.
- Icon-only buttons need an
accessibilityLabel.
Notes
- Uses
bg-secondaryforButtonGroupTextandbg-foreground/20for separators; light and dark follow the system appearance.














