2

Trying to style a parent div for a child's Link if the Link has the applied aria-current="page" or an active class name.

code (stripped):

<NavBody>
  {items.map((subItem, key) => {
    const { title, link } = subItem
    return (
      <NavLinkContainer key={key}>
        <NavLink
          onClick={closeMobileMenu}
          to={`/docs${link}`}
          activeClassName="active"
        >
          {title}
        </NavLink>
      </NavLinkContainer>
    )
  })}
</NavBody>

Styled Components:

const NavBody = styled(Accordion.Body)`
  margin-left: ${({ theme }) => theme.spacings.small};
  padding: 0 !important;
`

const NavLinkContainer = styled.div`
  padding-top: ${({ theme }) => theme.spacings.xSmall};
  padding-bottom: ${({ theme }) => theme.spacings.xSmall};
  border-left: 1px solid ${({ theme }) => theme.colors.color7};
  padding-left: ${({ theme }) => theme.spacings.small} !important;
`

const NavLink = styled(Link)`
  color: ${({ theme }) => theme.colors.color3};
  text-decoration: none;
  padding-bottom: ${({ theme }) => theme.spacings.xxSmall};

  &.active {
    color: ${({ theme }) => theme.colors.color1};
  }

  &:hover {
    color: inherit;
    opacity: 0.7;
    text-decoration: none;
    border-bottom: 1px solid ${({ theme }) => theme.colors.color1};
  }
`

I tried:

const NavLinkContainer = styled.div`
  padding-top: ${({ theme }) => theme.spacings.xSmall};
  padding-bottom: ${({ theme }) => theme.spacings.xSmall};
  border-left: 1px solid ${({ theme }) => theme.colors.color7};
  padding-left: ${({ theme }) => theme.spacings.small} !important;

  &.active {
    border-left: 1px solid ${({ theme }) => theme.colors.color1};
  }
`

but that's incorrectly applied due to the padding-left. Another attempt:

<NavBody>
  {items.map((subItem, key) => {
    const { title, link } = subItem
    return (
      <NavLinkContainer key={key} activeClassName="active">
        <NavLink
          onClick={closeMobileMenu}
          to={`/docs${link}`}
          activeClassName="active"
        >
          {title}
        </NavLink>
      </NavLinkContainer>
    )
  })}
</NavBody>

the applied activeClassName doesn't render on the div and:

const NavLinkContainer = styled.div`
  padding-top: ${({ theme }) => theme.spacings.xSmall};
  padding-bottom: ${({ theme }) => theme.spacings.xSmall};
  border-left: 1px solid ${({ theme }) => theme.colors.color7};
  padding-left: ${({ theme }) => theme.spacings.small} !important;

  &[aria-current='page'] {
    border-left: 3px solid ${({ theme }) => theme.colors.color1} !important;
  }
`

doesn't render the color.

Research

In Styled Components is there a way to style the parent based wether the child has a className of active or aria-current="page"?

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127

1 Answers1

0

I figured out how to modify my parent NavLinkContainer. In Reach Router I have access to pathname from useLocation:

const { pathname } = useLocation()

using link from my map and useMemo I was able to find if the link existed by setting to a variable:

const active = useMemo(() => {
    return pathname.toString().includes(link)
  }, [pathname, link])

by doing so I could pass a boolean to NavLinkContainer:

<NavLinkContainer border={active}>
  // Further code
</NavLinkContainer>

and in the Styled Component I could do:

const NavLinkContainer = styled.div`
  border-color: ${({ border, theme }) =>
    border ? `${theme.colors.color1}` : `${theme.colors.color5}`};
`

which gives me the ability to style the parent div with a custom border color set within my theme.

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127