Skip to content

Commit 017667d

Browse files
feat: add external link support in navigation components
1 parent 26d44ca commit 017667d

File tree

6 files changed

+24
-4
lines changed

6 files changed

+24
-4
lines changed

components/Header.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import SearchButton from './SearchButton'
99
import { useTheme } from 'next-themes'
1010
import Image from 'next/image'
1111
import { useEffect, useState } from 'react'
12+
import { ExternalLink } from './social-icons/icons'
1213

1314
const Header = () => {
1415
const { resolvedTheme } = useTheme()
@@ -58,9 +59,12 @@ const Header = () => {
5859
<Link
5960
key={link.title}
6061
href={link.href}
61-
className="hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100"
62+
className="hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100 flex items-center gap-1"
6263
>
6364
{link.title}
65+
{link.external && (
66+
<ExternalLink className="h-3 w-3 text-gray-500 dark:text-gray-400" />
67+
)}
6468
</Link>
6569
))}
6670
</div>

components/Link.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import Link from 'next/link'
33
import type { LinkProps } from 'next/link'
44
import { AnchorHTMLAttributes } from 'react'
55

6-
const CustomLink = ({ href, ...rest }: LinkProps & AnchorHTMLAttributes<HTMLAnchorElement>) => {
6+
const CustomLink = ({ href, external, ...rest }: LinkProps & AnchorHTMLAttributes<HTMLAnchorElement> & { external?: boolean }) => {
77
const isInternalLink = href && href.startsWith('/')
88
const isAnchorLink = href && href.startsWith('#')
9+
const isExternalLink = external || (href && (href.startsWith('http://') || href.startsWith('https://')))
910

1011
if (isInternalLink) {
1112
return <Link className="break-words" href={href} {...rest} />

components/MobileNav.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { disableBodyScroll, enableBodyScroll, clearAllBodyScrollLocks } from 'bo
55
import { Fragment, useState, useEffect, useRef } from 'react'
66
import Link from './Link'
77
import headerNavLinks from '@/data/headerNavLinks'
8+
import { ExternalLink } from './social-icons/icons'
89

910
const MobileNav = () => {
1011
const [navShow, setNavShow] = useState(false)
@@ -76,10 +77,13 @@ const MobileNav = () => {
7677
<Link
7778
key={link.title}
7879
href={link.href}
79-
className="hover:text-primary-500 dark:hover:text-primary-400 mb-4 py-2 pr-4 text-2xl font-bold tracking-widest text-gray-900 outline outline-0 dark:text-gray-100"
80+
className="hover:text-primary-500 dark:hover:text-primary-400 mb-4 py-2 pr-4 text-2xl font-bold tracking-widest text-gray-900 outline outline-0 dark:text-gray-100 flex items-center gap-2"
8081
onClick={onToggleNav}
8182
>
8283
{link.title}
84+
{link.external && (
85+
<ExternalLink className="h-4 w-4 text-gray-500 dark:text-gray-400" />
86+
)}
8387
</Link>
8488
))}
8589
</nav>

components/social-icons/icons.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,15 @@ export function Instagram(svgProps: SVGProps<SVGSVGElement>) {
9494
)
9595
}
9696

97+
export function ExternalLink(svgProps: SVGProps<SVGSVGElement>) {
98+
return (
99+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...svgProps}>
100+
<title>External Link</title>
101+
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14L21 3" />
102+
</svg>
103+
)
104+
}
105+
97106
export function Medium(svgProps: SVGProps<SVGSVGElement>) {
98107
return (
99108
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...svgProps}>

components/social-icons/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
Instagram,
1212
Medium,
1313
Bluesky,
14+
ExternalLink,
1415
} from './icons'
1516

1617
const components = {
@@ -26,6 +27,7 @@ const components = {
2627
instagram: Instagram,
2728
medium: Medium,
2829
bluesky: Bluesky,
30+
externalLink: ExternalLink,
2931
}
3032

3133
type SocialIconProps = {

data/headerNavLinks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const headerNavLinks = [
22
{ href: '/', title: 'Home' },
33
{ href: '/blog', title: 'Blog' },
4-
{ href: '/about', title: 'About' },
4+
// { href: '/about', title: 'About' },
55
{ href: '/tags', title: 'Tags' },
66
{ href: 'https://education.ditectrev.com', title: 'Education', external: true },
77
{ href: 'https://apps.apple.com/app/cloudmaster-swift/id6503601139', title: 'iOS App', external: true },

0 commit comments

Comments
 (0)