-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathlink.tsx
More file actions
75 lines (68 loc) · 1.87 KB
/
link.tsx
File metadata and controls
75 lines (68 loc) · 1.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import * as React from 'react'
import NextLink from 'next/link'
import type { Route } from 'next'
import { Slot } from '@radix-ui/react-slot'
import { cn } from '@/lib/utils'
import type { UrlObject } from 'url'
export interface LinkProps extends Omit<
React.AnchorHTMLAttributes<HTMLAnchorElement>,
'href'
> {
href: string | UrlObject
variant?: 'default' | 'muted' | 'underline' | 'nav'
external?: boolean
asChild?: boolean
}
const linkVariants = {
default: 'text-primary hover:underline underline-offset-4',
muted: 'text-muted-foreground hover:text-foreground transition-colors',
underline:
'underline underline-offset-4 hover:text-primary transition-colors',
nav: 'text-muted-foreground hover:text-foreground transition-colors font-medium',
}
export function Link({
href,
variant = 'default',
external,
asChild,
className,
children,
...props
}: LinkProps) {
const hrefString = typeof href === 'string' ? href : (href.href ?? '')
const isExternal =
external || hrefString.startsWith('http') || hrefString.startsWith('//')
const Comp = asChild ? Slot : isExternal ? 'a' : NextLink
const externalProps = isExternal
? { target: '_blank', rel: 'noopener noreferrer' }
: {}
return (
<Comp
href={href as Route}
className={cn(linkVariants[variant], className)}
{...externalProps}
{...props}
>
{children}
</Comp>
)
}
export interface NavLinkProps extends Omit<LinkProps, 'variant'> {
active?: boolean
}
export function NavLink({
active,
className,
children,
...props
}: NavLinkProps) {
return (
<Link
variant="nav"
className={cn(active && 'text-foreground', className)}
{...props}
>
{children}
</Link>
)
}