moranja
moranja

Reputation: 62

How do I reference another component's styled-components generated className while creating a (hover) rule in a different component?

I'm creating a menu with styled-components and React, and want the color of the icon to change on hover, but I need it to change when the icon's parent is hovered, so that hovering the text next to the icon also activates the icon's hover styles. Here is the code I'm using to get close:

import React from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

const Menu = styled.div`
  display: flex;
  flex-direction: column;
`;

const LinkContainer = styled.div`
  display: flex;
  flex-direction: row;
`;

const FontAwesomeIconExtended = styled.div`
  flex: 1;

  display: grid;
  place-items: center;
  height: 40px;
  width: 40px;
  padding: 10px 2px;
  border-radius: 10px;
  transition: color 0.5s ease;

  color: ${(props) => (props.$isactive ? '#fff' : '#CBE3EB')};
  background: ${(props) =>
    props.$isactive
      ? 'linear-gradient(96.34deg, #004157 0%, #0090b2 100%)'
      : '#fff'};

  ${LinkContainer}:hover & {
    color: ${(props) => (props.$isactive ? '#fff' : 'green')};
  }                                                 /* Problem occurring here */
`;

const LinkText = styled.div`
  flex: 1 0 100px;
`;

function NavLink({ ...props }) {
  return (
    <Link to={props.path}>
      <LinkContainer $isactive={props.$isactive}>
        <FontAwesomeIconExtended
          $isactive={props.$isactive}
          icon={props.icon}
          size='2x'
          as={FontAwesomeIcon}
        />
        <LinkText $isactive={props.$isactive}>{props.name}</LinkText>
      </LinkContainer>
    </Link>
  );
}

export default function NavMenu() {
  return (
    <Menu>
      <NavLink path='/' name='Home' icon='house' $isactive />
      <NavLink path='/profile' name='Profile' icon='user' />
      <NavLink path='/payments' name='Payments' icon='credit-card-front' />
      <NavLink path='/contracts' name='Contracts' icon='file-contract' />
      <NavLink path='/messages' name='Messages' icon='mail-bulk' />
      <NavLink path='/messages' name='Documents' icon='folders' />
      <NavLink path='/locations' name='Transfer' icon='truck-moving' />
    </Menu>
  );
}

The way you reference another styled component in a later component is very clever, but in this case when it creates the hover rule, it creates without consideration of the different type of parent container ($isactive === true, or $isactive === false), so all LinkContainers have two rules for hovering, and use the last defined rule. This can be seen by moving $isactive to the last NavLink component.

Here is a screenshot of the devtools showing what I mean about the two hover rules not taking into consideration the parents class, just the general type of the parent.

I think the solution might involve being specific about the two types of LinkContainer's classNames while creating the hover rule, but that doesn't seem well supported. Thanks for taking a look.

Upvotes: 3

Views: 2134

Answers (1)

Jkarttunen
Jkarttunen

Reputation: 7621

Increase the specificity by repeating the class name, using another '&'

${LinkContainer}:hover && {

Upvotes: 2

Related Questions