Dropdown

A dropdown menu component that displays a list of options triggered by a button or element

Installation

Terminal
pnpm add @choice-ui/dropdown

Import

Component.tsx
import { Dropdown, type DropdownProps } from "@choice-ui/dropdown"

Basic

Basic: The simplest usage of Dropdown.
Features:
- Click-triggered dropdown menu - Standard menu items - Keyboard navigation support - Automatic dismissal on click outside

Disabled

Disabled: Demonstrates disabled Dropdown functionality.
Features:
- Disabled trigger prevents menu opening - Disabled items prevent interaction - Visual feedback for disabled states - Useful for conditional menu availability

Large Size

LargeSize: Demonstrates Dropdown with large size variant.
Features:
- Large trigger size - Large menu items - Consistent sizing across components

Light Variant

LightVariant: Demonstrates Dropdown with light variant styling.
Features:
- Light variant visual style - Standard menu items - Divider separation - Danger variant item support

With Prefix

WithPrefix: Demonstrates Dropdown with prefix icons.
Features:
- Prefix icons on trigger - Prefix icons on menu items - Better visual recognition - Enhanced user experience

With Shortcuts

WithShortcuts: Demonstrates Dropdown with keyboard shortcuts.
Features:
- Keyboard shortcuts displayed on menu items - Supports modifier keys (Command, Shift, etc.) - Visual shortcut indicators - Common editor shortcuts pattern

With Labels And Dividers

WithLabelsAndDividers: Demonstrates Dropdown with labels and dividers for organization.
Features:
- Section labels for grouping - Visual dividers for separation - Better menu organization - Hierarchical menu structure
Use cases:
- File manager menus - Complex application menus - Settings and configuration menus

Long List

LongList: Demonstrates Dropdown with a long list of items and scrolling behavior.
Features:
- Long list of items (100 items) - Automatic scrolling when content exceeds height - Scroll arrows for navigation - Performance optimization for large lists
Use cases:
- Country/region selectors - Long option lists - Searchable dropdowns with many results

Placement

Placement: Demonstrates Dropdown with different placement options.
Features:
- Multiple placement options (bottom-start, bottom-end, right-start, etc.) - Automatic positioning adjustments - Prevents overflow beyond viewport - Flexible menu positioning

Match Trigger Width

MatchTriggerWidth: Demonstrates Dropdown menu matching trigger width.
Features:
- Menu width matches trigger width - Consistent visual alignment - Useful for narrow triggers - Better visual consistency

Trigger As Child

TriggerAsChild: Demonstrates custom trigger using asChild pattern.
Features:
- Use any element as trigger via asChild prop - Complete control over trigger element - No wrapper elements - Flexible trigger customization
Use cases:
- Icon buttons as triggers - Custom styled buttons - Third-party component integration

Nested

Nested: Demonstrates nested dropdown menus with multiple levels.
Features:
- Multiple levels of nesting - Automatic submenu positioning - Hover-based submenu activation - Tree event management for proper closing - Keyboard navigation across nested levels
Use cases:
- File explorer menus - Complex application menus - Hierarchical command structures

Nested In Popover

NestedInPopover: Demonstrates Dropdown nested inside a Popover or Dialog.
Features:
- Dropdown works within Popover content - Requires disabledNested prop for proper rendering - Prevents nested menu conflicts - Proper event handling in nested contexts
Important:
- When using Dropdown nested inside a Popover or Dialog, you must pass the `disabledNested={true}` prop to ensure proper rendering.

Nested Submenu With Long List

NestedSubmenuWithLongList: Demonstrates scrolling functionality in nested submenus with long lists.
Features:
- First level menu with standard items - Nested submenu with a long list that exceeds screen height - Scroll arrows appear when content exceeds available height - Scrolling works properly in nested menus - Height constraints are properly applied - Multiple nested submenus with long lists
Use cases:
- File explorer with many files/folders - Long category lists in nested menus - Any scenario requiring scrollable nested menus

Selection

Selection: Demonstrates selection functionality with visual indicators.
Features:
- Visual selection indicator (check mark) - Controlled selection state - Selection persists between menu opens - Automatic menu closure on selection
Use cases:
- Radio button-like selection in menus - Theme or preference selection - Single-choice menu scenarios

Nested Selection

NestedSelection: Demonstrates nested dropdown with selection functionality in submenus.
Features:
- Selection works across nested levels - Unified state management for all options - Visual selection indicators in nested menus - Proper selection handling in submenus
Use cases:
- Multi-level preference selection - Hierarchical option selection - Complex configuration menus

Complex Menu

ComplexMenu: Advanced example showing complex menu structure with mixed features.
Features:
- Mixed menu features (labels, dividers, shortcuts) - Nested submenus with selection - Prefix icons - Keyboard shortcuts - Danger variant items
Use cases:
- Application settings menus - Complex preference panels - Feature-rich application menus

Coordinate Mode

CoordinateMode: Demonstrates Dropdown in coordinate mode without a trigger element.
Features:
- No trigger element required - Positioned at specific x/y coordinates - Auto-select first item option - Perfect for context menus and mentions
Use cases:
- Context menus at cursor position - Mention dropdowns in editors - Custom positioned menus - Replaces deprecated CoordinateMenu component

Click anywhere in this area to show dropdown at mouse position

Mentions With Coordinate Mode

MentionsWithCoordinateMode: Demonstrates mentions functionality using coordinate mode with Slate.js editor.
Features:
- Type @ to trigger mentions menu - Dropdown positioned at cursor location - Integration with Slate.js editor - User selection and insertion - Real-time text updates
Use cases:
- Rich text editors with mentions - Comment systems - Collaborative editing features

Current text: “

With Trigger Ref

WithTriggerRef: Demonstrates using triggerRef to bind dropdown to an external element.
Features:
- Attach dropdown to any element via ref - No need for Dropdown.Trigger wrapper - More control over trigger element - Flexible integration with existing components
Use cases:
- Attaching dropdown to existing elements - Third-party component integration - Custom trigger implementations

Using triggerRef

With Trigger Selector

WithTriggerSelector: Demonstrates using triggerSelector (CSS selector) to bind dropdown to an element.
Features:
- Supports any valid CSS selector (#id, .class, [data-*], etc.) - Same functionality as triggerRef - triggerRef takes priority if both are provided
Use cases:
- When you cannot access the element via ref (e.g., third-party components) - When the trigger element is rendered elsewhere in the DOM - When you prefer a simpler, selector-based approach

Using #id selector

Using .class selector

Using [data-*] selector

Empty

Empty: Demonstrates empty state display when no items are available.
Features:
- Show custom empty message when menu has no items - Useful for dynamic menu content scenarios

Selection With Prefix Icons

SelectionWithPrefixIcons: Demonstrates selection functionality with prefix icons.
Features:
- When prefix icons exist, the Check icon appears at the suffix position (right side) - When no prefix icon exists, the Check icon appears at the prefix position (left side) - Maintains proper visual hierarchy and clarity - Works seamlessly with existing selection functionality
Use cases:
- Theme selection with icon indicators - Preference selection with visual cues - Single-choice menus with icons

With Prefix Icons (Check icon on the right)

Notice: When prefix icons exist, the Check icon appears on the right side.

Without Prefix Icons (Check icon on the left)

Notice: When no prefix icons exist, the Check icon appears on the left side (standard behavior).

Mixed: With and Without Icons

Notice: Items with prefix icons show Check on the right, items without show Check on the left.

Avoid Collisions

AvoidCollisions: Demonstrates Dropdown with avoidCollisions set to false.
Features:
- When avoidCollisions is false, the dropdown strictly follows the placement direction - No automatic flipping or shifting to avoid viewport collisions - Useful when you need precise positioning control - May extend beyond viewport boundaries when false
Use cases:
- Custom positioning requirements - When you want dropdown to always appear in a specific direction - Context menus with strict positioning needs

Comparison: avoidCollisions

When avoidCollisions=false, the dropdown will strictly follow the placement direction and may extend beyond the viewport. When avoidCollisions=true (default), it will automatically adjust to stay within the viewport.

avoidCollisions=true (default)

Dropdown will automatically adjust to avoid viewport collisions.

avoidCollisions=false

Dropdown strictly follows placement direction, may extend beyond viewport.

Edge Case: Near Viewport Edges

Positioned near the right edge to demonstrate the difference. Try opening both menus to see the behavior difference.

Different Placements with avoidCollisions=false

API reference

DropdownPropsTypeDefault
autoSelectFirstItem
boolean
|
undefined
true
avoidCollisions
boolean
|
undefined
true
disabledNested
boolean
|
undefined
-
focusManagerProps
Partial<FloatingFocusManagerProps>
|
undefined
-
matchTriggerWidth
boolean
|
undefined
-
offset
number
|
undefined
-
onOpenChange
((open: boolean) => void)
|
undefined
-
open
boolean
|
undefined
-
placement
undefined
|
"top"
|
"right"
|
"bottom"
|
"left"
|
"top-start"
|
"top-end"
|
"right-start"
|
"right-end"
|
"bottom-start"
|
"bottom-end"
|
"left-start"
|
"left-end"
-
portalId
string
|
undefined
-
position
{ x: number; y: number; }
|
null
|
undefined
-
readOnly
boolean
|
undefined
-
root
HTMLElement
|
null
|
undefined
-
selection
boolean
|
undefined
-
triggerRef
RefObject<HTMLElement>
|
undefined
-
triggerSelector
string
|
undefined
-
variant
undefined
|
"default"
|
"light"
|
"reset"
-