# Split button
> Split button with a primary action and a menu of alternatives; choosing an item rolls its label into the main button.
- Element: `<hf-split>`
- React: `import { HfSplit } from "@/components/lumesec/hf-split"`
- Collection: Pixel HD (https://elements.lumesec.ai/components/pixel-hd)
- Registry item: https://elements.lumesec.ai/r/hf-split.json
- Page: https://elements.lumesec.ai/components/pixel-hd/split



Live preview: https://elements.lumesec.ai/view/hf-split

```html
<hf-split items="Deploy to production|Ships to everyone;Deploy to staging|Internal testers only"></hf-split>
```

## Playground

Change a prop and the component updates. Props marked live animate to the new value; the others rebuild the element.

## Installation

```bash
npx shadcn@latest add @lumesec/hf-split
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/hf-split.json
```

## Usage

React:

```tsx
import { HfSplit } from "@/components/lumesec/hf-split";

export function Example() {
  return (
    <HfSplit items="Deploy to production|Ships to everyone;Deploy to staging|Internal testers only" />
  );
}
```

HTML:

```html
<script type="module" src="https://elements.lumesec.ai/cdn/hf-split.js"></script>

<hf-split items="Deploy to production|Ships to everyone;Deploy to staging|Internal testers only"></hf-split>
```

## Behaviour

A primary action with a menu of alternatives. Rows sweep in, a highlight springs between them, and choosing one rolls it into the main button.

## API reference

### Attributes

| Attribute | React prop | Type     | Default                                                                                                                                                                            | Description                                                                                                                                                |
| --------- | ---------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `items`   | `items`    | `string` | `Deploy to production\|Ships to everyone after checks;Deploy to staging\|Internal testers only;Create preview\|A unique URL for this branch;Schedule deploy…\|Pick a time tonight` | Menu entries separated by `;`, each `Label\|Description` with an optional description. The first entry starts selected. The menu is built once on connect. |

### Events

Events bubble and cross the shadow boundary unless the description says otherwise.

| Event    | React prop | Detail              | Description                                                                  |
| -------- | ---------- | ------------------- | ---------------------------------------------------------------------------- |
| `action` | `onAction` | `{ value: string }` | Fires when the main button is clicked. `value` is the selected item's label. |
| `select` | `onSelect` | `{ value: string }` | Fires when an item is chosen from the menu. `value` is its label.            |

### Methods

Call them on the element, for example through a React ref.

| Method                    | Description                                                                                                     |
| ------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `toggle(force?: boolean)` | Opens or closes the menu: `true` opens, `false` closes, no argument toggles. Opening focuses the selected item. |

### Properties

| Property            | Type                                | Description         |
| ------------------- | ----------------------------------- | ------------------- |
| `items` (read-only) | `{ label: string; desc: string }[]` | The parsed `items`. |

## Keyboard

| Keys                | Action                                                          |
| ------------------- | --------------------------------------------------------------- |
| ArrowDown           | On the caret button: open the menu and focus the selected item. |
| ArrowDown / ArrowUp | In the menu: move focus to the next or previous item, wrapping. |
| Escape              | In the menu: close it and return focus to the caret button.     |
| Tab                 | In the menu: close it and move focus on.                        |

## Accessibility

* The caret button has `aria-haspopup="menu"`, `aria-expanded` and a fixed `aria-label="More deploy options"`.
* The menu has `role="menu"`; items are buttons with `role="menuitemradio"`, `aria-checked` on the current choice and `tabindex="-1"`.
* Choosing an item closes the menu and returns focus to the caret button. A pointer press outside the element also closes the menu.
* Effects are drawn on an `aria-hidden` canvas.
* Reduced motion: the button's drifting noise stops, menu rows appear without the sweep, the highlight jumps between rows and the label changes without rolling.

## Theming

The element reads your shadcn theme tokens through its shadow root, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--border`, `--card`, `--foreground`, `--lumesec` and `--muted-foreground`.

To restyle only LumeSec elements, set the matching `--ui-*` overrides: `--ui-accent`, `--ui-border`, `--ui-fg`, `--ui-muted` and `--ui-surface`.

## Notes

* The host carries an `open` attribute while the menu is open, usable for styling. Setting it yourself does not open the menu; call `toggle()`.
* The menu is absolutely positioned below the button, up to 320px wide, and overlaps the content that follows.
* The main button is at least 200px wide and 46px tall.


