| import { cloneElement, isValidElement } from 'react' |
| import * as DropdownMenu from '@radix-ui/react-dropdown-menu' |
| import clsx from 'clsx' |
|
|
| export default function Dropdown({ |
| trigger, |
| items = [], |
| align = 'end', |
| contentClassName, |
| disabled = false, |
| }) { |
| const triggerNode = |
| isValidElement(trigger) && disabled |
| ? cloneElement(trigger, { |
| disabled: true, |
| 'aria-disabled': true, |
| }) |
| : trigger |
|
|
| return ( |
| <DropdownMenu.Root> |
| <DropdownMenu.Trigger asChild disabled={disabled}> |
| {triggerNode} |
| </DropdownMenu.Trigger> |
| <DropdownMenu.Portal> |
| <DropdownMenu.Content |
| align={align} |
| sideOffset={8} |
| className={clsx( |
| 'z-50 min-w-[12rem] rounded-lg border border-border bg-card p-1 shadow-panel', |
| contentClassName, |
| )} |
| > |
| {items.map((item) => { |
| if (item.type === 'separator') { |
| return <DropdownMenu.Separator key={item.key} className="my-1 h-px bg-border/80" /> |
| } |
| |
| const Icon = item.icon |
| return ( |
| <DropdownMenu.Item |
| key={item.key} |
| disabled={item.disabled} |
| onSelect={item.onSelect} |
| className={clsx( |
| 'flex cursor-pointer select-none items-center gap-2 rounded-md px-3 py-2 text-sm outline-none transition data-[disabled]:pointer-events-none data-[disabled]:opacity-40', |
| item.destructive |
| ? 'text-danger focus:bg-danger/10' |
| : 'text-foreground focus:bg-secondary', |
| )} |
| > |
| {Icon ? <Icon className="h-4 w-4" /> : null} |
| <span className="flex-1">{item.label}</span> |
| </DropdownMenu.Item> |
| ) |
| })} |
| </DropdownMenu.Content> |
| </DropdownMenu.Portal> |
| </DropdownMenu.Root> |
| ) |
| } |
|
|