Skip to main content

Split Button

A button group that pairs a one-click default action with a dropdown menu of related alternatives. Best for when users typically want one action but occasionally need variants.

import { CopyIcon, FileTextIcon } from "@phosphor-icons/react";import { Icon } from "@ngrok/mantle/icon";import { SplitButton } from "@ngrok/mantle/split-button"; <SplitButton.Root>	<SplitButton.PrimaryAction icon={<CopyIcon />}>Copy page</SplitButton.PrimaryAction>	<SplitButton.MenuTrigger label="Open actions menu" />	<SplitButton.MenuContent>		<SplitButton.MenuItem>			<Icon svg={<CopyIcon />} />			Copy page		</SplitButton.MenuItem>		<SplitButton.MenuItem>			<Icon svg={<FileTextIcon />} />			View as Markdown		</SplitButton.MenuItem>	</SplitButton.MenuContent></SplitButton.Root>;

Composition

Compose the parts of a SplitButton together to build your own:

SplitButton.Root├── SplitButton.PrimaryAction├── SplitButton.MenuTrigger└── SplitButton.MenuContent    └── SplitButton.MenuItem

Size

Set the size prop on SplitButton.Root to control the height of the whole composite, default md. The size applies to both the primary action and the menu trigger so the two halves always share one height; the parts themselves do not accept a size prop. The scale is shared with Button and IconButton.

import { PlusIcon } from "@phosphor-icons/react";import { SplitButton } from "@ngrok/mantle/split-button"; <SplitButton.Root size="sm">	<SplitButton.PrimaryAction icon={<PlusIcon />}>New endpoint</SplitButton.PrimaryAction>	<SplitButton.MenuTrigger label="Open create options" />	<SplitButton.MenuContent>		<SplitButton.MenuItem>New domain</SplitButton.MenuItem>	</SplitButton.MenuContent></SplitButton.Root>;

Polymorphism

When you want to render something else as a SplitButton.MenuItem, you can use the asChild prop to compose. This is useful for rendering links as menu items.

import { DownloadIcon, FileTextIcon } from "@phosphor-icons/react";import { Icon } from "@ngrok/mantle/icon";import { SplitButton } from "@ngrok/mantle/split-button"; <SplitButton.Root>	<SplitButton.PrimaryAction icon={<DownloadIcon />}>Download</SplitButton.PrimaryAction>	<SplitButton.MenuTrigger label="Open download options" />	<SplitButton.MenuContent>		<SplitButton.MenuItem>			<Icon svg={<DownloadIcon />} />			Download as PDF		</SplitButton.MenuItem>		<SplitButton.MenuItem asChild>			<a href="https://example.com" target="_blank" rel="noopener noreferrer">				<Icon svg={<FileTextIcon />} />				Open in new tab			</a>		</SplitButton.MenuItem>	</SplitButton.MenuContent></SplitButton.Root>;

API Reference

SplitButton.Root

A button group that pairs a one-click default action with a dropdown menu of related alternatives.

All props from div, plus:

PropTypeDefaultDescription
dir?"ltr" | "rtl"The reading direction of the dropdown menu.
open?booleanThe controlled open state of the dropdown menu.
defaultOpen?booleanThe open state of the dropdown menu when it is initially rendered.
onOpenChange?(open: boolean) => voidEvent handler called when the open state of the dropdown changes.
modal?booleanWhether the dropdown menu is modal.
size?"xs" | "sm" | "md" | "lg" | "xl""md"The size of the SplitButton. Applied to both the primary action and the menu trigger so the two halves always share one height.

Data attributes

Data AttributeValueDescription
data-slot"split-button"On the wrapping <div>.
data-size"xs" | "sm" | "md" | "lg" | "xl"The size prop, which both halves render at.

SplitButton.PrimaryAction

The most common action users can trigger with a single click. Renders as a Button with appearance="outlined" and intent="neutral".

All props from Button, except appearance, intent, and size (set size on SplitButton.Root instead).

PropTypeDefaultDescription
type?"button" | "submit" | "reset""button"The type attribute of the button.

SplitButton.MenuTrigger

The button that opens the split button dropdown menu. Renders as an IconButton with a caret-down icon that rotates when the menu is open.

All props from IconButton, except appearance, intent, size (set size on SplitButton.Root instead), asChild, and icon (which is redefined as optional below).

PropTypeDefaultDescription
icon?ReactNodeCaret-down iconCustom icon to render instead of the default caret-down.
type?"button" | "submit" | "reset""button"The type attribute of the button.

SplitButton.MenuContent

The container for the split button dropdown menu content. Appears in a portal with scrolling and animations. Wraps DropdownMenu.Content.

All props from DropdownMenu.Content.

PropTypeDefaultDescription
align?"start" | "center" | "end""end"The preferred alignment against the trigger.

SplitButton.MenuItem

A standard item in the split button dropdown menu that can be selected or activated. Wraps DropdownMenu.Item with gap-2 styling.

All props from DropdownMenu.Item.

PropTypeDefaultDescription
asChild?booleanfalseUse the asChild prop to compose onto alternative element types like anchors or custom components.