88 lines
2.0 KiB
TypeScript
88 lines
2.0 KiB
TypeScript
import Link from "next/link";
|
|
import { ArrowRight, ExternalLink, type LucideIcon } from "lucide-react";
|
|
import React, { createElement } from "react";
|
|
import { Button } from "./ui/button";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
export default function LinkButton({
|
|
text,
|
|
linkData,
|
|
variant = "default",
|
|
radius = "sm",
|
|
size = "default",
|
|
extraIcon,
|
|
showIcon = true,
|
|
className,
|
|
onPress,
|
|
...props
|
|
}: {
|
|
text: string;
|
|
linkData: { href: string; target: string } | null;
|
|
variant?:
|
|
| "ghost"
|
|
| "default"
|
|
| "secondary"
|
|
| "link"
|
|
| "destructive"
|
|
| "outline";
|
|
size?: "default" | "sm" | "lg" | "icon";
|
|
extraIcon?: LucideIcon;
|
|
showIcon?: boolean;
|
|
className?: string;
|
|
onPress?: () => void;
|
|
[key: string]: any;
|
|
}) {
|
|
const isExternal = linkData?.href?.startsWith("http");
|
|
|
|
return (
|
|
<Button
|
|
asChild
|
|
variant={variant}
|
|
size={size}
|
|
rel={isExternal ? "noopener noreferrer" : undefined}
|
|
onClick={onPress}
|
|
className={cn(
|
|
className,
|
|
`
|
|
group
|
|
rounded-full
|
|
font-semibold
|
|
transition-all
|
|
duration-300
|
|
no-underline
|
|
flex
|
|
items-center
|
|
gap-2
|
|
${showIcon ? "pr-4" : "px-6"}
|
|
active:transform
|
|
active:translate-y-[1px]
|
|
`
|
|
)}
|
|
{...props}
|
|
>
|
|
<Link
|
|
href={linkData?.href ?? ""}
|
|
target={linkData?.target ?? "_self"}
|
|
>
|
|
{extraIcon && (
|
|
<span className="transition-transform duration-300 group-hover:scale-110">
|
|
{createElement(extraIcon, { size: size === "lg" ? 24 : 20 })}
|
|
</span>
|
|
)}
|
|
|
|
<span>{text}</span>
|
|
|
|
{showIcon && (
|
|
<span className="transition-all duration-300 group-hover:transform group-hover:translate-x-1">
|
|
{isExternal ? (
|
|
<ExternalLink size={size === "lg" ? 24 : 20} />
|
|
) : (
|
|
<ArrowRight strokeWidth={3} size={size === "lg" ? 24 : 20} />
|
|
)}
|
|
</span>
|
|
)}
|
|
</Link>
|
|
</Button>
|
|
);
|
|
}
|