{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "split-button-action", "dependencies": [ "lucide-react" ], "registryDependencies": [ "button", "dropdown-menu", "https://reusables.vercel.app/r/utils.json" ], "files": [ { "path": "registry/reusables/ui/split-button-action.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronDown, Loader2 } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button, ButtonProps } from \"@/components/ui/button\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\n\nexport interface SplitButtonOption {\n label: string\n onClick: () => void\n icon?: React.ReactNode\n variant?: \"default\" | \"destructive\"\n}\n\ninterface SplitButtonProps extends React.ButtonHTMLAttributes {\n options: SplitButtonOption[]\n mainAction: () => void\n variant?: ButtonProps[\"variant\"]\n size?: ButtonProps[\"size\"]\n dropdownAlign?: \"start\" | \"center\" | \"end\"\n icon?: React.ReactNode\n isLoading?: boolean\n glassMorphism?: boolean\n}\n\nexport default function SplitButtonAction({\n children,\n options,\n mainAction,\n variant = \"default\",\n size = \"default\",\n dropdownAlign = \"end\",\n className,\n icon,\n isLoading,\n glassMorphism,\n ...props\n}: SplitButtonProps) {\n const [isOpen, setIsOpen] = React.useState(false)\n\n const baseClassName = cn(\n \"relative transition-all duration-200\",\n glassMorphism && \"shadow-lg backdrop-blur-sm backdrop-saturate-150\",\n className\n )\n\n const buttonClassName = cn(\n \"rounded-r-none\",\n \"hover:translate-y-[-1px]\",\n \"active:translate-y-[1px]\",\n \"transition-all duration-200\",\n glassMorphism && \"backdrop-blur-sm backdrop-saturate-150\"\n )\n\n const dropdownTriggerClassName = cn(\n \"rounded-l-none\",\n \"border-l\",\n \"px-2\",\n \"hover:translate-y-[-1px]\",\n \"active:translate-y-[1px]\",\n \"transition-all duration-200\",\n variant === \"default\" && \"border-primary-foreground/20\",\n variant === \"destructive\" && \"border-destructive-foreground/20\",\n variant === \"outline\" && \"border-input\",\n variant === \"secondary\" && \"border-secondary-foreground/20\",\n glassMorphism && \"backdrop-blur-sm backdrop-saturate-150\"\n )\n\n return (\n
\n
\n {\n e?.preventDefault()\n mainAction()\n }}\n disabled={isLoading}\n {...props}\n >\n {isLoading ?\n <>\n \n Loading...\n \n : <>\n {icon && {icon}}\n {children}\n \n }\n \n \n \n \n \n \n \n \n {options.map((option, index) => (\n \n {\n e?.preventDefault()\n option.onClick()\n setIsOpen(false)\n }}\n className=\"flex cursor-pointer items-center gap-2 transition-colors duration-200\"\n >\n {option.icon && (\n {option.icon}\n )}\n {option.label}\n \n {index < options.length - 1 && }\n \n ))}\n \n \n
\n
\n )\n}\n", "type": "registry:ui", "target": "components/ui/split-button-action.tsx" } ], "type": "registry:ui" }