# Button.Split

A split button that groups a primary action with a dropdown trigger for secondary actions. Supports two modes: **custom** (arbitrary button children) and **strict** (declarative action list with built-in menu).

## When to Use

- Present a default action alongside alternative actions in a compact control
- Allow users to switch between related operations (e.g., deploy targets, save modes)
- Group two or more buttons visually as a single connected unit

## Component

---

## Properties

- **`actions`** `ButtonSplitAction[]` — Array of actions for strict mode. Each action requires `key` and `label`
- **`actionKey`** `string` — Currently selected action key (controlled)
- **`defaultActionKey`** `string` — Initially selected action key (uncontrolled)
- **`onAction`** `(key: string) => void` — Called when the action button is pressed
- **`onActionChange`** `(key: string) => void` — Called when the selected action changes via the menu
- **`type`** `'primary' | 'secondary' | 'outline' | 'neutral' | 'clear'` (default: `'outline'`) — Button type (inherited by children via context)
- **`theme`** `'default' | 'danger' | 'success' | 'warning' | 'note' | 'special'` (default: `'default'`) — Button theme (inherited by children via context)
- **`size`** `'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'` (default: `'medium'`) — Button size (inherited by children via context)
- **`isDisabled`** `boolean` (default: `false`) — Disables all buttons (inherited via context)
- **`actionProps`** `Partial<CubeButtonProps>` — Additional props for the action button in strict mode
- **`triggerProps`** `Partial<CubeButtonProps>` — Additional props for the trigger button in strict mode
- **`menuProps`** `Partial<CubeMenuProps>` — Additional props for the dropdown menu in strict mode

### Base Properties

Supports [Base properties](../../BaseProperties.md)

### Styling Properties

#### styles

Customises the root wrapper element of the split button.

### Style Properties

These properties allow direct style application without using the `styles` prop:

- **Base:** `display`, `font`, `preset`, `hide`, `whiteSpace`, `opacity`, `transition`
- **Position:** `gridArea`, `order`, `gridColumn`, `gridRow`, `placeSelf`, `alignSelf`, `justifySelf`, `zIndex`, `margin`, `inset`, `position`
- **Dimension:** `width`, `height`, `flexBasis`, `flexGrow`, `flexShrink`, `flex`
- **Block:** `border`, `radius`, `shadow`, `outline`, `padding`, `paddingInline`, `paddingBlock`, `overflow`, `scrollbar`, `textAlign`
- **Color:** `color`, `fill`, `fade`, `image`
- **Flow:** `flow`, `placeItems`, `placeContent`, `alignItems`, `alignContent`, `justifyItems`, `justifyContent`, `align`, `justify`, `gap`, `columnGap`, `rowGap`, `gridColumns`, `gridRows`, `gridTemplate`, `gridAreas`

### Context Inheritance

`type`, `theme`, `size`, and `isDisabled` set on `Button.Split` are inherited by all child `Button` components via context. Explicitly passed props on individual buttons always take precedence.

## Modes

### Strict Mode

Pass an `actions` array to automatically render an action button and a trigger button with a dropdown menu. The trigger displays a `DirectionIcon` pointing down.

Each action object requires `key` and `label`, and inherits all other props from `Menu.Item` (`icon`, `rightIcon`, `description`, `descriptionPlacement`, `prefix`, `suffix`, `hotkeys`, `textValue`, `isDisabled`, `qa`, `styles`, etc.).

```jsx
import { Button } from '@cube-dev/ui-kit';

const actions = [
  { key: 'deploy', label: 'Deploy', icon: <IconSend />, hotkeys: 'Mod+D' },
  { key: 'deploy-staging', label: 'Deploy to Staging', icon: <IconSend />, description: 'Preview environment' },
  { key: 'deploy-preview', label: 'Deploy Preview', icon: <IconPlayerPlay /> },
];

<Button.Split
  actions={actions}
  defaultActionKey="deploy"
  type="primary"
  onAction={(key) => console.log('Executed:', key)}
  onActionChange={(key) => console.log('Switched to:', key)}
/>
```

#### Controlled

Use `actionKey` and `onActionChange` for controlled state.

```jsx
const [currentKey, setCurrentKey] = useState('deploy');

<Button.Split
  actions={actions}
  actionKey={currentKey}
  type="primary"
  onAction={(key) => console.log('Executed:', key)}
  onActionChange={setCurrentKey}
/>
```

### Custom Mode

Pass `children` to render arbitrary buttons with split-group styling (joined radius, collapsed borders). Set `type` and `theme` on the wrapper -- child buttons inherit them via context.

```jsx
import { Button, Menu } from '@cube-dev/ui-kit';
import { DirectionIcon } from '@cube-dev/ui-kit';

<Button.Split type="primary">
  <Button onPress={() => console.log('Save')}>Save</Button>
  <Menu.Trigger placement="bottom end">
    <Button
      aria-label="More save options"
      icon={({ pressed }) => <DirectionIcon to={pressed ? 'up' : 'down'} />}
    />
    <Menu onAction={(key) => console.log(key)}>
      <Menu.Item key="save-draft">Save as Draft</Menu.Item>
      <Menu.Item key="save-publish">Save & Publish</Menu.Item>
    </Menu>
  </Menu.Trigger>
</Button.Split>
```

### Multiple Buttons

More than two buttons are supported. Middle buttons have no border radius.

```jsx
<Button.Split type="outline">
  <Button icon={<IconPlus />}>Add</Button>
  <Button icon={<IconCopy />}>Copy</Button>
  <Button icon={<IconDownload />}>Export</Button>
</Button.Split>
```

## Examples

### Variants

Different types and themes can be applied. All child buttons inherit the styling.

```jsx
<Button.Split actions={actions} defaultActionKey="copy" type="primary" />
<Button.Split actions={actions} defaultActionKey="copy" type="secondary" />
<Button.Split actions={actions} defaultActionKey="copy" type="outline" />
<Button.Split actions={actions} defaultActionKey="copy" type="primary" theme="danger" />
<Button.Split actions={actions} defaultActionKey="copy" type="primary" isDisabled />
```

### Customizing Sub-Components

Use `actionProps`, `triggerProps`, and `menuProps` to customise individual parts in strict mode.

```jsx
<Button.Split
  actions={actions}
  defaultActionKey="deploy"
  type="primary"
  actionProps={{ size: 'large' }}
  triggerProps={{ 'aria-label': 'Select deploy target' }}
  menuProps={{ placement: 'bottom start' }}
/>
```

## Accessibility

### Keyboard Navigation

- `Tab` -- Moves focus between the action button and the trigger button.
- `Space` / `Enter` -- Activates the focused button. On the trigger, opens the dropdown menu.
- `Arrow Down` -- When the menu is open, navigates menu items.
- `Escape` -- Closes the dropdown menu and returns focus to the trigger.

### Screen Reader Support

- The action button announces its label.
- The trigger button has `aria-label="More options"` by default (override via `triggerProps`).
- The dropdown menu announces selection changes.

### ARIA Properties

- `aria-label` -- Provide on the trigger for context (e.g., "Select deploy target").
- Menu items support `aria-disabled` via the `isDisabled` property on actions.

## Best Practices

1. **Do**: Use strict mode for standard action+trigger patterns.
   ```jsx
   <Button.Split actions={actions} defaultActionKey="deploy" type="primary" />
   ```

2. **Do**: Set `type` and `theme` on the wrapper instead of repeating on each child.
   ```jsx
   <Button.Split type="primary">
     <Button>Save</Button>
     <Button icon={<DirectionIcon to="down" />} aria-label="Options" />
   </Button.Split>
   ```

3. **Don't**: Mix `actions` prop with `children`. Use one mode or the other.

4. **Accessibility**: Always provide `aria-label` on icon-only trigger buttons.

## Suggested Improvements

- Support `isLoading` on the action button in strict mode.
- Add keyboard shortcut display in menu items via `hotkeys` prop.

## Related Components

- [Button](./Button.md) -- Standalone action button.
- [Menu](./Menu.md) -- Dropdown menu for action lists.
- Button.Group -- Layout wrapper for spacing multiple buttons.
