javascriptreactjsuser-interfacetailwind-csshamburger-menu

how to replace group-focus with JavaScript


I am trying to replace group-focus with React state isOpen.

Icon number 7

I tried to just simple replace whenever group-focus is to conditional rendering. But the X is not shown

This is my actuall code:

import React, { useState } from "react";

export default function HamburgerIcon() {
  const [isOpen, setIsOpen] = useState(false);

  const toggleMenu = () => {
    setIsOpen(!isOpen);
  };

  return (
    <div>
      <button className={`relative group ${isOpen ? "focus:ring-4" : ""}`} onClick={toggleMenu}>
        <div className={`relative
         flex 
         overflow-hidden
         items-center
        justify-center 
        rounded-full 
        w-[50px] 
        h-[50px] 
        transform 
        transition-all
        ring-0 
        ring-secondary 
        hover:ring-8 duration-200 shadow-md ${isOpen ? "ring-4" : ""}`}>
          <div className={`flex flex-col justify-between w-[20px] h-[20px] transform transition-all duration-300 origin-center overflow-hidden`}>
            {/*This is div as Hamburger */}
            <div className={`bg-font-color h-[2px] w-7 transform transition-all duration-300 origin-left ${isOpen ? "rotate-45 translate-y-6 delay-100" : ""}`}></div>
            <div className={`bg-font-color h-[2px] w-7 rounded transform transition-all duration-300 ${isOpen ? "translate-y-6 delay-75" : ""}`}></div>
            <div className={`bg-font-color h-[2px] w-7 transform transition-all duration-300 origin-left ${isOpen ? "translate-y-6" : ""}`}></div>

            {/*This is div with X*/}
            <div className={`absolute items-center justify-between transform transition-all duration-500 top-2.5 ${isOpen ? "-translate-x-10" : "translate-x-0"} flex w-0 ${isOpen ? "w-12" : ""}`}>
              <div className={`absolute bg-font-color h-[2px] w-5 transform transition-all duration-500 ${isOpen ? "rotate-45 delay-300" : ""}`}></div>
              <div className={`absolute bg-font-color h-[2px] w-5 transform transition-all duration-500 ${isOpen ? "-rotate-45 delay-300" : ""}`}></div>
            </div>
          </div>
        </div>
      </button>
    </div>
  );
}

But if I click on button the X is not shown is not displayed, or is displayed at the same time as the hamburger and therefore looks like it is not displayed at all

The output


Solution

  • You have a conditional the wrong way around.

    In the example CodePen:

    <div class="… -translate-x-10 group-focus:translate-x-0 …">
    

    But in your JSX code:

    <div className={`… ${isOpen ? "-translate-x-10" : "translate-x-0"} …`}>
    

    Whereas it should be:

    <div className={`… ${isOpen ? "translate-x-0" : "-translate-x-10"} …`}>
    

    Full code:

    tailwind.config = {
      theme: {
        extend: {
          colors: {
            'font-color': 'red',
          },
        },
      },
    };
    
    const { useState } = React;
    
    function HamburgerIcon() {
      const [isOpen, setIsOpen] = useState(false);
    
      const toggleMenu = () => {
        setIsOpen(!isOpen);
      };
    
      return (
        <div>
          <button className={`relative group ${isOpen ? "focus:ring-4" : ""}`} onClick={toggleMenu}>
            <div className={`relative flex  overflow-hidden items-center justify-center  rounded-full  w-[50px]  h-[50px]  transform  transition-all ring-0  ring-secondary  hover:ring-8 duration-200 shadow-md ${isOpen ? "ring-4" : ""}`}>
              <div className={`flex flex-col justify-between w-[20px] h-[20px] transform transition-all duration-300 origin-center overflow-hidden`}>
                {/*This is div as Hamburger */}
                <div className={`bg-font-color h-[2px] w-7 transform transition-all duration-300 origin-left ${isOpen ? "rotate-45 translate-y-6 delay-100" : ""}`}></div>
                <div className={`bg-font-color h-[2px] w-7 rounded transform transition-all duration-300 ${isOpen ? "translate-y-6 delay-75" : ""}`}></div>
                <div className={`bg-font-color h-[2px] w-7 transform transition-all duration-300 origin-left ${isOpen ? "translate-y-6" : ""}`}></div>
    
                {/*This is div with X*/}
                <div className={`absolute items-center justify-between transform transition-all duration-500 top-2.5 ${isOpen ? "translate-x-0" : "-translate-x-10"} flex w-0 ${isOpen ? "w-12" : ""}`}>
                  <div className={`absolute bg-font-color h-[2px] w-5 transform transition-all duration-500 ${isOpen ? "rotate-45 delay-300" : ""}`}></div>
                  <div className={`absolute bg-font-color h-[2px] w-5 transform transition-all duration-500 ${isOpen ? "-rotate-45 delay-300" : ""}`}></div>
                </div>
              </div>
            </div>
          </button>
        </div>
      );
    }
    
    ReactDOM.createRoot(document.getElementById('app')).render(<HamburgerIcon/>);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdn.tailwindcss.com/3.3.3"></script>
    
    <div id="app"></div>