Dropdown
Dropdown menus appear below a trigger element and provide a list of contextual actions. Used for user profile menus, row action menus, and select-like interfaces.
Overview
Dropdowns are positioned absolutely relative to their trigger. They open on click (not hover). Clicking outside closes them. Items support icons, dividers, danger styling, and disabled states. Max 8 visible items before scrolling.
Variants
User Profile Menu
Row Actions
Token Reference
| Part | Class | Value |
|---|---|---|
| Container | .dropdown-menu | bg:#fff, border:1px solid #E2E8F0, radius:14px, shadow: 0 10px 40px rgba(0,0,0,.1), padding:6px |
| Item | .dropdown-item | flex, gap:10px, padding:9px 12px, radius:8px, 13px fw-500, hover:bg:#F8FAFC |
| Danger item | .dropdown-item.danger | color:#F05252, hover:bg:#FDE2E2 |
| Disabled item | .dropdown-item.disabled | color:#94A3B8, cursor:not-allowed |
| Divider | .dropdown-divider | height:1px, bg:#F1F5F9, margin:4px 0 |
| Section header | .dropdown-header | 10px, fw-700, UPPERCASE, #94A3B8, padding:8px 12px 4px |
| Icon | .dropdown-icon | 16×16px, color:#64748B, flex-shrink:0 |
| Position default | .dropdown-menu | top:calc(100%+6px), right:0 (aligns right by default) |
| Position left | .dropdown-menu.left | right:auto, left:0 (aligns left) |
AI Implementation Notes
For AI coding assistants: Dropdowns require a click-outside handler:
document.addEventListener('click', e => { if(!wrap.contains(e.target)) menu.style.display='none' }). Always use display:none/block toggle — not CSS visibility or opacity — for show/hide. The .dropdown-wrap must be position:relative and display:inline-block. Icons inside items are always 16×16px SVG with class .dropdown-icon. Dropdown items can be <a> or <div> elements.
When to Use
Use Dropdown when
- User profile menu (profile, settings, logout)
- Row action menus (view, edit, duplicate, delete)
- More actions overflow menu
Don't use Dropdown when
- Selecting a value from a list — use Select instead
- Only 1-2 items — show them as regular buttons
- Navigation between pages — use sidebar
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
| trigger | ReactNode | required | — | Button or element that opens the dropdown on click. |
| items | array | required | — | Array of menu items. Each item: {label, icon, onClick, danger, divider, header, disabled}. |
| position | string | optional | 'right' | Alignment of menu relative to trigger. 'left' | 'right' |
Behavior
| Trigger | Behavior |
|---|---|
| Trigger click | Toggle menu display:none/block. Close all other open dropdowns first. |
| Click outside | Close menu. Use document.addEventListener('mousedown') — not click — to prevent propagation issues. |
| Escape key | Close menu and return focus to trigger. |
| Item click | Execute item.onClick, then close menu. |
Design Decisions
Why border-radius:14px on dropdown menu — larger than other components?
Dropdown menus float above the page with a strong shadow. The larger radius (14px vs 10px for inputs) helps reinforce the elevated, floating nature of the menu. It creates a visual distinction between inline controls and floating overlays.
Changelog
v1.0.0July 2026Added
- Context menus with icon, label, divider, section header, danger, disabled states
- Click-outside close handler
- Left/right position variants
States
View Detail
Edit
Delete
Open
Visible, shadow, items available
Disabled item
Disabled Item
color:#94A3B8, pointer-events:none
Accessibility
| Requirement | Implementation |
|---|---|
| role="menu" | Add to .dropdown-menu container. |
| role="menuitem" | Add to each .dropdown-item. |
| aria-haspopup="menu" | Add to trigger button. |
| aria-expanded | true when open, false when closed on trigger button. |
| Escape key | Closes menu and returns focus to trigger. |
| Arrow keys | Up/Down navigate menu items. |
Composition
Allowed
Triggered by icon-only button (.btn-icon-only)
User profile menu in topbar
Row action menu in tables
More actions overflow button
Forbidden
As replacement for Select for data inputs
More than 8 items without grouping/dividers
Nested dropdown submenus
Best Practices
Do
Group related actions with dividers. Put destructive actions last, after a divider.
Clear visual grouping reduces scanning time.
Don't
Mix navigation links and action buttons in the same menu without grouping.
Different action types need visual separation.
Related Components
Anatomy
1
Wrapper
div.dropdown-wrap. position:relative, display:inline-block. Contains trigger + menu.
2
Trigger
Any button element. Click opens/closes menu. aria-haspopup="menu", aria-expanded reflects open state.
3
Menu Container
div.dropdown-menu. position:absolute, top:calc(100%+6px), right:0. bg:#fff, border-radius:14px, box-shadow, padding:6px.
4
Menu Item
a or div.dropdown-item. display:flex, gap:10px, padding:9px 12px, radius:8px. Optional icon (16px), label text, and .danger variant.
5
Divider
div.dropdown-divider. height:1px, bg:#F1F5F9, margin:4px 0. Separates logical groups.
Content Rules
Good item label
View Detail
Verb + noun. Clear action.
Bad item label
Click to see more information
Too verbose for a menu item. Keep to 2 words max.