78 views

Building an Autolink Heading Component for React Navigation

Building an Autolink Heading Component for React Navigation

Introduction

In this post, we'll explore how I've created an Autolink Heading component for React Navigation. This component will generate anchor links for section headings automatically. By using this component, you can improve user experience and make navigation within your React applications more efficient. It also contributes to the site SEO performance. Let's explore how to build this component!

This is how I created the first version of the Autolink Heading component to replicate the behavior of rehype-autolink-headings for React headings. It's a simple design that get's the job done. However, I'm sure it has a lot of room for improvement.

import React, {
  cloneElement,
  isValidElement,
  ReactElement,
  ReactNode,
} from "react"
import { slug } from "github-slugger"
 
import { cn } from "@/lib/utils"
 
interface AutoLinkHeadingProps {
  children: ReactNode
  className: string
  linkClassName?: string
  ariaLabel?: string
  headingId?: string
}
 
function isHeadingElement(element: ReactNode): element is ReactElement {
  return (
    isValidElement(element) &&
    typeof element.type === "string" &&
    /^h[1-6]$/.test(element.type)
  )
}
 
export function AutoLinkHeading({
  children,
  className,
  linkClassName = "",
  ariaLabel = "Link to section",
  headingId = "",
}: AutoLinkHeadingProps): JSX.Element | null {
  const firstChild = React.Children.toArray(children)[0]
 
  if (!isHeadingElement(firstChild)) {
    console.warn("AutoLinkHeader: The first child is not a heading element.")
    return null
  }
 
  const firstGrandChild = React.Children.toArray(firstChild.props.children)[0]
 
  if (firstGrandChild === undefined) {
    console.warn(
      "AutoLinkHeader: No text content found for the header element."
    )
    return null
  }
 
  const headerSlug = headingId ? headingId : slug(firstGrandChild.toString())
  const clonedFirstChild = cloneElement(firstChild, {
    className: cn(firstChild.props.className, className),
    id: headerSlug,
    children: (
      <a
        href={`#${headerSlug}`}
        className={linkClassName}
        aria-label={ariaLabel}
      >
        {firstChild.props.children}
      </a>
    ),
  })
  return clonedFirstChild
}
 

Here, we've defined the AutoLinkHeader component that takes children, className, linkClassName, and ariaLabel as props. It checks if the first child is a heading element, and if so, generates a slug based on the text content. It then clones the first child element and adds an anchor link with the generated slug.

I'm using the algorithm from github-slugger to create the header link and ID. It's the same one used by GitHub for their section headings and also by rehype-slug, the project I used as inspiration for this one.

To use the AutoLinkHeader component, follow the example below:

<AutoLinkHeading className="linked_header" linkClassName="link">
  <h2 className="header">All Posts on Next.js</h2>
</AutoLinkHeading>

That transforms the h2 tag in something like this: autolink_headings_html

In the above code snippet, we pass the desired CSS classes to the className and linkClassName props. The h2 element is wrapped inside the AutoLinkHeader component, and it will automatically generate an anchor link based on the heading's text content.

The result looks like this: autolink-headings-example

Converting section headings to link targets using the # symbol offers several benefits:

  1. Improved User Experience: Users can easily navigate to specific sections by clicking on the corresponding links, enhancing their overall experience.
  2. Enhanced Accessibility: Anchor links improve accessibility by allowing users with assistive technologies to navigate the page more efficiently.
  3. Simplified Content Sharing: Linking to specific sections simplifies content sharing, as users can share direct links to relevant sections.
  4. SEO Benefits: Anchor links help search engines understand content structure, improving visibility in search results.

By converting section headings to link targets, you can enhance user experience, accessibility, simplify content sharing, and gain SEO benefits.

Check out the React AutoLink Heading repo.

Conclusion

Autolink Heading component for React Navigation that automatically generates anchor links for section headings. By converting section headings to link targets, we can improve user experience, accessibility, content sharing, and gain SEO benefits. By implementing this component in your React applications, you can enhance navigation and make it easier for users to find the information they need. Happy coding! 🌟