# `useAnchoredMenu` Hook

## Purpose

`useAnchoredMenu` is a React hook that enables components to display anchored menus (like `Menu` or `CommandMenu`) positioned relative to a specific anchor element. Unlike [`useContextMenu`](./use-context-menu.md) which positions at cursor coordinates, `useAnchoredMenu` anchors to an element, making it ideal for dropdown menus, popovers, or programmatically triggered menus attached to specific UI elements.

The hook provides a clean API for programmatic menu opening and automatic integration with the global menu synchronization system.

## Related Components

- [`useContextMenu`](./use-context-menu.md) - For cursor-positioned context menus
- [`MenuTrigger`](./MenuTrigger.md) - The underlying trigger component used for positioning
- [`Menu`](./Menu.md) - The menu component typically used with this hook
- [`CommandMenu`](./CommandMenu.md) - Command palette component that can be used with this hook

## API

```ts
function useAnchoredMenu&lt;P, T = ComponentProps&lt;typeof MenuTrigger&gt;&gt;(
  Component: ComponentType&lt;P&gt;,
  defaultTriggerProps?: Omit&lt;
    ComponentProps&lt;typeof MenuTrigger&gt;,
    'children' | 'isOpen' | 'onOpenChange' | 'targetRef'
  &gt;,
  defaultMenuProps?: P,
): {
  /** Ref to attach to the anchor element for positioning the menu. */
  anchorRef: RefObject&lt;HTMLElement&gt;;

  /**
   * Programmatically opens the menu with the provided props.
   * Runtime props are merged with defaultMenuProps (runtime props take precedence).
   * @param props - Props to pass to the menu component (merged with defaultMenuProps)
   * @param triggerProps - Additional props for MenuTrigger (merged with defaultTriggerProps)
   */
  open(props: P, triggerProps?: T): void;

  /**
   * Updates the props of the currently open menu.
   * Props are merged with defaultMenuProps.
   */
  update(props: P, triggerProps?: T): void;

  /** Closes the menu programmatically. */
  close(): void;

  /** Current open/closed state of the menu. */
  isOpen: boolean;

  /**
   * JSX element that must be rendered in your component tree.
   * Contains the MenuTrigger and positioning logic.
   */
  get rendered(): ReactElement | null;
};
```

### Parameters

- **`Component`** - The menu component to render (`Menu`, `CommandMenu`, etc.)
- **`defaultTriggerProps`** - Default props passed to `MenuTrigger` for positioning and behavior
- **`defaultMenuProps`** - Default props passed to the menu component (merged with runtime props)

## Key Features

### Programmatic Control

The hook provides full programmatic control over the menu:

- **`open()`** opens the menu with provided props
- **`update()`** updates menu props without closing/reopening
- **`close()`** closes the menu
- **No automatic triggering** - designed for manual control via events or state

### Element-Based Positioning

Positions menus relative to the anchor element:

- Uses **`anchorRef`** for positioning context
- Supports **collision detection** and automatic repositioning via MenuTrigger
- **Default placement:** `"bottom start"`
- Customizable via `defaultTriggerProps` or runtime `triggerProps`

### Props Merging Strategy

- **`defaultMenuProps`** - Used as base props for the menu component
- **Runtime props** (via `open()`/`update()`) - Merged with defaults, taking precedence
- **Trigger props** - Merged with `defaultTriggerProps` for positioning control

### Menu Synchronization

Integrates with the global menu synchronization system:

- **Only one menu open** at a time across the entire application
- **Automatic closing** when other menus open
- **Works with** `MenuTrigger`, `useContextMenu`, `Select`, `ComboBox`, etc.

## Usage

```tsx
import { useAnchoredMenu, Menu, Button, Flex } from '@cube-dev/ui-kit';
import { IconDotsVertical } from '@tabler/icons-react';

function TabWithMultipleTriggers() {
  const menu = useAnchoredMenu(
    Menu, 
    {
      placement: 'top end',
    },
    {
      // Default menu props applied to all menu opens
      onAction: (key) => {
        console.log('Tab action:', key);
      },
      children: (
        <>
          <Menu.Item key="rename">Rename Tab</Menu.Item>
          <Menu.Item key="duplicate">Duplicate Tab</Menu.Item>
          <Menu.Item key="close">Close Tab</Menu.Item>
          <Menu.Item key="close-others">Close Other Tabs</Menu.Item>
        </>
      ),
    }
  );

  const openTab = () => {
    console.log('Opening tab...');
  };

  const openActionsMenu = () => {
    // Opens with default props - no need to pass them again
    menu.open();
  };

  const handleRightClick = (event) => {
    event.preventDefault();
    openActionsMenu(event);
  };

  return (
    <>
      <Flex
        ref={menu.anchorRef}
        display="inline-flex"
        onContextMenu={handleRightClick}
      >
        <Button size="small" radius="left" onPress={openTab}>
          Open file
        </Button>

        <Button
          size="small"
          icon={<IconDotsVertical />}
          aria-label="Tab actions"
          padding="1x"
          radius="right"
          margin="-1bw left"
          onPress={openActionsMenu}
        />
      </Flex>

      {menu.rendered}
    </>
  );
}
```

This example demonstrates how `defaultMenuProps` simplifies menu usage by defining common menu content once:

1. **Click the dots button** to open the actions menu
2. **Right-click anywhere on the tab** to also open the same actions menu

The menu content and behavior are defined in `defaultMenuProps`, eliminating the need to pass the same props repeatedly. Both triggers share the same anchor point (`menu.anchorRef`) and use the predefined menu configuration, showcasing how `defaultMenuProps` reduces code duplication in complex UI interactions.

> **Important:** The `{rendered}` element must be placed in the component tree such that the MenuTrigger can properly position relative to the anchorRef. Typically, place it adjacent to the anchor element.

## Comparison with Related Hooks

- **`Positioning`** — useAnchoredMenu: Element-anchored; useContextMenu: Cursor coordinates
- **`Trigger`** — useAnchoredMenu: Manual (programmatic); useContextMenu: Right-click (automatic)
- **`Event Binding`** — useAnchoredMenu: Manual event handling; useContextMenu: Automatic `onContextMenu`
- **`Use Cases`** — useAnchoredMenu: Dropdown menus, action buttons; useContextMenu: Context menus, right-click actions
- **`Default Placement`** — Both: `"bottom start"`
- **`Setup Complexity`** — useAnchoredMenu: Manual open calls; useContextMenu: Minimal (auto-binding)

## Implementation Notes

### Positioning

The hook positions the menu by:

1. Using the **`anchorRef`** as the positioning target
2. Creating a visually hidden trigger for accessibility
3. Delegating to **`MenuTrigger`** for collision detection and final positioning

### Event Handling

- **No automatic events** - consumer must call `open()` in response to events
- **State management** handled internally with synchronization

### Memory Management

- **Event listeners** for global synchronization cleaned up automatically
- **Menu content** only rendered when open
- **No memory leaks** from uncleaned handlers

---

*Last updated: 2025-01-16* 

### 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`
