Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to gatsby-link for matching active when on child routes #7208

Closed
madeleineostoja opened this issue Aug 10, 2018 · 10 comments · Fixed by #12495
Closed

Add option to gatsby-link for matching active when on child routes #7208

madeleineostoja opened this issue Aug 10, 2018 · 10 comments · Fixed by #12495

Comments

@madeleineostoja
Copy link

madeleineostoja commented Aug 10, 2018

Summary

Would be great to mirror reach router's isCurrent and isPartiallyCurrent options to gatsby-links activeStyle and activeClassname props. Basically I'd want to be able to designate a Link as active when any child routes are also active, without having to bypass gatbsy-link and use isPartiallyCurrent directly.

Basic example

Hesitant to suggest just tacking on another prop as lazy DX, but that would probably make the most sense. Something like this:

<Link ... activeStyle={{...}} greedyActive={true} />

Would default to false, so non-breaking change that doesn't really add much cognitive overhead for people.

Motivation

Common use-case is top-level nav for any nested content (eg: a blog), where you'd often want to designate the nav item active (eg: 'Blog') when on a child path (eg: /blog/some-post).

If this isn't added, would at least be worth documenting how to achieve by accessing react router APIs directly in gatsby-link docs, as I imagine it's a common pattern.

@madeleineostoja madeleineostoja changed the title Add option to gatsby-link for matching active to child routes Add option to gatsby-link for matching active on child routes Aug 10, 2018
@madeleineostoja madeleineostoja changed the title Add option to gatsby-link for matching active on child routes Add option to gatsby-link for matching active when on child routes Aug 10, 2018
@pojntfx
Copy link

pojntfx commented Aug 25, 2018

👍 as well. Until then, the following polyfill might help someone:

const isPartiallyActive = ({ isPartiallyCurrent }) =>
  isPartiallyCurrent ? { className: "item active" } : null;
<div 
  class="item"
  activeClassName={link === "/" ? "active" : undefined}
  getProps={link === "/" ? undefined : isPartiallyActive}
/>

This checks whether the link links to the root level (and thus should not be have the active class applied on child routes, but only if it is actually the current page) and if it is not, it sets className to item active.

More info is in the reach router docs. See https://gitlab.com/libresat/libresat/tree/master/packages/site for an example (blog posts).

@madeleineostoja
Copy link
Author

@KyleAMathews would you accept a PR for this feature?

@janosh
Copy link
Contributor

janosh commented Dec 5, 2018

greedyActive should definitely be the default. In the vast majority of cases, you want child routes to "activate" their parents. I'm surprised this isn't implemented already.

@KyleAMathews
Copy link
Contributor

@ryanflorence any thoughts here?

@janosh
Copy link
Contributor

janosh commented Dec 15, 2018

@KyleAMathews If @seaneking is willing to provide a PR for this feature, I think that's great. Couldn't gatsby-link implement this feature irrespective of Reach Router?

If you're worried about changing the default behavior for everyone, maybe we could add a global option to gatsby-config? Something like

module.exports = {
  siteMetadata: {
    ...
  },
  plugins: [
    ...
  ],
  settings: {
    gatsby-link: {
      greedyActive: true,
    }
  }
}

@wllkle
Copy link

wllkle commented Jan 10, 2019

👍 as well. Until then, the following polyfill might help someone:

const isPartiallyActive = ({ isPartiallyCurrent }) =>
  isPartiallyCurrent ? { className: "item active" } : null;
<div 
  class="item"
  activeClassName={link === "/" ? "active" : undefined}
  getProps={link === "/" ? undefined : isPartiallyActive}
/>

This checks whether the link links to the root level (and thus should not be have the active class applied on child routes, but only if it is actually the current page) and if it is not, it sets className to item active.

More info is in the reach router docs. See https://gitlab.com/libresat/libresat/tree/master/packages/site for an example (blog posts).

Hi there, if at all possible would you have an example using this? I'm having problems implementing this functionality. Thanks!

@janosh
Copy link
Contributor

janosh commented Jan 10, 2019

@wllkle This is how I am using it.

import React from 'react'
import { Link } from 'gatsby'

const partlyActive = className => ({ isPartiallyCurrent }) => ({
  className: className + (isPartiallyCurrent ? ` active` : ``),
})

const PartlyActiveLink = ({ className, ...rest }) => (
  <Link getProps={partlyActive(className)} {...rest} />
)

In my case, the actual styles are then coming from a styled-component.

import styled from 'styled-components'

const NavLink = styled(PartlyActiveLink)`
  color: ${props => props.theme.lightBlue};
  transition: ${props => props.theme.shortTrans};
  cursor: pointer;
  &.active {
    color: ${props => props.theme.darkYellow};
  }
  :hover {
    color: ${props => props.theme.lightGreen};
  }
`

@gatsbot gatsbot bot added the stale? Issue that may be closed soon due to the original author not responding any more. label Feb 13, 2019
@gatsbot
Copy link

gatsbot bot commented Feb 13, 2019

Hiya!

This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

Thanks for being a part of the Gatsby community! 💪💜

@madeleineostoja
Copy link
Author

Think we should keep this open, until it's clarified either way whether from the team whether this should feature be included in gatsby-link or not (I vote yes, FWIW).

Tbh I think this should be the default behaviour, with an opt-out flag instead. But that would be a breaking change so fair enough if it's added as an opt-in feature instead.

@gatsbot gatsbot bot closed this as completed Feb 25, 2019
@gatsbyjs gatsbyjs deleted a comment from gatsbot bot Feb 25, 2019
@janosh janosh reopened this Feb 25, 2019
@gatsbot gatsbot bot closed this as completed Mar 8, 2019
@janosh janosh added not stale and removed stale? Issue that may be closed soon due to the original author not responding any more. labels Mar 8, 2019
@janosh janosh reopened this Mar 8, 2019
@gatsbyjs gatsbyjs deleted a comment from gatsbot bot Mar 8, 2019
@arcanis
Copy link
Contributor

arcanis commented Mar 11, 2019

I've opened a PR, in case someone actually implementing it was all that was needed 😛 (#12495)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants