> ## Documentation Index
> Fetch the complete documentation index at: https://araf.badr.co.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Dropdown Menu

> A floating menu triggered by a button click — supports icons, keyboard shortcuts, sub-menus, separators, and destructive items.

## Overview

<div style={{padding:"28px 24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",gap:"32px",alignItems:"flex-start",flexWrap:"wrap"}}>
  <div style={{display:"flex",flexDirection:"column",gap:"8px",fontFamily:"Inter,sans-serif"}}>
    <button style={{display:"flex",alignItems:"center",gap:"6px",padding:"8px 14px",border:"1px solid #D0D5DD",borderRadius:"8px",background:"#fff",fontSize:"14px",color:"#344054",fontWeight:500,cursor:"pointer"}}>
      My account

      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
        <polyline points="6 9 12 15 18 9" />
      </svg>
    </button>

    <div style={{background:"#fff",border:"1px solid #E5E7EB",borderRadius:"10px",boxShadow:"0 4px 16px rgba(0,0,0,0.1)",padding:"4px",minWidth:"180px"}}>
      <div style={{padding:"6px 8px",display:"flex",alignItems:"center",gap:"8px",fontSize:"13px",color:"#344054",borderRadius:"6px",cursor:"pointer"}}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#667085" strokeWidth="2">
          <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />

          <circle cx="12" cy="7" r="4" />
        </svg>

        Profile
      </div>

      <div style={{padding:"6px 8px",display:"flex",alignItems:"center",gap:"8px",fontSize:"13px",color:"#344054",borderRadius:"6px",cursor:"pointer"}}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#667085" strokeWidth="2">
          <circle cx="12" cy="12" r="3" />

          <path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14" />
        </svg>

        Settings
        <span style={{marginLeft:"auto",fontSize:"11px",color:"#9CA3AF"}}>⌘S</span>
      </div>

      <div style={{height:"1px",background:"#F2F4F7",margin:"4px 0"}} />

      <div style={{padding:"6px 8px",display:"flex",alignItems:"center",gap:"8px",fontSize:"13px",color:"#DC2626",borderRadius:"6px",cursor:"pointer"}}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#DC2626" strokeWidth="2">
          <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />

          <polyline points="16 17 21 12 16 7" />

          <line x1="21" y1="12" x2="9" y2="12" />
        </svg>

        Log out
      </div>
    </div>
  </div>
</div>

**Dropdown Menu** is a floating panel triggered by a click — used for contextual actions, user account menus, and option lists. It supports icons, keyboard shortcuts, checkboxes, radio items, sub-menus, and separators.

***

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @araf-ds/core
  ```

  ```bash yarn theme={null}
  yarn add @araf-ds/core
  ```

  ```bash pnpm theme={null}
  pnpm add @araf-ds/core
  ```
</CodeGroup>

***

## Usage

```tsx theme={null}
import {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
} from "@araf-ds/core"

export default function Example() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="outline">My account</Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end">
        <DropdownMenuItem>
          <UserIcon size={14} /> Profile
        </DropdownMenuItem>
        <DropdownMenuItem>
          <SettingsIcon size={14} /> Settings
          <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
        </DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuItem variant="destructive">
          <LogOutIcon size={14} /> Log out
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}
```

***

## Variants

### Basic with Icons and Shortcuts

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",gap:"16px",alignItems:"flex-start",flexWrap:"wrap"}}>
  <div style={{background:"#fff",border:"1px solid #E5E7EB",borderRadius:"10px",boxShadow:"0 4px 16px rgba(0,0,0,0.1)",padding:"4px",minWidth:"200px",fontFamily:"Inter,sans-serif"}}>
    <div style={{padding:"6px 8px",fontSize:"11px",color:"#667085",fontWeight:500}}>My account</div>

    <div style={{height:"1px",background:"#F2F4F7",margin:"2px 0"}} />

    {[
            {icon:"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2 M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z",label:"Profile",shortcut:"⌘P"},
            {icon:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",label:"Billing",shortcut:"⌘B"},
            {icon:"M18 20V10 M12 20V4 M6 20v-6",label:"Settings",shortcut:"⌘S"},
          ].map(item => (
            <div key={item.label} style={{padding:"7px 8px",display:"flex",alignItems:"center",gap:"8px",fontSize:"13px",color:"#344054",borderRadius:"6px",cursor:"pointer"}}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#667085" strokeWidth="2">
                {item.icon.split("M").filter(Boolean).map((seg,i) => <path key={i} d={"M"+seg}/>)}
              </svg>
              {item.label}
              <span style={{marginLeft:"auto",fontSize:"11px",color:"#9CA3AF"}}>{item.shortcut}</span>
            </div>
          ))}

    <div style={{height:"1px",background:"#F2F4F7",margin:"4px 0"}} />

    <div style={{padding:"7px 8px",display:"flex",alignItems:"center",gap:"8px",fontSize:"13px",color:"#DC2626",borderRadius:"6px",cursor:"pointer"}}>
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#DC2626" strokeWidth="2">
        <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />

        <polyline points="16 17 21 12 16 7" />

        <line x1="21" y1="12" x2="9" y2="12" />
      </svg>

      Log out
      <span style={{marginLeft:"auto",fontSize:"11px",color:"#FDA29B"}}>⇧⌘Q</span>
    </div>
  </div>
</div>

```tsx theme={null}
<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button variant="outline">Open</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent align="end" className="w-48">
    <DropdownMenuLabel>My account</DropdownMenuLabel>
    <DropdownMenuSeparator />
    <DropdownMenuItem>
      <UserIcon size={14} /> Profile
      <DropdownMenuShortcut>⌘P</DropdownMenuShortcut>
    </DropdownMenuItem>
    <DropdownMenuItem>
      <StarIcon size={14} /> Billing
      <DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
    </DropdownMenuItem>
    <DropdownMenuItem>
      <BarChartIcon size={14} /> Settings
      <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
    </DropdownMenuItem>
    <DropdownMenuSeparator />
    <DropdownMenuItem variant="destructive">
      <LogOutIcon size={14} /> Log out
      <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
    </DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>
```

### With Checkbox Items

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{background:"#fff",border:"1px solid #E5E7EB",borderRadius:"10px",boxShadow:"0 4px 16px rgba(0,0,0,0.1)",padding:"4px",minWidth:"200px",fontFamily:"Inter,sans-serif",display:"inline-block"}}>
    <div style={{padding:"6px 8px",fontSize:"11px",color:"#667085",fontWeight:500}}>Appearance</div>

    <div style={{height:"1px",background:"#F2F4F7",margin:"2px 0"}} />

    {[{label:"Show status bar",checked:true},{label:"Show activity bar",checked:false},{label:"Show sidebar",checked:true}].map(item => (
            <div key={item.label} style={{padding:"7px 8px",display:"flex",alignItems:"center",gap:"8px",fontSize:"13px",color:"#344054",borderRadius:"6px",cursor:"pointer"}}>
              <div style={{width:"14px",height:"14px",borderRadius:"3px",border:item.checked?"none":"1px solid #D0D5DD",background:item.checked?"#0479CE":"transparent",display:"flex",alignItems:"center",justifyContent:"center"}}>
                {item.checked && <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3"><polyline points="20 6 9 17 4 12"/></svg>}
              </div>
              {item.label}
            </div>
          ))}
  </div>
</div>

```tsx theme={null}
const [showStatusBar, setShowStatusBar] = useState(true)
const [showSidebar, setShowSidebar] = useState(true)

<DropdownMenuContent>
  <DropdownMenuLabel>Appearance</DropdownMenuLabel>
  <DropdownMenuSeparator />
  <DropdownMenuCheckboxItem
    checked={showStatusBar}
    onCheckedChange={setShowStatusBar}
  >
    Show status bar
  </DropdownMenuCheckboxItem>
  <DropdownMenuCheckboxItem
    checked={showSidebar}
    onCheckedChange={setShowSidebar}
  >
    Show sidebar
  </DropdownMenuCheckboxItem>
</DropdownMenuContent>
```

### With Sub-menu

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{background:"#fff",border:"1px solid #E5E7EB",borderRadius:"10px",boxShadow:"0 4px 16px rgba(0,0,0,0.1)",padding:"4px",minWidth:"180px",fontFamily:"Inter,sans-serif",display:"inline-block"}}>
    <div style={{padding:"7px 8px",display:"flex",alignItems:"center",gap:"8px",fontSize:"13px",color:"#344054",borderRadius:"6px",cursor:"pointer"}}>
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#667085" strokeWidth="2">
        <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />

        <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
      </svg>

      Edit
    </div>

    <div style={{padding:"7px 8px",display:"flex",alignItems:"center",gap:"8px",fontSize:"13px",color:"#344054",borderRadius:"6px",cursor:"pointer"}}>
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#667085" strokeWidth="2">
        <rect x="9" y="9" width="13" height="13" rx="2" />

        <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
      </svg>

      Duplicate
    </div>

    <div style={{padding:"7px 8px",display:"flex",alignItems:"center",gap:"8px",fontSize:"13px",color:"#344054",borderRadius:"6px",cursor:"pointer",background:"#F9FAFB"}}>
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#667085" strokeWidth="2">
        <circle cx="18" cy="5" r="3" />

        <circle cx="6" cy="12" r="3" />

        <circle cx="18" cy="19" r="3" />

        <line x1="8.59" y1="13.51" x2="15.42" y2="17.49" />

        <line x1="15.41" y1="6.51" x2="8.59" y2="10.49" />
      </svg>

      Share

      <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#9CA3AF" strokeWidth="2" style={{marginLeft:"auto"}}>
        <polyline points="9 18 15 12 9 6" />
      </svg>
    </div>
  </div>
</div>

```tsx theme={null}
<DropdownMenuContent>
  <DropdownMenuItem><EditIcon size={14} /> Edit</DropdownMenuItem>
  <DropdownMenuItem><CopyIcon size={14} /> Duplicate</DropdownMenuItem>
  <DropdownMenuSub>
    <DropdownMenuSubTrigger>
      <ShareIcon size={14} /> Share
    </DropdownMenuSubTrigger>
    <DropdownMenuSubContent>
      <DropdownMenuItem>Email link</DropdownMenuItem>
      <DropdownMenuItem>Copy link</DropdownMenuItem>
      <DropdownMenuItem>Twitter</DropdownMenuItem>
    </DropdownMenuSubContent>
  </DropdownMenuSub>
</DropdownMenuContent>
```

***

## API Reference

### DropdownMenu

<ParamField path="open" type="boolean">
  Controlled open state.
</ParamField>

<ParamField path="onOpenChange" type="(open: boolean) => void">
  Callback fired when open state changes.
</ParamField>

<ParamField path="defaultOpen" type="boolean" default="false">
  Uncontrolled default open state.
</ParamField>

### DropdownMenuContent

<ParamField path="align" type="string" default="start">
  Horizontal alignment relative to the trigger. Values: `start` · `center` · `end`
</ParamField>

<ParamField path="side" type="string" default="bottom">
  Which side to render on. Values: `top` · `right` · `bottom` · `left`
</ParamField>

<ParamField path="sideOffset" type="number" default="4">
  Distance in px between the trigger and the menu.
</ParamField>

<ParamField path="className" type="string">
  Additional class names for the menu panel.
</ParamField>

### DropdownMenuItem

<ParamField path="variant" type="string" default="default">
  Visual style. `"destructive"` renders item in red.
</ParamField>

<ParamField path="disabled" type="boolean" default="false">
  Disables the item — it becomes non-interactive and grayed out.
</ParamField>

<ParamField path="onSelect" type="() => void">
  Callback fired when the item is selected. Menu closes automatically.
</ParamField>

### DropdownMenuCheckboxItem

<ParamField path="checked" type="boolean">
  Controlled checked state.
</ParamField>

<ParamField path="onCheckedChange" type="(checked: boolean) => void">
  Callback fired when checked state changes.
</ParamField>

***

## Accessibility

* Dropdown menu uses `role="menu"` with `aria-orientation="vertical"`
* Each item has `role="menuitem"` (or `"menuitemcheckbox"` / `"menuitemradio"`)
* Trigger has `aria-haspopup="menu"` and `aria-expanded`
* Keyboard: Arrow keys navigate items, Enter/Space selects, Escape closes, Tab closes and moves focus
* Sub-menus open on ArrowRight and close on ArrowLeft or Escape

***

## Do's & Don'ts

<CardGroup cols={2}>
  <Card title="Do" icon="check" iconType="solid" color="#16A34A">
    * Group related actions with `DropdownMenuSeparator`
    * Use `DropdownMenuLabel` to label groups of items
    * Add keyboard shortcuts via `DropdownMenuShortcut` for power users
    * Mark destructive items with `variant="destructive"` for visual clarity
  </Card>

  <Card title="Don't" icon="xmark" iconType="solid" color="#DC2626">
    * Don't use Dropdown Menu for navigation — use a Navbar or Sidebar
    * Don't put more than 10–12 items without grouping or sub-menus
    * Don't use it for single-action triggers — use a Button
    * Don't nest sub-menus more than 2 levels deep
  </Card>
</CardGroup>
