The Material-UI Accordion (previously known as the expansion panel) is commonly used for controlling when secondary components or information is displayed.
In this example, we will build an Accordion that has components nested in both the summary and details sections and discuss the different components that compose an Accordion (AccordionSummary, AccordionActions, AccordionDetails).
We will also add common stylings to the Accordion (width, height, border, etc).

I moved MUI Accordion onclick and expansion into a separate post for easier reading, but it builds off of this tutorial. I also upgraded the code to MUI v5 in the onClick/expansion post and use the new sx prop.
Code Sandbox with full React code is in the Resources section.
Material-UI Accordion, AccordionSummary, AccordionDetails, and AccordionActions Explained
The Material-UI Accordion is really a wrapper around nested helper components. Not all nested components are required with every accordion. Below is a list of the components and their functions:
- Accordion – This component wraps the helper components and controls props such as
defaultExpanded
and a couple of props related to the expansion animation. - AccordionSummary – This component is required for expansion functionality on clicks (but not required for rendering). It also contains the
expandIcon
. - AccordionDetails – This component is optional for full functionality. However, it comes with default styling that you most likely want, so I recommend using it.
- AccordionActions – This is an optional wrapper used to contain action buttons/icons/etc. It comes with a useful
spacing
prop for default spacing of action components.
Accordion, AccordionSummary, AccordionDetails, and AccordionActions JSX Example
The JSX for this example is quite verbose, partially due to extra divs for aligning the sliders just right. My example is a fork of this example from the docs.
<div className={classes.root}>
{/*elevation is not listed in docs but is available*/}
<Accordion
defaultExpanded
elevation={3}
className={classes.accordion}
>
<AccordionSummary
expandIcon={expanded ? <RemoveIcon /> : <AddIcon />}
onClick={() => {
setExpanded(!expanded);
}}
>
<div className={classes.column}>
<Typography
className={classes.heading}
>
Settings
</Typography>
</div>
<div className={classes.column}>
<Typography className={classes.secondaryHeading}>
Primary Setting
</Typography>
<FormControlLabel
style={{ width: "100%" }}
aria-label="Acknowledge"
onClick={(event) => event.stopPropagation()}
onFocus={(event) => event.stopPropagation()}
control={
<Slider
value={primaryValue}
onChange={handlePrimaryChange}
/>
}
/>
</div>
</AccordionSummary>
<AccordionDetails className={classes.details}>
<div className={classes.column} />
<div className={classes.column}>
<Typography className={classes.secondaryHeading}>
Secondary Setting
</Typography>
<FormControlLabel
style={{ width: "100%" }}
aria-label="Acknowledge"
onClick={(event) => event.stopPropagation()}
onFocus={(event) => event.stopPropagation()}
control={
<Slider
value={secondaryValue}
onChange={handleSecondaryChange}
/>
}
/>
</div>
<div className={clsx(classes.column, classes.helper)}></div>
</AccordionDetails>
<AccordionActions>
<Button size="small">Cancel</Button>
<Button
size="small"
onClick={() => {
setPrimaryValue(0);
setSecondaryValue(0);
}}
>
Reset
</Button>
<Button size="small">Save</Button>
</AccordionActions>
</Accordion>
</div>
Notice that even though elevation isn’t mentioned in the docs, it is an accepted prop on the Accordion. This is because Paper is actually the root element of the Accordion, per the API docs. Adding elevation is a shorthand for adding shadow styling to the Accordion. Shadow can also be accomplished by directly applying box-shadow styling via css.
Notice how I’ve used all the subcomponents discussed above to contain sliders, text, and action buttons. I’ve also used added a state management Boolean (expanded
) to track expansion state. Normally this isn’t needed. However, I wanted to swap out the open/close icon depending on state. I also had to disable the default transition applied to the expandIcon
, and I’ll discuss this shortly in the styling section below.
Finally, when the Slider components are clicked, we have to stop that click event from propagating and accidentally contracting the Accordion. This is accomplished with the FormControlLabel
‘s onClick={(event) => event.stopPropagation()}
(the MUI docs did a good job of demonstrating this).
MUI Accordion Width, Height, and Border
The code below applies classes to three different components in order to achieve the desired styling:
root
is applied to the wrapping div to control widthaccordion
is applied to the Accordion component to control heightdetails
is applied to AccordionDetails. This is only visible on expansion.
root: {
width: "100%"
},
accordion: {
minHeight: 150, //ugly but works
height: "100%"
},
details: {
alignItems: "center",
border: "1px solid rgba(0,0,0,0.1)",
borderRadius: 4
}
Here’s a detailed description of each styling:
- Accordion width: this is easy to customize. Simply target the wrapping div.
- Background color: I left background color unchanged when the Accordion is closed. I added background to the wrapping div and this colored the whole component. Alternatively I could have targeted the Accordion component.
- Height: I don’t recommend changing height. I did in my demo just to show that it is possible. If you want to do it, add a minimum height and then leave the height attribute at 100%. The minimum height will only affect the Accordion when it is closed, as long as the minimum is less than the total natural vertical size when expanded. However, it’s best to simply let the Accordion take its vertical size based on its internal components.
Material-UI Accordion Vs Expansion Panel
You may have used or encountered the Expansion Panel component previously. What’s the difference between the Expansion Panel component and the Accordion? Nothing but the name.
Per Material-UI Docs
The ExpansionPanel component was renamed to Accordion to use a more common naming convention.
Source: MUI ExpansionPanel Docs
You should useimport { Accordion } from '@material-ui/core'
orimport Accordion from '@material-ui/core/Accordion'
.
Resources
Think you’re a JavaScript expert? Test yourself on these 50 difficult JavaScript questions.
Here’s how to add custom icons to Bootstrap’s Accordion.