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

javascript
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.

tsx
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.

jsx
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.

jsx
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; use onClick for navigation.
  • danger: highlights destructive actions.
  • disabled: disables the item and prevents clicks.
  • separator: renders a divider line between sections.
  • className and style: 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.

jsx
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.

jsx
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.

jsx
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

PropTypeDefaultDescription
triggerReact.ReactNode—Element that toggles dropdown.
itemsDropdownItem[]—Array of action items or separator entries.
openboolean—Controlled open state.
onOpenChange(open: boolean) => void—Triggered when state changes.
align"left" | "right""right"Menu alignment.
widthnumber220Dropdown menu width in pixels.
closeOnClickbooleantrueClose dropdown when item is clicked.
classNamestring—Wrapper styling for the trigger container.
menuClassNamestring—Dropdown container styling.
itemClassNamestring—Item styling for every menu entry.
triggerClassNamestring—Styles the wrapper around the trigger node.
menuListClassNamestring—Styles the inner role="menu" list container.
separatorClassNamestring—Styles each separator row between items.
itemIconClassNamestring—Styles an item's leading icon wrapper.
itemLabelClassNamestring—Styles an item's label text.
styleCSSProperties—Inline styles for the wrapper.
menuStyleCSSProperties—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 separator to visually group actions.
  • Use danger for destructive actions like delete.
  • Combine Dropdown with your Button component 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.

Built with React, Tailwind CSS & TypeScript.