10

I have created an Accordion for my Project. But I want the panel to be expanded only when the expand icon is clicked. Currently it is expanding on clicking anywhere on the panel. Can we customize its expanding behavior ?

CODE:

import React from "react";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import Accordion from "@material-ui/core/Accordion";
import AccordionDetails from "@material-ui/core/AccordionDetails";
import Typography from "@material-ui/core/Typography";
import AccordionSummary from "@material-ui/core/AccordionSummary";

export default function App() {
return (
    <div style={{}}>
    <h4>How to create Accordion in ReactJS?</h4>
    <Accordion style={{ width: 400}}>
        <AccordionSummary 
         expandIcon={<ExpandMoreIcon />}
         aria-controls="panel1a-content"
        >   
          <div>Click to Expand</div>
        </AccordionSummary>
        <AccordionDetails>
        <Typography>Greetings of the day :)</Typography>
        </AccordionDetails>
    </Accordion>
    </div>
);
}
NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
Aishwarya
  • 101
  • 1
  • 1
  • 3

5 Answers5

11

Yes we can do it like this

1- Create our own state with handler:

  const [expand, setExpand] = React.useState(false);
  const toggleAcordion = () => {
    setExpand((prev) => !prev);
  };

2- Add our state to the Accordion:

<Accordion expanded={expand} style={{ width: 400 }}>

3- Add onClick for the icon:

    <AccordionSummary
      expandIcon={<ExpandMoreIcon />}
      aria-controls="panel1a-content"
      IconButtonProps={{
        onClick: toggleAcordion
      }}
    >

Full Code:

Codesandbox Demo

EDIT: Explanation: Material-UI Accordion has its own state (open or close) and its own click handler, what we did above is that we create our own state and override Material-UI Accordion state by the prop expanded and add event listener onClick to the icon button by the prop IconButtonProps, our event listener will open or close the Accordion by change our state.

NOTE: The code above doesn't change the style in case of the cursor pointer.

Abdulmuhaymin
  • 905
  • 7
  • 16
7

There is no public API to do what you want out-of-the-box, but you can use this CSS trick:

V5

<AccordionSummary
  sx={{
    pointerEvents: "none"
  }}
  expandIcon={
    <ExpandMoreIcon
      sx={{
        pointerEvents: "auto"
      }}
    />
  }
>

V4

const useStyles = makeStyles({
  summary: {
    pointerEvents: 'none',
  },
  icon: {
    pointerEvents: 'auto',
  },
});
<AccordionSummary
  className={classes.summary}
  expandIcon={<ExpandMoreIcon className={classes.icon} />}
>
  <Typography>Accordion 1</Typography>
</AccordionSummary>

Live Demo

Codesandbox Demo

NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
  • We have API, check this out https://v4.mui.com/api/accordion-summary/ and https://v4.mui.com/api/accordion/ – Abdulmuhaymin Sep 28 '21 at 09:25
  • What I meant is that there is not a simple prop like `expandOnButtonClick`, but yeah, it's doable if you control the `Accordion` state, I'll edit my answer. @Abdulmuhaymin – NearHuscarl Sep 28 '21 at 09:30
5

For v5, and setting the mouse cursor properly:

1- Create our own state with handler:

const [accordionOpen, setAccordionOpen] = React.useState(false);

2- Add our state to the Accordion and toggle on click:

<Accordion expanded={accordionOpen}>
    <AccordionSummary
      expandIcon={
        <ExpandMoreIcon
          style={{ cursor: 'pointer' }}
          onClick={() => setAccordionOpen(!accordionOpen)} />
      }
      sx={{ cursor: 'unset !important' }}
    >
JohnFlux
  • 188
  • 1
  • 5
1

you can try set expanded true/false in the Accordion

function Container(props) {
  const [expand, setExpand] = React.useState(false);
  const toggleAccordion = () => {
    setExpand((prev) => !prev);
  };
  return (
    <React.Fragment>
      <Accordion expanded={expand}>
        <AccordionSummary
          expandIcon={<ExpandMoreIcon
            onClick={toggleAccordion}
          />}
          aria-controls="panel1a-content"
          id="panel1a-header"
        >
          <Typography></Typography>
        </AccordionSummary>
        <AccordionDetails>
        </AccordionDetails>
      </Accordion>
    </React.Fragment>)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Grant mitchell
  • 277
  • 1
  • 2
  • 12
1

None of these solutions worked for me. I handled it with the e.stopPropagation() method, using it in the onClick event of the icon after calling the toggle function.

Like this:

import React from "react";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import Accordion from "@material-ui/core/Accordion";
import AccordionDetails from "@material-ui/core/AccordionDetails";
import Typography from "@material-ui/core/Typography";
import AccordionSummary from "@material-ui/core/AccordionSummary";

export default function App() {
return (
    <div style={{}}>
    <h4>How to create Accordion in ReactJS?</h4>
    <Accordion style={{ width: 400}}>
        <AccordionSummary 
         expandIcon={<ExpandMoreIcon />}
         aria-controls="panel1a-content"
        >   
          <div ><img src='yourIcon' onClick={(e) => { toggleAccordion(); e.stopPropagation() }} /></div>
        </AccordionSummary>
        <AccordionDetails>
        <Typography>Greetings of the day :)</Typography>
        </AccordionDetails>
    </Accordion>
    </div>
);
}
tdy
  • 36,675
  • 19
  • 86
  • 83
Serwa_srp
  • 41
  • 6