Dropdown Menu
by Dax · tsx · 46 lines
A polished dropdown menu with icons, keyboard shortcuts, separators, and a slide-down entrance. Built on Radix so it handles positioning, focus, and keyboard navigation out of the box.
dropdownmenunavigationradix
46 lines
"use client";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
type MenuItem = {
label: string;
icon?: React.ReactNode;
shortcut?: string;
onClick?: () => void;
separator?: boolean;
};
export function Dropdown({ trigger, items }: {
trigger: React.ReactNode;
items: MenuItem[];
}) {
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>{trigger}</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
sideOffset={6}
className="min-w-[180px] rounded-xl border border-neutral-200 bg-white p-1 shadow-xl animate-in fade-in-0 zoom-in-95 slide-in-from-top-2"
>
{items.map((item, i) =>
item.separator ? (
<DropdownMenu.Separator key={i} className="my-1 h-px bg-neutral-100" />
) : (
<DropdownMenu.Item
key={i}
onClick={item.onClick}
className="flex cursor-pointer items-center gap-2 rounded-lg px-3 py-2 text-sm text-neutral-700 outline-none transition hover:bg-neutral-50 focus:bg-neutral-50"
>
{item.icon && <span className="text-neutral-400">{item.icon}</span>}
<span className="flex-1">{item.label}</span>
{item.shortcut && (
<span className="text-xs text-neutral-400">{item.shortcut}</span>
)}
</DropdownMenu.Item>
)
)}
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
);
}