Propel

Button Group

A connected group of related buttons that share one size.

Show code
import { ButtonGroup, ButtonGroupButton } from "@makeplane/propel/components/button-group";
import { Icon } from "@makeplane/propel/components/icon";
import { ClipboardOutline, CopyOutline, UndoOutline } from "@makeplane/propel/icons";

export default function BasicDemo() {
  return (
    <ButtonGroup size="sm" aria-label="Editing actions">
      <ButtonGroupButton label="Undo" icon={<Icon icon={UndoOutline} />} />
      <ButtonGroupButton label="Copy" icon={<Icon icon={CopyOutline} />} />
      <ButtonGroupButton label="Paste" icon={<Icon icon={ClipboardOutline} />} />
    </ButtonGroup>
  );
}

Installation

import { ButtonGroup, ButtonGroupButton } from "@makeplane/propel/components/button-group";

Usage

ButtonGroup is a group-role container that shares its size with every ButtonGroupButton inside via context. Name the group for assistive tech with aria-label.

import { ButtonGroup, ButtonGroupButton } from "@makeplane/propel/components/button-group";
import { Icon } from "@makeplane/propel/components/icon";
import { ClipboardOutline, CopyOutline, UndoOutline } from "@makeplane/propel/icons";

export default function BasicDemo() {
  return (
    <ButtonGroup size="sm" aria-label="Editing actions">
      <ButtonGroupButton label="Undo" icon={<Icon icon={UndoOutline} />} />
      <ButtonGroupButton label="Copy" icon={<Icon icon={CopyOutline} />} />
      <ButtonGroupButton label="Paste" icon={<Icon icon={ClipboardOutline} />} />
    </ButtonGroup>
  );
}

Examples

Sizes

The group’s size sizes every segment — a segment’s own size still wins. There is no lg grouped button.

Show code
import { ButtonGroup, ButtonGroupButton } from "@makeplane/propel/components/button-group";
import { Icon } from "@makeplane/propel/components/icon";
import { ClipboardOutline, CopyOutline, UndoOutline } from "@makeplane/propel/icons";

export default function SizesDemo() {
  return (
    <div className="flex flex-col items-start gap-6">
      {(["sm", "md"] as const).map((size) => (
        <ButtonGroup key={size} size={size} aria-label={`Editing actions (${size})`}>
          <ButtonGroupButton label="Undo" icon={<Icon icon={UndoOutline} />} />
          <ButtonGroupButton label="Copy" icon={<Icon icon={CopyOutline} />} />
          <ButtonGroupButton label="Paste" icon={<Icon icon={ClipboardOutline} />} />
        </ButtonGroup>
      ))}
    </div>
  );
}

Disabled

A disabled segment is hard-disabled (not focusable) while its siblings stay interactive.

Show code
import { ButtonGroup, ButtonGroupButton } from "@makeplane/propel/components/button-group";
import { Icon } from "@makeplane/propel/components/icon";
import { ClipboardOutline, CopyOutline, UndoOutline } from "@makeplane/propel/icons";

export default function DisabledDemo() {
  return (
    <ButtonGroup size="sm" aria-label="Editing actions">
      <ButtonGroupButton label="Undo" icon={<Icon icon={UndoOutline} />} />
      <ButtonGroupButton label="Copy" icon={<Icon icon={CopyOutline} />} />
      <ButtonGroupButton label="Paste" icon={<Icon icon={ClipboardOutline} />} disabled />
    </ButtonGroup>
  );
}

API Reference

ButtonGroup

The ready-made connected button group: a group-role container that shares size with every ButtonGroupButton inside via context (an item's own size still wins). There is no Base UI button-group primitive — the items are independent Base UI Buttons; the group contributes only the shared chrome and the group role. Name the group for assistive tech via aria-label.

PropTypeDefaultDescription
size(required)"sm" | "md"—Size applied to every ButtonGroupButton in the group (each can still override it).
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>—Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.

ButtonGroupButton

The ready-made group segment: grafts Base UI's Button behavior onto the styled ButtonGroupButton (behavior outer, the styled button as the render target), lays out an optional icon beside the label (iconPosition), and takes its size from the surrounding ButtonGroup via context.

PropTypeDefaultDescription
label(required)string—Visible button label.
type"button" | "submit" | "reset"buttonThe button's form behavior.
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>—Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
nativeButtonboolean—Set false when render swaps the underlying tag away from <button> (e.g. an <a>): Base UI then adds role="button", tab focus, and Enter/Space activation.
size"sm" | "md""sm"Size override. Inside a ButtonGroup the group's size is used (so you can omit it); standalone it defaults to sm.
iconReactNode—Icon rendered beside the label (inline-start by default), e.g. <Icon icon={Plus} />.
iconPosition"start" | "end"startWhich side of the label the icon sits on.