38 lines · 1.3 KB
import { forwardRef } from "react";
import { createLink, type LinkComponent } from "@tanstack/react-router";
import { cn } from "~/utils/cn";

type LinkTone = "accent" | "subtle" | "success";

const LINK_TONES: Record<LinkTone, string> = {
  accent: "text-kumo-link",
  subtle: "text-kumo-default",
  success: "text-kumo-success",
};

type StyleProps = { tone?: LinkTone; mono?: boolean; className?: string };

export function textLinkClass({ tone = "accent", mono = false, className }: StyleProps = {}): string {
  return cn("underline-offset-2 hover:underline", LINK_TONES[tone], mono && "font-mono", className);
}

type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement> & StyleProps;

/** Plain `<a>` for external or raw URLs. Use `TextLink` for in-app routes. */
export const ExternalLink = forwardRef<HTMLAnchorElement, AnchorProps>(function ExternalLink(
  { tone, mono, className, children, ...rest },
  ref,
) {
  return (
    <a ref={ref} className={textLinkClass({ tone, mono, className })} {...rest}>
      {children}
    </a>
  );
});
ExternalLink.displayName = "ExternalLink";

const RouterTextLink = createLink(ExternalLink);

/** Type-safe router link with the standard text-link treatment. */
export const TextLink: LinkComponent<typeof ExternalLink> = (props) => <RouterTextLink {...props} />;