javascriptcssreactjsjsxreact-spring

Display list on page or in drawer menu depending on screen width


I have a menu that displays as a hamburger/drawer menu when screen width is less than a certain amount and I am using react-spring to slide that menu on-screen when the "hamburger icon" is clicked. My issue is that the <ul> is within that <animated.div> from react-springs so when the screen size is wider and the hamburger/drawer menu is hidden, the <ul> with the list items are hidden with it, which I do not want, I want the menu to be displayed normally on page (without a drawer) when the screen is wider. Is there a way to achieve this without having to create two <ul>'s with the same <li>'s twice, one within the <animated.div> that displays in a drawer menu on narrower screens and one that displays on page on wider screens?

React.js/JSX:

return (
    //State of menuVisible starts off as false
    <FontAwesomeIcon
      className="menuBarIcon"
      icon={faBars}
      onClick={() => setMenuVisible(!menuVisible)}/>
    {menuTransitions(
      (styles, item) => item &&
      <animated.div
        style={styles}
        className="menu">
        <ul>
          <li><a>Menu Item One</a></li>
          <li><a>Menu Item Two</a></li>
          <li><a>Menu Item Three</a></li>
          <li><a>Menu Item Four</a></li>
          <li><a>Menu Item Five</a></li>
        </ul>
      </animated.div>
    )}
);

CSS:

//Wider screens
.menuBarIcon {
  display: none;
}

@media (max-width: 1080px) {
//Narrower screens
.menuBarIcon {
  display: inline;
  float: right;
  padding: 10px;
  margin: 25px;
}

.menu {
  position: fixed;
  top: 0;
  left: 0;
  width: 320px;
  height: 100%;
}
}

Solution

  • I solved it, what I did was to first have the <ul> outside of the <animated.div> so that now it displays normally in wider screens. I then added a ternary operator to the <ul> based on the state of menuVisible so that it would alternate between two classes, one that would hide the <ul> and one that would display it. Then to have it positioned within the drawer menu I simply added the CSS of the menu class to the <ul> in the media query for narrower screens.

    React.js/JSX:

    return (
    <FontAwesomeIcon
      className="menuBarIcon"
      icon={faBars}
      onClick={() => setMenuVisible(!menuVisible)}/>
    {menuTransitions(
      (styles, item) => item &&
      <animated.div
        style={styles}
        className="menu">
      </animated.div>
    )}
    //Class alternates between the two based on condition of the state of menuVisible
    <ul className={menuVisible ? "menuActive" : "menuInactive"}>
      <li><a>Menu Item One</a></li>
      <li><a>Menu Item Two</a></li>
      <li><a>Menu Item Three</a></li>
      <li><a>Menu Item Four</a></li>
      <li><a>Menu Item Five</a></li>
    </ul>
    );
    

    CSS:

    @media (max-width: 1080px) {
    //Narrower screens
    
    .menu {
      position: fixed;
      top: 0;
      left: 0;
      width: 320px;
      height: 100%;
    }
    
    ul {
      //Added same CSS as .menu class to Ul to position the list within the drawer menu
      position: fixed;
      top: 0;
      left: 0;
      width: 280px; //width is different to compensate for padding in li
      height: 100%
      flex-direction: column;
    }
    
    .menuActive {
      //Ul displays normally when menuVisible state is true
      display: block;
    }
    
    .menuInactive {
      //Ul is hidden when menuVisible state is false
      display: none;
    }
    }