DropdownMenu.
Actions that stay out of the way.
Live preview
import { DropdownMenu, Button } from "luminescent";
import "luminescent/style.css";
export function Example() {
return (
<DropdownMenu
trigger={<Button variant="secondary">Project actions</Button>}
items={[
{ id: "duplicate", label: "Duplicate", onSelect: () => {} },
{ id: "archive", label: "Archive", disabled: true },
{ id: "delete", label: "Delete", destructive: true },
]}
/>
);
}
Installation
npm install luminescent
Import luminescent/style.css once at your application root. The example above uses the same package implementation as Storybook.
Variants and states
Use the preview controls to explore the supported variants, sizes, disabled/loading states and reduced motion. Controls appear only where the component exposes the corresponding prop. Theme and glow apply to every component.
Controlled and uncontrolled state
State contract: open / defaultOpen / onOpenChange. Omit the controlled prop to let the component own its initial state; supply a value and callback when your application owns it. Native uncontrolled fields and state-backed form controls participate in form reset. Controlled state must be reset by the application.
import { useState } from "react";
import { DropdownMenu, Button } from "luminescent";
export function ControlledExample() {
const [value, setValue] = useState(false);
return (
<DropdownMenu
open={value}
onOpenChange={setValue}
trigger={<Button>Actions</Button>}
items={[{ id: "copy", label: "Copy", onSelect: () => {} }]}
/>
);
}
API reference
Generated from the source TypeScript interfaces. Native attributes, className, style, aria-* and data-* also pass through to the documented element. Import DropdownMenuProps from the package for the full inherited contract.
| Prop | Type | Details |
|---|---|---|
triggerrequired | React.ReactElement | Optional unless marked required. |
itemsrequired | DropdownMenuItem[] | Optional unless marked required. |
label | string | Optional unless marked required. |
open | boolean | Optional unless marked required. |
defaultOpen | boolean | Optional unless marked required. |
onOpenChange | (open: boolean) => void | Optional unless marked required. |
onAction | (id: string) => void | Optional unless marked required. |
Accessibility and keyboard
Radix menu: Enter/Space/ArrowDown opens, arrows and Home/End move, typing searches, Escape closes/restores focus. Disabled items are skipped. Use href for navigation and onSelect for actions. Does not expose nested/checkbox/radio menu items.
Keep labels meaningful and test application-level contrast, focus order and screen-reader output. See the accessibility guide for composition requirements.
Theme customization
import { LuminescentProvider, DropdownMenu, Button } from "luminescent";
import "luminescent/style.css";
export function Example() {
return (
<LuminescentProvider theme="light" accent="violet" glow="subtle">
<DropdownMenu
trigger={<Button variant="secondary">Project actions</Button>}
items={[
{ id: "duplicate", label: "Duplicate", onSelect: () => {} },
{ id: "archive", label: "Archive", disabled: true },
{ id: "delete", label: "Delete", destructive: true },
]}
/>
</LuminescentProvider>
);
}
Switch between light and dark in the preview, or open the playground for a larger workspace. Custom CSS variables can override spacing, color, typography and effects.