import { DropdownMenu as KDropdownMenu } from "@kobalte/core/dropdown-menu"; import { splitProps, type JSX, For, Show } from "solid-js"; import { tv } from "tailwind-variants"; import { ChevronRight } from "lucide-solid"; // TODO Dropdown Menu 样式 const menuStyles = tv( { slots: { trigger: "inline-block cursor-pointer", content: [ "z-50 min-w-[8rem] overflow-hidden rounded-md border border-light bg-white p-1 text-zinc-950 shadow-md animate-in zoom-in-95 dark:bg-zinc-950 dark:text-zinc-50", "data-[expanded]:animate-in data-[closed]:animate-out", ], item: "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[highlighted]:bg-zinc-100 data-[highlighted]:text-zinc-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:data-[highlighted]:bg-zinc-800 dark:data-[highlighted]:text-zinc-50", separator: "-mx-1 my-1 h-px border-light", subIcon: "ml-auto h-4 w-4", }, }, { twMerge: true, }, ); const { content, item, separator, subIcon, trigger } = menuStyles(); // 定义菜单项配置类型 export type DropdownItemConfig = { label: string; onClick?: () => void; disabled?: boolean; separator?: boolean; // 是否作为分隔线 children?: DropdownItemConfig[]; // 子菜单 }; interface DropdownMenuProps { trigger: JSX.Element; items: DropdownItemConfig[]; placement?: | "bottom" | "bottom-start" | "bottom-end" | "top" | "left" | "right"; class?: string; } // 递归渲染函数:处理无限级嵌套 const RenderMenuItems = (props: { items: DropdownItemConfig[] }) => { return ( {(config) => ( } > 0} fallback={ config.onClick?.()} > {config.label} } > {/* 子菜单渲染逻辑 */} {config.label} )} ); }; export const DropdownMenu = (props: DropdownMenuProps) => { const [local] = splitProps(props, [ "trigger", "items", "placement", "class", ]); return ( {local.trigger} ); };