# Icon Split Button

A split button whose main action is icon-only, for toolbars and other dense chrome.

## Installation

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

`IconSplitButton` is [`SplitButton`](/components/split-button) with an icon-only main segment. It
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.

Both segments are icon-only, so both need an accessible name: `aria-label` names the main action
and `menuLabel` names the chevron.

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

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

### Choosing between the two

Reach for `IconSplitButton` only where a glyph alone names the action unambiguously — a toolbar
`+`, say. An icon-only main segment gives no way to tell what a plain click will do without
hovering for the tooltip, so anywhere that matters, keep the text label and use `SplitButton`.

If every path through the control goes through the menu — the glyph only names a category and
there is no default action worth firing on its own — this is the wrong component. That is a plain
menu trigger, not a split button, and it should not carry a divider.

## 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 { IconSplitButton } from "@makeplane/propel/components/icon-split-button";
import { Menu, MenuContent, MenuItem } from "@makeplane/propel/components/menu";
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}>
          <IconSplitButton
            variant={variant}
            size="md"
            icon={<Icon icon={AddOutline} />}
            aria-label={`Create work item (${variant})`}
            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. Both segments are the same square
box, so the control measures exactly twice its rung height, plus the frame's 1px gap on `primary`.
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 { IconSplitButton } from "@makeplane/propel/components/icon-split-button";
import { Menu, MenuContent, MenuItem } from "@makeplane/propel/components/menu";
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}>
          <IconSplitButton
            variant="primary"
            size={size}
            icon={<Icon icon={AddOutline} />}
            aria-label={`Create work item (${size})`}
            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 { IconSplitButton } from "@makeplane/propel/components/icon-split-button";
import { Menu, MenuContent, MenuItem } from "@makeplane/propel/components/menu";
import { AddOutline } from "@makeplane/propel/icons";

export default function LoadingDemo() {
  return (
    <Menu>
      <IconSplitButton
        variant="primary"
        size="md"
        icon={<Icon icon={AddOutline} />}
        aria-label="Create work item"
        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 { IconSplitButton } from "@makeplane/propel/components/icon-split-button";
import { Menu, MenuContent, MenuItem } from "@makeplane/propel/components/menu";
import { AddOutline } from "@makeplane/propel/icons";

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

### IconSplitButton

The icon-only split button (Figma "Icon Split button", 9441:1252): two square `IconButton`s in
the shared `SplitButton` frame — a main action segment plus a chevron segment grafted as the
surrounding menu's `MenuTrigger`. Both segments are the same square box at every rung (Figma
measures 24+24, 28+28, 32+32; primary adds the frame's 1px gap, secondary runs them flush), so
neither takes a width override. Neutral only, like `SplitButton` — no danger/error variant.

Use it over `SplitButton` only where a glyph alone names the action unambiguously (a toolbar `+`,
say). An icon-only main segment gives no way to tell what a plain click will do without hovering;
anywhere that matters, keep the text label and use `SplitButton`.

It ships no menu of its own — render it as a `Menu`'s child, with the surface as a sibling
`MenuContent`:

```tsx
<Menu>
  <IconSplitButton
    variant="primary"
    size="md"
    icon={<Icon icon={Plus} />}
    aria-label="Create"
  />
  <MenuContent align="end">
    <MenuItem label="Create from template" />
  </MenuContent>
</Menu>;
```

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `variant` (required) | `"primary" \| "secondary"` | — |  |
| `size` (required) | `"sm" \| "md" \| "lg"` | — |  |
| `icon` (required) | `ReactNode` | — | The main segment's icon element, usually `<Icon icon={...} />`. |
| `aria-label` | `string` | — | Defines a string value that labels the current element. Required: the main segment is icon-only, so it has no visible text to name it. @see aria-labelledby. |
| `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. |
| `loading` | `boolean` | `false` | Shows a spinner on the main segment and makes both segments non-interactive (the main segment stays focusable, IconButton'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. |
