The Best MUI Accordion onClick, Expand, and Icons Tutorial

This post build off of my code base for styling MUI Accordions. I explore the component’s expand/contract state in the DOM, the classes applied by MUI, and how to handle the click and change events.

Here is the original Accordion styling post, plus a few other helpful posts:

Accordion Styling Expanded and Closed

I set the Accordion component to expanded by default with the defaultExpanded prop.

Material-UI handily adds a class called Mui-expanded to the Accordion and AccordionSummary components when the Accordion is expanded. This makes styling the different states relatively simple.

Take a look at my JSS code below.

accordion: {
  "&.Mui-expanded": {
    transform: "rotate(0deg)",
    backgroundColor: "rgb(245, 240, 237)"
  },
  "& .MuiAccordionSummary-expandIconWrapper": {
    color: `${theme.palette.primary.main}`
  }
}

Notice the syntax in the accordion class. The "&.Mui-expanded" selector will target the Accordion only when it has the Mui-expanded class applied in the DOM. MUI handles adding the class for us on expansion and removing it on contraction.

MuiAccordion-root class in the DOM

Importantly, since I used a custom icon, and a different icon for open/closed states, I needed to remove the default transform and rotate that MUI added on the icon.

I also passed the theme to my style object (which was then used in sx props). I applied the theme primary.main color to my icon button by selecting the child div with class MuiAccordionSummary-expandIconWrapper.

Interestingly, we can see that the MUI Collapse component is being used by default to control the expand and collapse functionality. I can tell because the Collapse renders three layers of divs in the DOM:

MUI Accordion with Expand and Collapse
MUI Accordion with Expand and Collapse

MUI Accordion Icon and onClick

Accordion Icon Position

I found it challenging to position the expand Icon vertically or horizontally. I was only able to make incremental changes and don’t recommend customizing it.

I could adjust the horizontal position modestly by using flexGrow. In the code below, I set flexGrow on the AccordionSummary and IconButton elements in the DOM. I selected them using nested selectors (wrapped in a parent class of root seen in the previous section). These two divs are siblings, and it seems by default the Summary is given most of the space.

"& .MuiAccordionSummary-content": {
  flexGrow: 12
},
"& .MuiIconButton-root": {
  flexGrow: 1
}

This code is not included in my final Code Sandbox demo because it didn’t add enough value.

If you want to vertically position the expand icon, you can first strip the padding. After that, consider adjusting the top value like below:

"& .MuiIconButton-root": {
  paddingTop: 0,
  top: '-4px'
}

Expand MUI Accordion Only on Icon Click

If you want to expand the Accordion only when the expand icon is clicked, and not when content is clicked, you need to call preventDefault and stopPropagation in the AccordionSummary click handler. Then handle the click only in the Icons.

<AccordionSummary
  expandIcon={
    expanded ? 
      <RemoveIcon onClick={() => setExpanded(false)}/> :
      <AddIcon onClick={() => setExpanded(true)} />}
  }
  onClick={(event) => {
    event.stopPropagation();
    event.preventDefault()
  }}
>

This should work…..but it didn’t in my Code Sandbox. I’m not sure why, and if you find a change that makes it work please let me know in the comments. The general idea is correct, and I am suspicious it would work fine in MUI V5 even though it isn’t in V4 code.

MUI Accordion onClick with TypeScript

Here’s an easy example of the typing for the Accordion onClick prop:

<Accordion
  onClick={(event: React.MouseEvent<HTMLElement>) =>
    {console.log(event)}
>

This event handler can be passed the preventDefault and stopPropagation functions mentioned above.

Here’s a deeper dive into MUI onClick events with TypeScript.

MUI Accordion onChange vs. onClick

The Accordion has an onChange event that fires when the component is expanded or contracted. The expansion and contraction is handled internally, but this event can be used to set things like icon state.

I used the onClick handler of the AccordionSummary to accomplish the same functionality. Either is a viable method.

Resources

Code Sandbox Link

MUI Accordion API

Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.