# Button Group

> Attached buttons that act as one control: undo/redo, zoom, or a split button whose arrow opens a menu.

Component · Foundations · Pro kit · [Live page](https://ui.twentyfirst.media/pro/components/ButtonGroup/)

Attached buttons that act as one control: undo/redo, zoom, or a split button whose arrow opens a menu.

- Children are regular `Button`, `IconButton` or a `Popover` trigger; the group only joins their corners.
- `label` names the group for assistive tech; `orientation="vertical"` stacks them.

## Example

```tsx
import { Button, ButtonGroup, IconButton, Menu, Popover } from "@twentyfirstmedia/pro";

export default function Preview() {
  return (
    <div className="tf-panel" style={{ gap: 20, paddingBottom: 200 }}>
      <div className="tf-row" style={{ gap: 16 }}>
        <ButtonGroup label="History">
          <Button variant="secondary" icon="undo">
            Undo
          </Button>
          <Button variant="secondary" icon="redo">
            Redo
          </Button>
        </ButtonGroup>
        <ButtonGroup label="Zoom">
          <IconButton icon="minus" label="Zoom out" variant="outline" />
          <Button variant="secondary">100%</Button>
          <IconButton icon="plus" label="Zoom in" variant="outline" />
        </ButtonGroup>
      </div>
      <ButtonGroup label="Publish">
        <Button icon="send">Publish</Button>
        <Popover
          open
          flush
          align="end"
          trigger={<IconButton icon="chevronDown" label="More publish options" variant="solid" />}
        >
          <Menu
            items={[
              { label: "Schedule…", icon: "calendar" },
              { label: "Publish to staging", icon: "upload" },
              "-",
              { label: "Save as draft", icon: "file" },
            ]}
          />
        </Popover>
      </ButtonGroup>
    </div>
  );
}
```

## Props

### ButtonGroup

| Prop | Type | Notes |
| --- | --- | --- |
| `label?` | `string` | Accessible name of the group. |
| `orientation?` | `"horizontal" \| "vertical"` |  |
| `children?` | `ReactNode` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Button

| Prop | Type | Notes |
| --- | --- | --- |
| `variant?` | `"primary" \| "secondary" \| "soft" \| "ghost" \| "danger" \| "danger-solid"` |  |
| `size?` | `"md" \| "sm"` |  |
| `icon?` | `IconName` |  |
| `iconRight?` | `IconName` |  |
| `disabled?` | `boolean` |  |
| `type?` | `"button" \| "submit" \| "reset"` |  |
| `onClick?` | `(e: MouseEvent<HTMLButtonElement>) => void` |  |
| `children?` | `ReactNode` |  |
| `asChild?` | `boolean` | Render the single child element (a link, a router Link) with the button's look instead of a <button>. |
| `id?` | `string` |  |
| `name?` | `string` | Form field name and value, sent with the form when this button submits it. |
| `value?` | `string` |  |
| `form?` | `string` | The id of the form this button belongs to, when it sits outside it. |
| `title?` | `string` |  |
| `tabIndex?` | `number` |  |
| `autoFocus?` | `boolean` |  |
| `aria-label?` | `string` |  |
| `aria-labelledby?` | `string` |  |
| `aria-describedby?` | `string` |  |
| `aria-expanded?` | `boolean \| "true" \| "false"` | For disclosure and menu triggers: whether what the button controls is open. |
| `aria-controls?` | `string` |  |
| `aria-haspopup?` | `boolean \| "true" \| "false" \| "menu" \| "listbox" \| "tree" \| "grid" \| "dialog"` |  |
| `aria-pressed?` | `boolean \| "true" \| "false" \| "mixed"` | For toggle buttons. |
| `aria-current?` | `boolean \| "true" \| "false" \| "page" \| "step" \| "location" \| "date" \| "time"` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### IconButton

| Prop | Type | Notes |
| --- | --- | --- |
| `icon` | `IconName` | Required |
| `label` | `string` | Accessible name and tooltip (`aria-label` and `title`); `aria-label` or `title` override them. |
| `variant?` | `"soft" \| "solid" \| "outline" \| "ghost"` |  |
| `size?` | `"sm" \| "md" \| "lg"` |  |
| `type?` | `"button" \| "submit" \| "reset"` |  |
| `onClick?` | `(e: MouseEvent<HTMLButtonElement>) => void` |  |
| `disabled?` | `boolean` |  |
| `asChild?` | `boolean` | Render the single child element (a link) with the button's look; the icon is placed inside it. |
| `children?` | `ReactNode` |  |
| `id?` | `string` |  |
| `name?` | `string` | Form field name and value, sent with the form when this button submits it. |
| `value?` | `string` |  |
| `form?` | `string` | The id of the form this button belongs to, when it sits outside it. |
| `title?` | `string` |  |
| `tabIndex?` | `number` |  |
| `autoFocus?` | `boolean` |  |
| `aria-label?` | `string` |  |
| `aria-labelledby?` | `string` |  |
| `aria-describedby?` | `string` |  |
| `aria-expanded?` | `boolean \| "true" \| "false"` | For disclosure and menu triggers: whether what the button controls is open. |
| `aria-controls?` | `string` |  |
| `aria-haspopup?` | `boolean \| "true" \| "false" \| "menu" \| "listbox" \| "tree" \| "grid" \| "dialog"` |  |
| `aria-pressed?` | `boolean \| "true" \| "false" \| "mixed"` | For toggle buttons. |
| `aria-current?` | `boolean \| "true" \| "false" \| "page" \| "step" \| "location" \| "date" \| "time"` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Popover

| Prop | Type | Notes |
| --- | --- | --- |
| `trigger` | `ReactNode \| ((s: { open: boolean; toggle: () => void }) => ReactNode)` | Required |
| `open?` | `boolean` |  |
| `onOpenChange?` | `(o: boolean) => void` |  |
| `align?` | `"start" \| "end"` |  |
| `side?` | `"top" \| "bottom"` |  |
| `width?` | `number` |  |
| `flush?` | `boolean` |  |
| `block?` | `boolean` |  |
| `role?` | `string` |  |
| `children?` | `ReactNode \| ((s: { close: () => void }) => ReactNode)` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Menu

| Prop | Type | Notes |
| --- | --- | --- |
| `items` | `(MenuItem \| "-")[]` | Required |
| `label?` | `string` | Accessible name of the menu. |
| `autoFocus?` | `boolean` | Focus the first item on mount (menus opened from a button or the keyboard). |
| `onClose?` | `() => void` | Called after an item runs, and on Escape, so the owner can close the menu. |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |
