# Split Button

A main action button paired with a chevron that opens a menu of secondary actions.

## Installation

```tsx
import { SplitButton } from "@makeplane/propel/components/split-button";
```
## Usage

`SplitButton` ships no menu of its own — render it as a `Menu`'s child, with the surface as a
sibling `MenuContent`. Clicking the main segment fires `onClick`; the chevron opens the menu.

```tsx
import { Icon } from "@makeplane/propel/components/icon";
import { Menu, MenuContent, MenuItem } from "@makeplane/propel/components/menu";
import { SplitButton } from "@makeplane/propel/components/split-button";
import { AddOutline } from "@makeplane/propel/icons";

export default function BasicDemo() {
  return (
    <Menu>
      <SplitButton
        variant="primary"
        size="md"
        label="Create work item"
        icon={<Icon icon={AddOutline} />}
      />
      <MenuContent align="end">
        <MenuItem label="Create from template" />
        <MenuItem label="Import work items" />
      </MenuContent>
    </Menu>
  );
}
```
## Examples

### Variants

Primary lays the segments out as separate pills; secondary connects them with a divider. There is
no tertiary or ghost split button, and no danger palette — both segments are neutral.

```tsx
import { Icon } from "@makeplane/propel/components/icon";
import { Menu, MenuContent, MenuItem } from "@makeplane/propel/components/menu";
import { SplitButton } from "@makeplane/propel/components/split-button";
import { AddOutline } from "@makeplane/propel/icons";

export default function VariantsDemo() {
  return (
    <div className="flex flex-wrap items-center gap-6">
      {(["primary", "secondary"] as const).map((variant) => (
        <Menu key={variant}>
          <SplitButton
            variant={variant}
            size="md"
            label="Button"
            icon={<Icon icon={AddOutline} />}
            menuLabel={`More options (${variant})`}
          />
          <MenuContent align="end">
            <MenuItem label="Secondary action" />
          </MenuContent>
        </Menu>
      ))}
    </div>
  );
}
```

### Sizes

One shared `size` sizes both segments — sm 24 / md 28 / lg 32 px. There is no `xs`: the
segments are contiguous, so the 20px rung's synthesized pointer target would overlap its
neighbour. See [Sizing](/foundations/sizing) for the full ladder.

```tsx
import { Icon } from "@makeplane/propel/components/icon";
import { Menu, MenuContent, MenuItem } from "@makeplane/propel/components/menu";
import { SplitButton } from "@makeplane/propel/components/split-button";
import { AddOutline } from "@makeplane/propel/icons";

export default function SizesDemo() {
  return (
    <div className="flex flex-col items-start gap-6">
      {(["sm", "md", "lg"] as const).map((size) => (
        <Menu key={size}>
          <SplitButton
            variant="primary"
            size={size}
            label="Button"
            icon={<Icon icon={AddOutline} />}
            menuLabel={`More options (${size})`}
          />
          <MenuContent align="end">
            <MenuItem label="Secondary action" />
          </MenuContent>
        </Menu>
      ))}
    </div>
  );
}
```

### Loading

`loading` shows a spinner on the main segment (soft-disabled: still focusable, `aria-busy`) and
disables the menu segment so the pending action can't fork.

```tsx
import { Icon } from "@makeplane/propel/components/icon";
import { Menu, MenuContent, MenuItem } from "@makeplane/propel/components/menu";
import { SplitButton } from "@makeplane/propel/components/split-button";
import { AddOutline } from "@makeplane/propel/icons";

export default function LoadingDemo() {
  return (
    <Menu>
      <SplitButton
        variant="primary"
        size="md"
        label="Create work item"
        icon={<Icon icon={AddOutline} />}
        loading
      />
      <MenuContent align="end">
        <MenuItem label="Create from template" />
      </MenuContent>
    </Menu>
  );
}
```

### Disabled

`disabled` disables both segments.

```tsx
import { Icon } from "@makeplane/propel/components/icon";
import { Menu, MenuContent, MenuItem } from "@makeplane/propel/components/menu";
import { SplitButton } from "@makeplane/propel/components/split-button";
import { AddOutline } from "@makeplane/propel/icons";

export default function DisabledDemo() {
  return (
    <Menu>
      <SplitButton
        variant="primary"
        size="md"
        label="Create work item"
        icon={<Icon icon={AddOutline} />}
        disabled
      />
      <MenuContent align="end">
        <MenuItem label="Create from template" />
      </MenuContent>
    </Menu>
  );
}
```
## API Reference

### SplitButton

The ready-made split button: a main action `Button` plus a chevron `IconButton` grafted as the
surrounding menu's `MenuTrigger`, laid out by the styled `SplitButton` frame (separate pills when
primary, connected outline when secondary). Neutral only — there is no danger/error split button.
It ships no menu of its own — render it as a `Menu`'s child, with the surface as a sibling
`MenuContent`:

```tsx
<Menu>
  <SplitButton variant="primary" size="md" label="Save" onClick={save} />
  <MenuContent>
    <MenuItem label="Save as draft" />
  </MenuContent>
</Menu>;
```

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `variant` (required) | `"primary" \| "secondary"` | — |  |
| `size` (required) | `"sm" \| "md" \| "lg"` | — |  |
| `label` (required) | `string` | — | Visible label of the main action segment. |
| `onClick` | `MouseEventHandler<HTMLDivElement> \| MouseEventHandler<HTMLButtonElement>` | — | Click handler of the main action segment. |
| `render` | `ReactElement<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. |
| `icon` | `ReactNode` | — | Icon rendered beside the main label (inline-start by default), e.g. `<Icon icon={Plus} />`. |
| `iconPosition` | `"start" \| "end"` | `"start"` | Which side of the main label the icon sits on. The `loading` spinner takes the same slot. |
| `loading` | `boolean` | `false` | Shows a spinner on the main segment and makes both segments non-interactive (the main segment stays focusable, Button's soft-disabled loading state). |
| `disabled` | `boolean` | — | Disables both segments. |
| `type` | `"button" \| "submit" \| "reset"` | `button` | The main segment's form behavior. |
| `menuLabel` | `string` | `More options` | Accessible name of the menu-opening segment (it is icon-only, so it must be labeled). |
