skip to Main Content
import React, { useState } from "react";
import {
  Accordion,
  AccordionDetails,
  AccordionSummary,
  Typography
} from "@mui/material";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";

export default function DetailedAccordion() {
  const [expanded, setExpanded] = useState(null);

  const handleChange = (panel) => (event, isExpanded) => {
    setExpanded(isExpanded ? panel : false);
  };

  return (
    <div>
      <Accordion defaultExpanded
        expanded={expanded === "panel1"}
        onChange={handleChange("panel1")}
      >
        <AccordionSummary
          expandIcon={<ExpandMoreIcon />}
          aria-controls="panel1bh-content"
          id="panel1bh-header"
        >
          <Typography>Accordion Panel 1</Typography>
        </AccordionSummary>
        <AccordionDetails>
          <Typography>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vitae
            elit libero, a pharetra augue.
          </Typography>
        </AccordionDetails>
      </Accordion>
      <Accordion
        expanded={expanded === "panel2"}
        onChange={handleChange("panel2")}
      >
        <AccordionSummary
          expandIcon={<ExpandMoreIcon />}
          aria-controls="panel2bh-content"
          id="panel2bh-header"
        >
          <Typography>Accordion Panel 2</Typography>
        </AccordionSummary>
        <AccordionDetails>
          <Typography>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vitae
            elit libero, a pharetra augue.
          </Typography>
        </AccordionDetails>
      </Accordion>
      <Accordion
        expanded={expanded === "panel3"}
        onChange={handleChange("panel3")}
      >
        <AccordionSummary
          expandIcon={<ExpandMoreIcon />}
          aria-controls="panel3bh-content"
          id="panel3bh-header"
        >
          <Typography>Accordion Panel 3</Typography>
        </AccordionSummary>
        <AccordionDetails>
          <Typography>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vitae
            elit libero, a pharetra augue.
          </Typography>
        </AccordionDetails>
      </Accordion>
    </div>
  );
}

I want all panels to be non-closable. One should always remain open.

Tried the code above but somehow again I can close them all.
Whichever one I leave open I can’t close until a new one opens.
All of them are closing on me all the time. One must be open.
Someone help how to solve this.
Here is a demo here. codesandbox.io

2

Answers


  1. An easy solution would be to store the state of each accordion in the state of the component.

    import React, { useState } from "react";
    import {
      Accordion,
      AccordionDetails,
      AccordionSummary,
      Typography
    } from "@mui/material";
    import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
    
    export default function DetailedAccordion() {
      const [expanded, setExpanded] = useState({
        panel1: true,
        panel2: false,
        panel3: false
      });
    
      const handleChange = (panel) => (event) => {
        if (panel === "panel1") {
          setExpanded({ panel1: true, panel2: false, panel3: false });
        }
        if (panel === "panel2") {
          setExpanded({ panel1: false, panel2: true, panel3: false });
        }
        if (panel === "panel3") {
          setExpanded({ panel1: false, panel2: false, panel3: true });
        }
      };
    
      return (
        <div>
          <Accordion expanded={expanded.panel1} onChange={handleChange("panel1")}>
            <AccordionSummary
              expandIcon={<ExpandMoreIcon />}
              aria-controls="panel1bh-content"
              id="panel1bh-header"
            >
              <Typography>Accordion Panel 1</Typography>
            </AccordionSummary>
            <AccordionDetails>
              <Typography>
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vitae
                elit libero, a pharetra augue.
              </Typography>
            </AccordionDetails>
          </Accordion>
          <Accordion expanded={expanded.panel2} onChange={handleChange("panel2")}>
            <AccordionSummary
              expandIcon={<ExpandMoreIcon />}
              aria-controls="panel2bh-content"
              id="panel2bh-header"
            >
              <Typography>Accordion Panel 2</Typography>
            </AccordionSummary>
            <AccordionDetails>
              <Typography>
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vitae
                elit libero, a pharetra augue.
              </Typography>
            </AccordionDetails>
          </Accordion>
          <Accordion expanded={expanded.panel3} onChange={handleChange("panel3")}>
            <AccordionSummary
              expandIcon={<ExpandMoreIcon />}
              aria-controls="panel3bh-content"
              id="panel3bh-header"
            >
              <Typography>Accordion Panel 3</Typography>
            </AccordionSummary>
            <AccordionDetails>
              <Typography>
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vitae
                elit libero, a pharetra augue.
              </Typography>
            </AccordionDetails>
          </Accordion>
        </div>
      );
    }
    
    Login or Signup to reply.
  2. Perhaps something like this? CodeSandbox Example Here

    const panelInfo = [
      { name: "Accordion Panel 1", details: "Accordion Panel 1 details..." },
      { name: "Accordion Panel 2", details: "Accordion Panel 2 details..." },
      { name: "Accordion Panel 3", details: "Accordion Panel 3 details..." }
    ];
    
    export default function App() {
      const [expanded, setExpanded] = useState(panelInfo[0]);
    
      function handleAccordClick(panel) {
        if (expanded !== panel) setExpanded(panel);
      }
    
      return (
        <div className="App">
          {panelInfo.map((panel) => (
            <Accordion
              expanded={panel === expanded}
              onClick={() => handleAccordClick(panel)}
              key={panel}
            >
              <AccordionSummary>{panel.name}</AccordionSummary>
              <AccordionDetails>{panel.details}</AccordionDetails>
            </Accordion>
          ))}
        </div>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search