Hero Gatsby with Link

Dynamic partiallyActive Link in Gatsby

Gatsby offers you to use activeClassName where you can adjust the style of your link to indicate that a user is "under" that module or section of your page. In other words, it helps people to understand where they are.

<Link
to="/about-me"
className={styles.menuLink}
activeClassName={styles.menuLinkActive}
>
About me
</Link>

Styles defined for styles.menuLinkActive in the example above are then applied and everything is cool. Say, the link is red when a user accesses the/about-me page.

But what if you have a scenario like mine, where the "Blog" link should be active when people access /posts/:title and blog is my homepage as well (path /)? Well, the first thought is about partiallyActive attribute and using it like that:

<Link
to="/"
className={styles.menuLink}
activeClassName={styles.menuLinkActive}
partiallyActive={true}
>
Blog
</Link>

But in that case, it will mean that the "Blog" link is active all the time. / matches every other URL. Fortunately, there is a way to make it more dynamic. Just use a function and fire it immediately. Gatsby's <Link> doesn't support passing a function so we still need to pass a boolean. Hence, the immediately called function.

<Link
to="/"
className={styles.menuLink}
activeClassName={styles.menuLinkActive}
partiallyActive={(() => {
if (typeof window !== 'undefined') {
const pathName = window.location.pathname;
return pathName === '/' || pathName.includes('/posts/');
}
})()}
>
Blog
</Link>

What happens here? We read pathname from the current location and return true when we deal with homepage (/) or the pathname includes /posts.

Please notice the if statement where we check if window object is there. That's needed for building process in Gatsby that happens in non-browser environment. The page is server-rendered so it doesn't have a context of browser when building.
But that's ok. Once, in the browser we will get the context and improve the experience.

It works on my blog, so it should work in your case as well.