1import { createLink, type LinkComponent } from "@tanstack/react-router";
2import type { VariantProps } from "class-variance-authority";
3import * as React from "react";
4
5import { cn } from "@/lib/utils";
6
7import { buttonVariants } from "./button";
8
9// A proper TanStack Router link that looks like a Button.
10// Replaces the `<Button asChild><Link …/></Button>` pattern,
11// giving us preloading, typed routes, and active link support.
12interface ButtonLinkProps extends VariantProps<typeof buttonVariants> {
13 className?: string;
14 children?: React.ReactNode;
15}
16
17const ButtonLinkComponent = React.forwardRef<
18 HTMLAnchorElement,
19 ButtonLinkProps & React.AnchorHTMLAttributes<HTMLAnchorElement>
20>(({ className, variant, size, children, ...props }, ref) => {
21 return (
22 <a ref={ref} className={cn(buttonVariants({ variant, size, className }))} {...props}>
23 {children}
24 </a>
25 );
26});
27ButtonLinkComponent.displayName = "ButtonLinkComponent";
28
29const CreatedButtonLink = createLink(ButtonLinkComponent);
30
31export const ButtonLink: LinkComponent<typeof ButtonLinkComponent> = (props) => {
32 return <CreatedButtonLink preload="intent" {...props} />;
33};
34
35// A nav link that uses activeProps/inactiveProps for styling.
36// Replaces the manual useMatchRoute() pattern in the header.
37const NavLinkComponent = React.forwardRef<
38 HTMLAnchorElement,
39 React.AnchorHTMLAttributes<HTMLAnchorElement>
40>(({ children, ...props }, ref) => {
41 return (
42 <a ref={ref} {...props}>
43 {children}
44 </a>
45 );
46});
47NavLinkComponent.displayName = "NavLinkComponent";
48
49const CreatedNavLink = createLink(NavLinkComponent);
50
51export const NavLink: LinkComponent<typeof NavLinkComponent> = (props) => {
52 return (
53 <CreatedNavLink
54 preload="intent"
55 className="text-muted-foreground hover:bg-accent hover:text-accent-foreground rounded-md px-3 py-1.5 text-sm font-medium transition-colors"
56 activeProps={{ className: "bg-accent text-accent-foreground" }}
57 inactiveProps={{
58 className: "text-muted-foreground hover:bg-accent hover:text-accent-foreground",
59 }}
60 {...props}
61 />
62 );
63};