2024-09-06 Web Development

Making a Custom Link Component for External Navigation

By O. Wolfson

Opening a link in a new browser tab is useful in many scenarios, such as when linking to external sites. This approach allows users to return to your site easily by switching tabs or closing the new window, instead of relying on the back button. It's a better user experience, especially when you don’t want users to navigate away from your site.

Example of an internal link that opens in the same tab.

Example of an external link that opens in a new tab.

However, MDX doesn’t support HTML attributes like target="_blank" directly in Markdown syntax. By default, links created with standard Markdown syntax in MDX won’t open in a new tab. To overcome this limitation, you can create a custom link component that automatically opens external links in a new tab while keeping internal links within the same tab.

Here’s how to create a custom link component for MDX that ensures external links open in a new tab.

1. Create a Custom Link Component

The first step is to create a custom Link component. This component will check whether a link is internal (same tab) or external (new tab) and apply the necessary attributes accordingly.

Create a new file called custom-link.tsx in your components directory:

tsx
import type React from "react";
import Link from "next/link";

const CustomLink = ({
  href,
  children,
}: {
  href: string;
  children: React.ReactNode;
}) => {
  // Automatically determine if the link is external based on the href value
  const isExternalLink = href.startsWith("http");

  if (isExternalLink) {
    return (
      <a
        href={href}
        target="_blank"
        rel="noopener noreferrer"
        className="hover:underline font-semibold"
      >
        {children}
      </a>
    );
  }

  // For internal links, use Next.js' `Link` component
  return (
    <Link href={href} className="hover:underline font-semibold">
      {children}
    </Link>
  );
};

export default CustomLink;

This component performs two key tasks:

  • External Links: If the URL starts with http (or ext is manually set to true), it will render an anchor (<a>) tag with target="_blank" and rel="noopener noreferrer" to ensure the link opens in a new tab securely.
  • Internal Links: For internal navigation, it uses the Next.js Link component, enabling client-side routing for faster page transitions.

2. Define the MDX Components in Your Project

Next, you’ll need to tell MDX to use this custom Link component whenever it encounters a link in your Markdown content.

In your mdx-components.tsx file, map the default anchor (<a>) element to the CustomLink component:

tsx
import React from "react";
import type { AnchorHTMLAttributes, DetailedHTMLProps } from "react";
import type { MDXComponents } from "mdx/types";
import CustomLink from "@/components/mdx/custom-link"; // Adjust the import path

export function useMDXComponents(components: MDXComponents): MDXComponents {
  return {
    ...components,
    a: ({ href = "", children, ...rest }) => {
      // Use the CustomLink component to handle external/internal links
      return <CustomLink href={href}>{children}</CustomLink>;
    },
  };
}

This ensures that every link in your MDX content will use the CustomLink component instead of the default HTML <a> tag. External links will open in a new tab, while internal links will use Next.js' Link component for faster client-side navigation.

3. Use the Custom Link Component in MDX Content

Now that you’ve set up the custom link component, you can use normal Markdown syntax in your MDX documents without needing to worry about manually adding target="_blank".

For example, you can write links like this in your MDX content:

mdx
# My Blog

[Open this link in the same tab.](/blog)

[Open this link in a new tab.](https://github.com/owolfdev/mdx-blog)
  • Internal Link: [Open this link in the same tab.](/blog) will use the Next.js Link component and keep the navigation within the same tab.
  • External Link: [Open this link in a new tab.](https://github.com/owolfdev/mdx-blog) will open in a new tab, using the custom CustomLink component that renders an anchor tag with target="_blank".

Conclusion

By creating a custom Link component, you can now ensure that external links in your MDX documents automatically open in a new tab while internal links benefit from Next.js client-side routing. This approach improves user experience by maintaining control over how links behave, without needing to modify your Markdown syntax for each link.