In this tutorial, we will create Accordion (FAQ) using react material ui (mui 5). We will see simple Accordion component, controlled accordion & customize example with react material UI 5.
Install & Setup Vite + React + Typescript + MUI 5
React Material UI 5 Accordion (FAQ) Example
1. react mui 5 simple Accordion (FAQ) component.
import Accordion from '@mui/material/Accordion';
import AccordionSummary from '@mui/material/AccordionSummary';
import AccordionDetails from '@mui/material/AccordionDetails';
import Typography from '@mui/material/Typography';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { Container } from '@mui/material';
export default function SimpleAccordion() {
return (
<Container maxWidth="md" sx={{ mt: 20 }}>
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography>Accordion 1</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
Lorem ipsum..
</Typography>
</AccordionDetails>
</Accordion>
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel2a-content"
id="panel2a-header"
>
<Typography>Accordion 2</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
Lorem ipsum dolor sit amet,..
</Typography>
</AccordionDetails>
</Accordion>
<Accordion disabled>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel3a-content"
id="panel3a-header"
>
<Typography>Disabled Accordion</Typography>
</AccordionSummary>
</Accordion>
</Container>
);
}
2. react mui 5 controlled Accordion (FAQ) .
import * as React from 'react';
import Accordion from '@mui/material/Accordion';
import AccordionDetails from '@mui/material/AccordionDetails';
import AccordionSummary from '@mui/material/AccordionSummary';
import Typography from '@mui/material/Typography';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { Container } from '@mui/material';
export default function ControlledAccordions() {
const [expanded, setExpanded] = React.useState<string | false>(false);
const handleChange =
(panel: string) => (event: React.SyntheticEvent, isExpanded: boolean) => {
setExpanded(isExpanded ? panel : false);
};
return (
<Container maxWidth="md" sx={{ mt: 20 }}>
<Accordion expanded={expanded === 'panel1'} onChange={handleChange('panel1')}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1bh-content"
id="panel1bh-header"
>
<Typography sx={{ width: '33%', flexShrink: 0 }}>
General settings
</Typography>
<Typography sx={{ color: 'text.secondary' }}>I am an accordion</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
Nulla facilisi...
</Typography>
</AccordionDetails>
</Accordion>
<Accordion expanded={expanded === 'panel2'} onChange={handleChange('panel2')}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel2bh-content"
id="panel2bh-header"
>
<Typography sx={{ width: '33%', flexShrink: 0 }}>Users</Typography>
<Typography sx={{ color: 'text.secondary' }}>
You are currently not an owner
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
Donec placerat...
</Typography>
</AccordionDetails>
</Accordion>
<Accordion expanded={expanded === 'panel3'} onChange={handleChange('panel3')}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel3bh-content"
id="panel3bh-header"
>
<Typography sx={{ width: '33%', flexShrink: 0 }}>
Advanced settings
</Typography>
<Typography sx={{ color: 'text.secondary' }}>
Filtering has been entirely disabled for whole web server
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
Nunc vitae ...
</Typography>
</AccordionDetails>
</Accordion>
<Accordion expanded={expanded === 'panel4'} onChange={handleChange('panel4')}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel4bh-content"
id="panel4bh-header"
>
<Typography sx={{ width: '33%', flexShrink: 0 }}>Personal data</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
Nunc vitae...
</Typography>
</AccordionDetails>
</Accordion>
</Container>
);
}
3. react mui 5 customize Accordion (FAQ) .
import * as React from "react";
import { styled } from "@mui/material/styles";
import ArrowForwardIosSharpIcon from "@mui/icons-material/ArrowForwardIosSharp";
import MuiAccordion, { AccordionProps } from "@mui/material/Accordion";
import MuiAccordionSummary, {
AccordionSummaryProps,
} from "@mui/material/AccordionSummary";
import MuiAccordionDetails from "@mui/material/AccordionDetails";
import Typography from "@mui/material/Typography";
import { Container } from "@mui/material";
const Accordion = styled((props: AccordionProps) => (
<MuiAccordion disableGutters elevation={0} square {...props} />
))(({ theme }) => ({
border: `1px solid ${theme.palette.divider}`,
"&:not(:last-child)": {
borderBottom: 0,
},
"&:before": {
display: "none",
},
}));
const AccordionSummary = styled((props: AccordionSummaryProps) => (
<MuiAccordionSummary
expandIcon={<ArrowForwardIosSharpIcon sx={{ fontSize: "0.9rem" }} />}
{...props}
/>
))(({ theme }) => ({
backgroundColor:
theme.palette.mode === "dark"
? "rgba(255, 255, 255, .05)"
: "rgba(0, 0, 0, .03)",
flexDirection: "row-reverse",
"& .MuiAccordionSummary-expandIconWrapper.Mui-expanded": {
transform: "rotate(90deg)",
},
"& .MuiAccordionSummary-content": {
marginLeft: theme.spacing(1),
},
}));
const AccordionDetails = styled(MuiAccordionDetails)(({ theme }) => ({
padding: theme.spacing(2),
borderTop: "1px solid rgba(0, 0, 0, .125)",
}));
export default function CustomizedAccordions() {
const [expanded, setExpanded] = React.useState<string | false>("panel1");
const handleChange =
(panel: string) => (event: React.SyntheticEvent, newExpanded: boolean) => {
setExpanded(newExpanded ? panel : false);
};
return (
<Container maxWidth="md" sx={{ mt: 20 }}>
<Accordion
expanded={expanded === "panel1"}
onChange={handleChange("panel1")}
>
<AccordionSummary aria-controls="panel1d-content" id="panel1d-header">
<Typography>Collapsible Group Item #1</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>Lorem ipsum...</Typography>
</AccordionDetails>
</Accordion>
<Accordion
expanded={expanded === "panel2"}
onChange={handleChange("panel2")}
>
<AccordionSummary aria-controls="panel2d-content" id="panel2d-header">
<Typography>Collapsible Group Item #2</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>Lorem ipsum...</Typography>
</AccordionDetails>
</Accordion>
<Accordion
expanded={expanded === "panel3"}
onChange={handleChange("panel3")}
>
<AccordionSummary aria-controls="panel3d-content" id="panel3d-header">
<Typography>Collapsible Group Item #3</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>Lorem ipsum...</Typography>
</AccordionDetails>
</Accordion>
</Container>
);
}