Toggle the visibility of sibling elements with a single click in ReactJS

Hey there, can you take a moment to click on this link and check out the GIF? I'm trying to replicate the same user interface using ReactJs. The goal is to toggle the visibility of sibling p elements with a single click among them. Below is the code snippet along with the result available at this link https://codesandbox.io/s/vkij6. Your assistance in creating a UI similar to the GIF would be greatly appreciated. Thank you in advance.

Below is the code snippet:

App.js

import Toggle from './components/Toggle';

const cities = [
  {
    name: "Mysuru",
    about: "Mysore (or Mysuru), a city in India's southwestern Karnataka state, was the capital of the Kingdom of Mysore from 1399 to 1947. In its center is opulent Mysore Palace, seat of the former ruling Wodeyar dynasty."
  },
  ...
];

function App() {
  return (
    <div className="App">
      <div className="toggle-container">
        <div className="cities">
          {cities.map((city) => (
            <Toggle key={city.name.toString()} city={city} />
          ))}
        </div>
      </div>
    </div>
  );
}

export default App;

Toggle.js


export default function Toggle({ city }) {
    const [toggle, setToggle] = useState(false);

    const handleClick = () => {
        setToggle(!toggle)
    }

    return (
        <>
            <p className="city-name" onClick={handleClick}>{city.name}</p>
            <p className={toggle ? "city-about-show" : "city-about-hide"}>{city.about}</p>
        </>
    )
}

style.css


.App {
  background-color: #000000;
  padding-top: 5px;
  padding-bottom: 5px;
  position: relative;
}

.toggle-container {
  background-color: hsla(245, 100%, 87%, 0.521);
  transition: background-color 300ms;
  width: 800px;
  height: 98.3vh;
  margin: auto;
  padding-top: 70px;
}

.cities {
  background-color: rgb(243, 244, 245);
  width: 450px;
  margin: auto;
  border-radius: 3px;
}
...

Answer №1

Instead of using individual toggle states for each city, I recommend utilizing a common state object that stores the toggle state for each city. By moving this state object to a parent component, you can avoid passing props around every time you need to open a specific city while closing others simultaneously.

import { useState } from 'react';

const cities = [
  {
    name: "Mysuru",
    about: "Mysore (or Mysuru), a city in India's southwestern Karnataka state, was the capital of the Kingdom of Mysore from 1399 to 1947. In its center is opulent Mysore Palace, seat of the former ruling Wodeyar dynasty."
  },
  {
    name: "Bengaluru",
    about: "Bengaluru (also called Bangalore) is the capital of India's southern Karnataka state. The center of India's high-tech industry, the city is also known for its parks and nightlife. By Cubbon Park, Vidhana Soudha is a Neo-Dravidian legislative building."
  },
  {
    name: "Udupi",
    about: "Udupi is a city in the southwest Indian state of Karnataka. It's known for its Hindu temples, including the huge, 13th-century Sri Krishna Temple, which houses a statue of Lord Krishna and attracts many pilgrims."
  },
  {
    name: "Mandya",
    about: "Mandya is a city in the state of Karnataka. It is the headquarter of Mandya district and is located 45 kilometres from Mysore and 100 kilometres from Bangalore"
  },
  {
    name: "Kodagu",
    about: "Kodagu, also known as Coorg, is a rural district in the southwest Indian state of Karnataka. In the area’s north, Madikeri Fort has 2 life-size elephant statues at its entrance, plus a Gothic-style church with a museum on its grounds."
  }
]

function Toggle({ city, toggle, handleClick }) {
  return (
      <>
          <p className="city-name" onClick={() => handleClick(city.name)}>{city.name}</p>
          <p className={toggle[city.name] ? "city city-about-show" : "city city-about-hide"}>{city.about}</p>
      </>
  )
}

function App() {
  const [toggle, setToggle] = useState({
    Mysuru: false,
    Bengaluru: false,
    Udupi: false,
    Mandya: false,
    Kodagu: false,
  });

  const handleClick = (city) => {
      setToggle({
        Mysuru: false,
        Bengaluru: false,
        Udupi: false,
        Mandya: false,
        Kodagu: false,
        [city]: !toggle[city]
      })
  }

  return (
    <div className="App">
      <div className="toggle-container">
        <div className="cities">
          {cities.map((city) => (
            <Toggle key={city.name.toString()} city={city} toggle={toggle} handleClick={handleClick} />
          ))}
        </div>
      </div>
    </div>
  );
}

CSS

.city {
  transition: height 1s;
  overflow: hidden;
}

.city-about-hide{
  height: 0;
  
}

.city-about-show {
  height: 100px;
  display: block;
  font-family: sans-serif;
  color: rgb(105, 105, 105);
  background-color: rgb(214, 231, 247);
  letter-spacing: 0.3px;
  font-size: 14px;
  padding: 20px 15px;
  line-height: 1.5;
}

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

The variable for Google Maps has not been defined

I'm currently working on developing a map that will display multiple markers based on custom posts with metaboxes. The end goal is to have a map showing markers with the post title, some description, and a link to the post. Although I feel like I&apo ...

Incorporate a three-dimensional model into your React application

I am eager to incorporate a 3D avatar into my React portfolio. I recently followed this informative tutorial: React portfolio Specifically, I am looking to replace my current image in the header section with a 3D avatar using three.js, as illustrated in t ...

Continuously spinning loading icon appears when submission button is triggered

We are currently experiencing some issues with our mobile forms. Our users utilize a mobile form to submit contact requests, but the problem arises when they hit 'submit' - the loading icon continues to spin even after the form has been successf ...

How can I ensure my example sketch in p5.js is functioning properly? What event triggers the execution of the run button function?

When experimenting with the example sketch provided at the following link, I noticed that I needed to click the run button in order for it to function properly: However, when I copied the code and ran it locally on my localhost, there was no indication of ...

What is the best way to send a JavaScript variable to Django using AJAX?

I am facing an issue while trying to pass an array in json format using ajax to my django views. Even though I receive a status of 200 indicating that the POST request has been successfully made, when I attempt to display the data passed in another templat ...

Aligment issues in columns on Bootstrap 5

I currently have a layout using Bootstrap 5 with multiple rows and columns. My goal is to have the columns aligned within each row, but I am experiencing issues where some borders are not lining up correctly with the columns. .VI-border { border-t ...

How to automatically set a pre-selected value in a ReactJS Material-UI Select Component

Is there a built-in event in Material-UI for detecting changes in pre-selected values within a Select component? Take, for instance, this Select component with three options: https://i.stack.imgur.com/CKJ5C.png I am looking for an event that triggers wh ...

How can I transfer an instance of a class to dataTransfer.setData?

So I created a new instance of a class: let item = new Item(); Next, I attempted to serialize the item and add it to dataTransfer for drag and drop functionality: ev.dataTransfer.setData("info", JSON.stringify(item)); At some point, I need to retriev ...

Using AngularJS to chain promises

After coming across some advice on AngularJS validation and promises, I am interested in creating a chain of confirmation dialogs to validate multiple steps at once. By making an API call based on user input, we can determine what steps require confirmati ...

Incorporating a URL into an HTML marquee

As a beginner in coding, I'm currently exploring how to incorporate a link into my marquee. My goal is to eliminate any color change or underline animation as well. Do you have any recommendations? .Marquee { color: #da6fe2; background-color: t ...

Managing errors and error codes in React/Redux applications

I am currently exploring the most effective approach for managing errors, particularly when deciding between error codes and an errors object in response from my API. As I dive into building a multi-part form using react, each time a user progresses to th ...

Guide to counting the number of image tags within a parent div and selectively removing them starting from a specific position

My dynamic image tag <img> is generated inside a div from the database using fetching. Here is how my HTML looks: <div class='forimgbox'> <p class='palheading'>Pals</p> <img src='userpic/2232323.p ...

Guide to embedding a component within another component using route based rendering

My routing configuration looks like this: <Provider store={store}> <BrowserRouter> <Route path="/" component={App} /> <Route path="/customers" component={Customers} /> <Route path="/tickets" componen ...

Developing an interactive graph with Django and harnessing the power of chart.js

I’m currently navigating the world of Django as a newcomer. My current project involves conducting sentiment analysis on real-time user tweets using the Twitter API. I've successfully analyzed and displayed the sentiments extracted from these tweets ...

Troubleshooting: JavaScript object ID field not transmitted to event handler

In my React application, I have implemented two components - Counters and Counter. The state object within the Counters component consists of an array of objects, with each object representing a Counter. Within the JSX code of the Counters component, each ...

Ensure that the height of the bootstrap image is limited by the dimensions of another column while still preserving its

I need to develop a versatile element with bootstrap that can accommodate images of different aspect ratios. To achieve this, I must trim the right side of the picture like so. <div class="container"> <div class="row"> <div class="col-12" ...

Error: The setup method cannot be called on an undefined object in the jQuery JSON-RPC client

To invoke a remote RPC procedure using jQuery, I am utilizing the jquery-json plugin available at this link: https://github.com/datagraph/jquery-jsonrpc/ <input style='width:100px;float:left;margin:20px 10px 0px 10px;' type="button" id="JsonH ...

Move extracted CSS from lazy-loaded VueJS component to a different location

I am currently implementing VueJS 2 and using vue-custom-element with lazy-loading in the following way: Vue.customElement('nav-icon', () => new Promise((resolve) => { require(['./NavIcon.vue'], (lazyComponent) => resolve(l ...

Is the process of adding a new row by duplicating an already existing row dynamic?

I've encountered an issue where a row in a table is not being displayed because the CSS style has been set to display:none. Here's the HTML table: <table class="myTable"> <tr class="prototype"> ........ </tr> </ ...

What is the reason for the consistent false return value of fs.existsSync()?

I'm facing an issue where the fs.existsSync() function always returns false even when I'm trying to check if a file exists. Below is the code snippet causing this problem. Any help or suggestions would be greatly appreciated! [ Environment Det ...