Dropdown Component
The Dropdown component is a flexible, fully customizable action menu built for modern applications. It supports icons, separators, danger states, controlled/uncontrolled behavior, and theme-aware styling.
Use items to define menu actions, trigger for the toggle element, and align + width for layout control.
Import Component From Library
1import { Dropdown } from "@neuctra/ui";Dropdown Item Structure
Each entry in items can render a clickable menu item or a separator. Items are rendered as buttons, so use onClick for actions and navigation behavior.
1type DropdownItem = {
2 label?: React.ReactNode;
3 icon?: React.ReactNode;
4 onClick?: () => void;
5 href?: string;
6 danger?: boolean;
7 disabled?: boolean;
8 separator?: boolean;
9 className?: string;
10 style?: React.CSSProperties;
11};Basic Usage Code
Start with a simple dropdown menu. The component supports icons, separators, danger states, and flexible positioning.
1import { Dropdown } from '@neuctra/ui';
2
3function BasicExample() {
4 const items = [
5 { label: "Edit", onClick: () => console.log('Edit clicked') },
6 { label: "Copy", onClick: () => console.log('Copy clicked') },
7 { separator: true },
8 { label: "Delete", danger: true, onClick: () => console.log('Delete clicked') }
9 ];
10
11 return (
12 <Dropdown
13 trigger={<button>Open Menu</button>}
14 items={items}
15 />
16 );
17}Basic Example
Menu Item Options
Each item supports icons, labels, click handlers, disabled state, separators, danger styling, and per-item styling.
1const items = [
2 {
3 label: "Edit",
4 icon: <Edit size={16} />,
5 onClick: handleEdit,
6 },
7 {
8 label: "Duplicate",
9 icon: <Copy size={16} />,
10 onClick: handleDuplicate,
11 },
12 { separator: true },
13 {
14 label: "Delete",
15 icon: <Trash2 size={16} />,
16 danger: true,
17 onClick: handleDelete,
18 },
19 {
20 label: "Disabled",
21 disabled: true,
22 },
23];label: menu item text or React node.icon: optional icon before the label.onClick: action when the item is selected.href: available in the item type, but the current renderer uses buttons; useonClickfor navigation.danger: highlights destructive actions.disabled: disables the item and prevents clicks.separator: renders a divider line between sections.classNameandstyle: customize item styling.
Controlled Dropdown
Use open and onOpenChange when you need explicit visibility control or want to sync the menu state with other UI.
Alignment & Width
Use align to anchor the menu left or right, andwidth to control the panel width.
1<Dropdown
2 trigger={<button>Right aligned</button>}
3 align="right"
4 width={240}
5 items={items}
6/>
7
8<Dropdown
9 trigger={<button>Left aligned</button>}
10 align="left"
11 width={260}
12 items={items}
13/>Close Behavior
By default the dropdown closes when an item is clicked. Use closeOnClick= to keep the menu open.
1<Dropdown
2 trigger={<button>Keep open</button>}
3 closeOnClick={false}
4 items={items}
5/>Styling
Use wrapper, menu, and item class props for shared styling. Use className or style on an individual item when only one action needs custom styling.
1<Dropdown
2 trigger={<button>Styled menu</button>}
3 width={260}
4 className="inline-flex"
5 menuClassName="rounded-xl"
6 itemClassName="font-medium"
7 menuStyle={{ padding: 4 }}
8 items={[
9 { label: "Edit", icon: <Edit size={16} /> },
10 {
11 label: "Custom item",
12 className: "text-primary",
13 style: { letterSpacing: 0 },
14 },
15 ]}
16/>Props Table
| Prop | Type | Default | Description |
|---|---|---|---|
| trigger | React.ReactNode | — | Element that toggles dropdown. |
| items | DropdownItem[] | — | Array of action items or separator entries. |
| open | boolean | — | Controlled open state. |
| onOpenChange | (open: boolean) => void | — | Triggered when state changes. |
| align | "left" | "right" | "right" | Menu alignment. |
| width | number | 220 | Dropdown menu width in pixels. |
| closeOnClick | boolean | true | Close dropdown when item is clicked. |
| className | string | — | Wrapper styling for the trigger container. |
| menuClassName | string | — | Dropdown container styling. |
| itemClassName | string | — | Item styling for every menu entry. |
| triggerClassName | string | — | Styles the wrapper around the trigger node. |
| menuListClassName | string | — | Styles the inner role="menu" list container. |
| separatorClassName | string | — | Styles each separator row between items. |
| itemIconClassName | string | — | Styles an item's leading icon wrapper. |
| itemLabelClassName | string | — | Styles an item's label text. |
| style | CSSProperties | — | Inline styles for the wrapper. |
| menuStyle | CSSProperties | — | Inline styles for the dropdown menu panel. |
Common Mistakes
<Dropdown items={{}} />items must be an array, not an object
<Dropdown trigger='Open' />A string is allowed, but a button-like element gives users a clearer interactive target.
{ label: "Docs", href: "/docs" }Items render as buttons, so use onClick for navigation behavior.
<button onClick={(e) => e.stopPropagation()}>Never call e.stopPropagation() in the trigger's own onClick — Dropdown already stops propagation on its wrapper, and doing it again in the trigger prevents that wrapper handler from running, so the menu never opens.
<Dropdown align="left" />Use align prop for positioning instead of hacks
Pro Tips
- Use
separatorto visually group actions. - Use
dangerfor destructive actions like delete. - Combine Dropdown with your
Buttoncomponent for consistent UI. - Use controlled mode (
open) for advanced flows. - Keep item labels short and action-focused.
Frequently Asked Questions
How do I install and import the Dropdown component?
Install the @neuctra/ui package, then import it with: import { Dropdown } from "@neuctra/ui";
Can I customize the Dropdown component's appearance?
Yes. Dropdown accepts a className prop for custom Tailwind CSS classes, so you can adjust spacing, layout, and styling without overriding the component internals.
Is the Dropdown component accessible?
Dropdown is built with semantic HTML and standard ARIA attributes, and supports keyboard navigation and focus states out of the box, so it works well with screen readers and keyboard-only users.