For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. An agent skill is available at /.well-known/agent-skills/site-skill.md.
Home

Dropdown Menu

A floating menu triggered by a button — for actions, navigation, and contextual options.

import { Button } from "@/components/ui/button";
import { Cloud, CreditCard, ExternalLink, Keyboard, LifeBuoy, LogOut, Mail, MessageSquare, Plus, PlusCircle, Settings, User, UserPlus, Users } from "lucide-react";
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";

export const DropdownMenuDemo = () => (
    <DropdownMenu>
      <DropdownMenuTrigger asChild><Button variant="outline">Open</Button></DropdownMenuTrigger>
      <DropdownMenuContent className="w-56">
        <DropdownMenuLabel>My Account</DropdownMenuLabel>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuItem><User /><span>Profile</span><DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut></DropdownMenuItem>
          <DropdownMenuItem><CreditCard /><span>Billing</span><DropdownMenuShortcut>⌘B</DropdownMenuShortcut></DropdownMenuItem>
          <DropdownMenuItem><Settings /><span>Settings</span><DropdownMenuShortcut>⌘S</DropdownMenuShortcut></DropdownMenuItem>
          <DropdownMenuItem><Keyboard /><span>Keyboard shortcuts</span><DropdownMenuShortcut>⌘K</DropdownMenuShortcut></DropdownMenuItem>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuItem><Users /><span>Team</span></DropdownMenuItem>
          <DropdownMenuSub>
            <DropdownMenuSubTrigger>
              <UserPlus />
              <span>Invite users</span>
            </DropdownMenuSubTrigger>
            <DropdownMenuPortal>
              <DropdownMenuSubContent>
                <DropdownMenuItem>
                  <Mail />
                  <span>Email</span>
                </DropdownMenuItem>
                <DropdownMenuItem>
                  <MessageSquare />
                  <span>Message</span>
                </DropdownMenuItem>
                <DropdownMenuSeparator />
                <DropdownMenuItem>
                  <PlusCircle />
                  <span>More...</span>
                </DropdownMenuItem>
              </DropdownMenuSubContent>
            </DropdownMenuPortal>
          </DropdownMenuSub>
          <DropdownMenuItem>
            <Plus />
            <span>New team</span>
            <DropdownMenuShortcut>⌘+T</DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuItem>
          <ExternalLink />
          <span>GitHub</span>
        </DropdownMenuItem>
        <DropdownMenuItem>
          <LifeBuoy />
          <span>Support</span>
        </DropdownMenuItem>
        <DropdownMenuItem disabled>
          <Cloud />
          <span>API</span>
        </DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuItem variant="destructive">
          <LogOut />
          <span>Log out</span>
          <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );

With Checkboxes

Use DropdownMenuCheckboxItem for toggleable settings that persist their state.

"use client";
 
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
 
export function DropdownMenuCheckboxes() {
  const [showStatusBar, setShowStatusBar] = useState(true);
  const [showActivityBar, setShowActivityBar] = useState(false);
  const [showPanel, setShowPanel] = useState(false);
 
  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="outline">View</Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-56">
        <DropdownMenuLabel>Appearance</DropdownMenuLabel>
        <DropdownMenuSeparator />
        <DropdownMenuCheckboxItem
          checked={showStatusBar}
          onCheckedChange={setShowStatusBar}
        >
          Status Bar
        </DropdownMenuCheckboxItem>
        <DropdownMenuCheckboxItem
          checked={showActivityBar}
          onCheckedChange={setShowActivityBar}
          disabled
        >
          Activity Bar
        </DropdownMenuCheckboxItem>
        <DropdownMenuCheckboxItem
          checked={showPanel}
          onCheckedChange={setShowPanel}
        >
          Panel
        </DropdownMenuCheckboxItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

With Radio Items

Use DropdownMenuRadioGroup for mutually exclusive selections.

"use client";
 
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuLabel,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
 
export function DropdownMenuRadioGroupDemo() {
  const [position, setPosition] = useState("bottom");
 
  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="outline">Position</Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-56">
        <DropdownMenuLabel>Panel Position</DropdownMenuLabel>
        <DropdownMenuSeparator />
        <DropdownMenuRadioGroup value={position} onValueChange={setPosition}>
          <DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
          <DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
          <DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
        </DropdownMenuRadioGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

Item sounds and haptics

Each DropdownMenuItem accepts sound and haptic props for per-item feedback. The sounds prop on DropdownMenu adds open/close audio.

import { Bell, Trash } from "lucide-react";
 
<DropdownMenu sounds>
  <DropdownMenuTrigger asChild>
    <Button variant="outline">Actions</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuItem sound="click" haptic>
      <Bell />
      <span>Notify</span>
    </DropdownMenuItem>
    <DropdownMenuItem variant="destructive" sound="error" haptic>
      <Trash />
      <span>Delete</span>
    </DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Props

PropTypeDefaultDescription
openboolean—Controlled open state
defaultOpenbooleanfalseUncontrolled initial open
onOpenChange(open: boolean) => void—Callback when state changes
soundsbooleanfalsePlay open/close audio feedback
modalbooleantrueWhether to trap focus inside the menu
PropTypeDefaultDescription
side"top" | "right" | "bottom" | "left""bottom"Preferred placement
align"start" | "center" | "end""center"Alignment along the trigger
sideOffsetnumber4Gap between trigger and menu
classNamestring—Use "w-56" to set a fixed width
PropTypeDefaultDescription
variant"default" | "destructive""default"Destructive styles for dangerous actions
insetbooleanfalseAdds left padding to align with icon items
disabledbooleanfalsePrevents selection
soundFeedbackType—Play a sound on click
hapticbooleanfalseTrigger haptic feedback on click

Usage

import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
 
<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button variant="outline">Open</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent className="w-56">
    <DropdownMenuLabel>My Account</DropdownMenuLabel>
    <DropdownMenuSeparator />
    <DropdownMenuGroup>
      <DropdownMenuItem>
        Profile
        <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
      </DropdownMenuItem>
      <DropdownMenuItem>
        Settings
        <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
      </DropdownMenuItem>
    </DropdownMenuGroup>
    <DropdownMenuSeparator />
    <DropdownMenuItem variant="destructive">Log out</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Specs

# Mint — Dropdown Menu Specs
 
## Component
- name: dropdown-menu
- file: registry/mint/dropdown-menu.tsx
- installs to: components/ui/dropdown-menu.tsx
- dependencies: radix-ui, lucide-react
- registryDependencies: none
 
## What is it
A Radix-powered floating action menu triggered by a button. Keyboard-navigable,
focus-trapped, and dismissable via Escape or click-outside. Use for actions,
navigation links, and contextual settings. Prefer ContextMenu for right-click
patterns; use Select for form value selection.
 
## Visual identity
Popover surface (--popover) with a subtle border and medium drop-shadow gives
the panel a floating, layered feel. Rounded-md corners (0.375rem) and compact
1.5/2 padding create a dense, tidy list. Accent-tinted hover states keep item
interactions consistent with the rest of the Mint palette.
 
## Design tokens
--popover: oklch(1 0 0) / oklch(0.269 0 0)                            — panel background
--popover-foreground: oklch(0.145 0 0) / oklch(0.985 0 0)             — panel text
--accent: oklch(0.92 0.05 155) / oklch(0.26 0.05 155)                          — item hover/focus background
--accent-foreground: oklch(0.32 0.1 155) / oklch(0.88 0.06 155)              — item hover/focus text
--muted-foreground: oklch(0.52 0.06 155) / oklch(0.6 0.06 155)               — icon and shortcut text
--destructive: oklch(0.55 0.25 15) / oklch(0.704 0.191 22.216)  — destructive item text
--border: oklch(0.88 0.04 155 / 60%) / oklch(0.32 0.05 155 / 40%)                       — panel border and separator
 
## Sub-components
- DropdownMenu             → root; accepts sounds prop for open/close audio
- DropdownMenuTrigger      → trigger element; use asChild to wrap a Button
- DropdownMenuPortal       → renders outside DOM tree; required for SubContent to avoid clipping
- DropdownMenuContent      → floating panel; sideOffset=4, min-w-[8rem], scrollable
- DropdownMenuGroup        → semantic grouping of items (no visual output; pair with DropdownMenuLabel)
- DropdownMenuItem         → action row; variant and sound/haptic props
- DropdownMenuCheckboxItem → toggleable item with CheckIcon indicator
- DropdownMenuRadioGroup   → container for mutually exclusive radio items; holds value + onValueChange
- DropdownMenuRadioItem    → single radio option with CircleIcon dot indicator
- DropdownMenuLabel        → non-interactive section heading; inset prop for alignment
- DropdownMenuSeparator    → horizontal rule (bg-border, h-px)
- DropdownMenuShortcut     → right-aligned keyboard hint (display only, muted text)
- DropdownMenuSub          → sub-menu root
- DropdownMenuSubTrigger   → opens sub-menu; ChevronRightIcon auto-appended; inset prop
- DropdownMenuSubContent   → floating panel for nested sub-menu
 
## Variants
- default      → standard item; accent background on focus
- destructive  → text-destructive; destructive/10 (light) or destructive/20 (dark) bg on focus
 
## States
- focus:        items show bg-accent + text-accent-foreground (keyboard and pointer)
- data-[state=open]: SubTrigger shows bg-accent + text-accent-foreground while sub-menu is open
- data-[disabled]: pointer-events-none + opacity-50 on any item
- data-[state=open/closed]: Content and SubContent animate in/out with fade + zoom + slide
 
## Conventions
- Set a fixed width on DropdownMenuContent: className="w-56"
- Group related items with DropdownMenuGroup + DropdownMenuLabel for labelled sections
- DropdownMenuShortcut is display-only — bind actual keyboard shortcuts separately via useEffect
- Wrap DropdownMenuSubContent in DropdownMenuPortal to prevent clipping inside overflow containers
- inset prop on DropdownMenuItem, DropdownMenuLabel, and DropdownMenuSubTrigger adds pl-8 to align text with icon-prefixed siblings
- sounds / haptic: GIN Design exclusive — sounds prop on DropdownMenu plays dropdownOpen/dropdownClose audio; sound and haptic props on DropdownMenuItem trigger per-item audio or haptic feedback on click
- Sub-components expose data-slot="[name]" for CSS targeting (e.g. data-slot="dropdown-menu-item")
- Do not use DropdownMenu for form value selection — use Select instead

Installation

GIN Design Plugin
$ npx shadcn add https://gin-design.vercel.app/dropdown-menu