What is the best way to handle a 3-element mode using an onClick function in Next.js?

Creating an accordion menu in Next.js comes with the challenge of implementing 3 different modes for an element:

  1. The first mode is default, where no click event has occurred: .mainLi_default
  2. In the second mode, the first click event triggers the opening of the menu with a specific style: .mainLi_open
  3. When a click event occurs on the same element again, the menu must close with a different specific style: .mainLi_recentOpen
export default function Menu() {
  const context = useContext(navItems);
  const listItems = context.listItems;
  const [selectItemId, setSelectItemId] = useState();
  function selectItemHandler(id, item) {
    setSelectItemId(id);
  }

  return (
    <>
      {listItems.map((menuItems) => {
        return (
          <ul key={menuItems.id} className={`${styles.list}`}>
            <li
              id={menuItems.id}
              className={`${styles.mainLi} ${menuItems.id == selectItemId ? styles.mainLi_open : styles.mainLi_default}`}
              onClick={() => {
                selectItemHandler(menuItems.id);
              }}
            >
              <div className={`${styles.options}`}>
                <span>{menuItems.icon}</span>
                <span>{menuItems.title}</span>
                <span>
                  <IoIosArrowDown />
                </span>
              </div>
              <ul className={styles.subMenu}>
                {menuItems.subItems.map((subitem) => {
                  return (
                    <li key={subitem.id}>
                      <Link href={subitem.path}>{subitem.title}</Link>
                    </li>
                  );
                })}
              </ul>
            </li>
          </ul>
        );
      })}
    </>
  );
}
/* used inside : nav-menu/menu/index.js */
.list {
  @apply flex w-full flex-col px-4 py-2;
}
.mainLi {
  @apply w-full;
}
.mainLi .options {
  @apply flex w-full cursor-pointer items-center justify-start gap-2 font-R-bold capitalize;
}
.mainLi .options span:nth-child(1) {
  @apply text-20;
}
.mainLi .options span:nth-child(2) {
  @apply text-16;
}
.mainLi .options span:nth-child(3) {
  @apply ml-auto text-20;
}
.mainLi .subMenu {
  @apply mt-4 flex w-full flex-col gap-2 px-6 font-R-regular capitalize text-secondary;
}
/* menu status classes */
/* Start default status (default) */
.mainLi_default .options span:nth-child(1) {
  @apply text-mute;
}
.mainLi_default .options span:nth-child(2) {
  @apply text-mute;
}
.mainLi_default .options span:nth-child(3) {
  @apply text-mute;
}
.mainLi_default .subMenu {
  @apply hidden text-secondary;
}
/* End default status (default) */
/* Start open status */
.mainLi_open .options span:nth-child(1) {
  @apply text-primary;
}
.mainLi_open .options span:nth-child(2) {
  @apply text-primary;
}
.mainLi_open .options span:nth-child(3) {
  @apply rotate-180 text-secondary;
}
.mainLi_open .subMenu {
  @apply flex text-secondary;
}
/* End open status */
/* START recentOpen status */
.mainLi_recentOpen .options span:nth-child(1) {
  @apply text-secondary;
}
.mainLi_recentOpen .options span:nth-child(2) {
  @apply text-secondary;
}
.mainLi_recentOpen .options span:nth-child(3) {
  @apply rotate-180 text-secondary;
}
.mainLi_recentOpen .subMenu {
  @apply hidden text-secondary;
}
/* End recentOpen status */
/* menu status classes */

I have successfully implemented the first and second modes, but I am currently working on figuring out how to manage the last mode.

Answer №1

To implement a feature where user can track their recently opened items, utilize useState([]) to create an array. When the user clicks on an item, check if its ID already exists in the array. If not, save the ID along with existing values in the array. Within the component's classname, ascertain whether the current ID exists in the useState Array. If it does, apply a specific classname for styling purposes.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the most effective method in Vue.js for transitioning elements without the need to use v-for and v-if at the

Utilizing v-for to generate multiple <p> elements, each one animating in within a Vue <transition> component if the v-if condition is met. Below is the code snippet: <transition name="fade"> <p v-for="(quote, idx) in game.quot ...

Can an excess of CSS impact the speed and performance of a website?

After conducting thorough research on this specific topic, I was unable to locate the precise answer that I require. For instance, there are numerous divs within my project that necessitate a border. One approach is to create a distinct CSS class such as ...

The useRouter hook from next/router was unable to connect because NextRouter was not activated

import { useRouter } from 'next/router'; const Navbar2 = () => { const router = useRouter(); return ( <nav className={`fixed top-0 w-full px-10 bg-white p-4 transition-all duration-500 ${isVisible ? 'top-0' : 'top-[-1 ...

Steps for developing your own node package manager

Looking to create a CLI package manager application called mypkgname for your Github repository? You can easily install this package globally by registering it on npm: npm install -g mypkgname-cli mypkgname init myApp cd myApp npm install npm start Here ...

When attempting to showcase array information in React, there seems to be an issue with the output

After printing console.log(response.data), the following output is displayed in the console. https://i.sstatic.net/LLmDG.png A hook was created as follows: const [result,setResult] = useState([]); The API output was then assigned to the hook with: setRe ...

In React JSX, what is the best approach for printing a substring?

I am facing an issue with dividing two variables in my React component. I need to display the result to only one decimal place, so I decided to use the substring method like this: <div className="col-md-8"> {(total_star / total_user).toString ...

Is there a way to customize the background size of the selected date in the DateCalendar component of MUI?

I need assistance with modifying the background size of DateCalendar's selected date in MUI (material-UI). I attempted to adjust it by changing some CSS properties using styled(DateCalendar) as shown below. However, clicking on dates caused issues wit ...

Integrating Facebook login with Cordova using the cordovaOauth plugin

Encountering issues while setting up FB login for my cordova mobile app. A tutorial followed: http://www.codeproject.com/Tips/1031475/How-to-Integrate-Facebook-Login-into-a-Cordova-App#_comments <script src="js/angular.js"></script> <scrip ...

Troubleshooting a layoutUnit problem with Primefaces southern region

I'm encountering an issue with my PrimeFaces layout. The south layoutUnit is not displaying on the page, and I am unsure why. Below is the code for the page: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/ ...

What could be the reason for XMLHttpRequest to freeze with no error until it reaches the default browser timeout limit

As a front end developer, I have some gaps in my understanding of how networks operate. When a Javascript XMLHttpRequest times out, the ontimeout handler gets triggered. In case the XMLHttpRequest.timeout property is not set (which is supported in modern b ...

Angular 13 does not currently have support for the experimental syntax 'importMeta' activated

Since upgrading to angular 13, I've encountered an issue while attempting to create a worker in the following manner: new Worker(new URL('../path/to/worker', import.meta.url), {type: 'module'}) This code works as expected with "ng ...

An error has occurred in Angular5 and Three.js: 'Scene1' property is undefined

Running into an issue with my angular5 website integrated with Three.js. I keep getting an error message that says: Cannot read property 'Scene1' of undefined when trying to add an object to the Scene. Any suggestions on how to properly define th ...

Setting the input type for a TextField in Mui: A step-by-step guide

I'm looking to restrict the textfield to only accept integer inputs: <TextField value={inputs.length} name="length" required label="Enter length" color="secondary" variant="filled" onChange={handleChange} ...

Retrieve the list of device tokens for the APNS service

Is it possible to retrieve a list of all device tokens on which my app is installed through an APNS endpoint? I am aware of the feedback service that provides the status of devices to whom messages are sent, but I believe this is only after the message ...

Unable to retrieve value - angularJS

An AngularJS application has been developed to dynamically display specific values in an HTML table. The table consists of six columns, where three (Work Name, Team Name, Place Name) are fixed statically, and the remaining three columns (Service One, Servi ...

When using jQuery to focus on an input element, the cursor fails to show up

Looking to enhance user experience by focusing on an input element upon clicking a specific div. The HTML structure being used is as follows: <div class="placeholder_input"> <input type="text" id="username" maxlength="100" /> <div ...

Enhancing React components with Hooks and markers

I'm facing a syntax uncertainty regarding how to update React state using hooks in two specific scenarios. 1) I have a state named company and a form that populates it. In the contacts section, there are two fields for the company employee (name and ...

Troubleshooting Select2 frontend design in Bootstrap 4

I've been working on implementing Select2 with Bootstrap 4 for my <select> elements. Unfortunately, I ran into an issue because there isn't an official Bootstrap 4 template for Select2. However, I came across this project which seems to be ...

inject a $scope object into a view when a button is clicked

Right now, I am using an array as a $scope object $scope.data { item1: "Value", item2: "Value Alt" } Every item corresponds to a form input with a default value. My goal is to create a new form from the same data set upon an ng-click event while main ...

How can I prevent overwriting previous input data in LocalStorage using Draftjs?

I have implemented a draftjs rich text editor to store my text input in local storage. The current functionality allows me to enter text and save it to local storage by clicking the save button. See the code snippet below: import React from "react"; impor ...