# SilkeOverflowMenu

A dropdown menu component triggered by a button click or right-click. Perfect for action menus, context menus, and option lists.

## Features

- **Click or right-click trigger**: Configure how the menu opens
- **Item-based or custom content**: Use predefined items or render custom children
- **Item kinds**: Default, danger, and selected states
- **Dividers**: Separate groups of items
- **Controlled or uncontrolled**: Manage open state externally or let the component handle it
- **Positioning options**: Control where the menu appears relative to the trigger

## Basic Usage

```js
<SilkeOverflowMenu
  items={[
    { label: 'Edit', icon: 'edit' },
    { label: 'Duplicate', icon: 'copy' },
    { label: 'Delete', icon: 'delete', kind: 'danger' },
  ]}
/>
```

## With Icons

```js
<SilkeOverflowMenu
  items={[
    { label: 'Cut', icon: 'cut', onClick: () => console.log('Cut') },
    { label: 'Copy', icon: 'copy', onClick: () => console.log('Copy') },
    { label: 'Paste', icon: 'paste', onClick: () => console.log('Paste') },
  ]}
/>
```

## Item Kinds

Use `kind` to style items differently:

```js
<SilkeOverflowMenu
  items={[
    { label: 'View', icon: 'eye' },
    { label: 'Edit', icon: 'edit' },
    { label: 'Currently selected', icon: 'check', kind: 'selected' },
    'divider',
    { label: 'Delete', icon: 'delete', kind: 'danger' },
  ]}
/>
```

## With Dividers

Use `'divider'` string to separate groups:

```js
<SilkeOverflowMenu
  items={[
    { label: 'New File', icon: 'file.add' },
    { label: 'New Folder', icon: 'folder.add' },
    'divider',
    { label: 'Import', icon: 'upload' },
    { label: 'Export', icon: 'download' },
    'divider',
    { label: 'Settings', icon: 'settings' },
  ]}
/>
```

## Custom Trigger Button

Customize the trigger button with label and icon:

```js
<SilkeBox gap="m">
  <SilkeOverflowMenu
    label="Actions"
    items={[{ label: 'Action 1' }, { label: 'Action 2' }]}
  />
  <SilkeOverflowMenu
    icon="settings"
    items={[{ label: 'Settings 1' }, { label: 'Settings 2' }]}
  />
  <SilkeOverflowMenu
    label="Options"
    icon="chevron.down"
    items={[{ label: 'Option 1' }, { label: 'Option 2' }]}
  />
</SilkeBox>
```

## Right-Click Trigger

Open the menu on right-click (context menu):

```js
<SilkeOverflowMenu
  trigger="right-click"
  label="Right-click me"
  items={[
    { label: 'Cut' },
    { label: 'Copy' },
    { label: 'Paste' },
  ]}
/>
```

## Custom Content

Render custom content instead of predefined items:

```js
const items = [
  { id: 1, label: 'Option A' },
  { id: 2, label: 'Option B' },
  { id: 3, label: 'Option C' },
];
const [selected, setSelected] = React.useState([]);

<SilkeOverflowMenu label="Select options">
  <SilkeBox column hPad="s" vPad="xs" bg="neutral-10" shadow="level2" gap="xs" rounded="small">
    {items.map((item) => (
      <SilkeCheckbox
        key={item.id}
        label={item.label}
        value={selected.includes(item.id)}
        onChange={(checked) => {
          setSelected(checked ? [...selected, item.id] : selected.filter((id) => id !== item.id));
        }}
      />
    ))}
  </SilkeBox>
</SilkeOverflowMenu>;
```

## Controlled Open State

Manage the open state externally:

```js
const [open, setOpen] = React.useState(false);

<SilkeBox gap="m" vAlign="center">
  <SilkeOverflowMenu
    open={open}
    onToggleOpen={setOpen}
    items={[{ label: 'Item 1' }, { label: 'Item 2' }]}
  />
  <SilkeText size="s">Menu is {open ? 'open' : 'closed'}</SilkeText>
</SilkeBox>;
```

## Dynamic Items

Pass a function to generate items dynamically:

```js
const getItems = () => [
  { label: `Generated at ${new Date().toLocaleTimeString()}` },
  { label: 'Static item' },
];

<SilkeOverflowMenu items={getItems} />;
```

## Positioning

Control menu placement with origin props:

```js
<SilkeBox gap="m">
  <SilkeOverflowMenu
    label="Bottom Right"
    anchorOrigin="bottom-right"
    targetOrigin="top-right"
    items={[{ label: 'Item 1' }, { label: 'Item 2' }]}
  />
  <SilkeOverflowMenu
    label="Bottom Left"
    anchorOrigin="bottom-left"
    targetOrigin="top-left"
    items={[{ label: 'Item 1' }, { label: 'Item 2' }]}
  />
</SilkeBox>
```

## Disabled Items

```js
<SilkeOverflowMenu
  items={[
    { label: 'Enabled action', icon: 'check' },
    { label: 'Disabled action', icon: 'close', disabled: true },
    { label: 'Another enabled', icon: 'star' },
  ]}
/>
```

## Props

| Prop           | Type                                              | Default          | Description                              |
| -------------- | ------------------------------------------------- | ---------------- | ---------------------------------------- |
| `items`        | `(SilkeOverflowMenuItem \| 'divider')[] \| () => ...` | `[]`         | Menu items or function returning items   |
| `children`     | `React.ReactNode`                                 | -                | Custom content instead of items          |
| `trigger`      | `'click' \| 'right-click'`                        | `'click'`        | What opens the menu                      |
| `open`         | `boolean`                                         | -                | Controlled open state                    |
| `onToggleOpen` | `(open: boolean) => void`                         | -                | Callback when open state changes         |
| `label`        | `string`                                          | -                | Button label                             |
| `icon`         | `SilkeIcons`                                      | `'menuMore'`     | Button icon                              |
| `anchorOrigin` | `PopoverOrigin`                                   | `'bottom-right'` | Where menu attaches to button            |
| `targetOrigin` | `PopoverOrigin`                                   | `'top-right'`    | Which corner of menu aligns to anchor    |
| `offsetX`      | `number`                                          | -                | Horizontal offset in pixels              |
| `offsetY`      | `number`                                          | -                | Vertical offset in pixels                |

Also accepts all `SilkeButton` props for the trigger button.

## SilkeOverflowMenuItem

| Prop         | Type                            | Default     | Description                    |
| ------------ | ------------------------------- | ----------- | ------------------------------ |
| `label`      | `React.ReactNode`               | Required    | Item text                      |
| `kind`       | `'default' \| 'danger' \| 'selected'` | `'default'` | Item style variant       |
| `icon`       | `SilkeIcons`                    | -           | Item icon                      |
| `disabled`   | `boolean`                       | `false`     | Disable the item               |
| `onClick`    | `(e: React.MouseEvent) => void` | -           | Click handler                  |
| `groupLabel` | `string`                        | -           | Label for grouping (internal)  |

Also accepts most `SilkeButton` props.

## Types

```typescript
type SilkeOverflowMenuItem = {
  label: React.ReactNode;
  kind?: 'default' | 'danger' | 'selected';
  groupLabel?: string;
} & Omit<SilkeButtonProps, 'height' | 'width' | 'align' | 'vAlign' | 'hAlign' | 'kind'>;
```
