|
| 1 | +import { Slot } from "@radix-ui/react-slot"; |
| 2 | +import { type VariantProps, cva } from "class-variance-authority"; |
| 3 | +import { SquareArrowOutUpRightIcon } from "lucide-react"; |
| 4 | +import { forwardRef } from "react"; |
| 5 | +import { cn } from "utils/cn"; |
| 6 | + |
| 7 | +export const linkVariants = cva( |
| 8 | + `relative inline-flex items-center no-underline font-medium text-content-link hover:cursor-pointer |
| 9 | + after:hover:content-[''] after:hover:absolute after:hover:left-0 after:hover:w-full after:hover:h-[1px] after:hover:bg-current after:hover:bottom-px |
| 10 | + focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-content-link |
| 11 | + focus-visible:ring-offset-2 focus-visible:ring-offset-surface-primary focus-visible:rounded-sm |
| 12 | + visited:text-content-link pl-[2px]`, //pl-[2px] adjusts the underline spacing to align with the icon on the right. |
| 13 | + { |
| 14 | + variants: { |
| 15 | + size: { |
| 16 | + lg: "text-sm gap-[2px] [&_svg]:size-icon-sm [&_svg]:p-[2px] leading-6", |
| 17 | + sm: "text-xs gap-1 [&_svg]:size-icon-xs [&_svg]:p-[1px] leading-[18px]", |
| 18 | + }, |
| 19 | + }, |
| 20 | + defaultVariants: { |
| 21 | + size: "lg", |
| 22 | + }, |
| 23 | + }, |
| 24 | +); |
| 25 | + |
| 26 | +export interface LinkProps |
| 27 | + extends React.AnchorHTMLAttributes<HTMLAnchorElement>, |
| 28 | + VariantProps<typeof linkVariants> { |
| 29 | + asChild?: boolean; |
| 30 | +} |
| 31 | + |
| 32 | +export const Link = forwardRef<HTMLAnchorElement, LinkProps>( |
| 33 | + ({ className, children, size, asChild, ...props }, ref) => { |
| 34 | + const Comp = asChild ? Slot : "a"; |
| 35 | + return ( |
| 36 | + <Comp |
| 37 | + className={cn(linkVariants({ size }), className)} |
| 38 | + ref={ref} |
| 39 | + {...props} |
| 40 | + > |
| 41 | + {children} |
| 42 | + <SquareArrowOutUpRightIcon aria-hidden="true" /> |
| 43 | + </Comp> |
| 44 | + ); |
| 45 | + }, |
| 46 | +); |
0 commit comments