프론트엔드/Component
[Component] MUI 아코디언 컴포넌트 예시 코드
순코딩
2025. 3. 4. 14:33
믹스인 코드
src / styles / mixins.ts
import { css } from '@emotion/react';
// 믹스인 정의
export const mixinFlex = (direction : "row" | "column") => css`
display: flex;
flex-direction: ${direction};
align-items: center;
justify-content: center;
`;
컴포넌트 코드
"use client";
import { Accordion, AccordionDetails, AccordionSummary, styled, Typography } from "@mui/material";
import React from "react";
import ExpandMoreOutlinedIcon from "@mui/icons-material/ExpandMoreOutlined";
import { mixinFlex } from "@/styles/mixins";
type AccordionByCollegeType = {
title: string;
majors: string[];
Icon: React.ReactElement;
};
const AccordionByCollege = ({ title, majors, Icon }: AccordionByCollegeType) => {
return (
<Container>
<CollegeAccordion>
<Summary expandIcon={<ExpandMoreOutlinedIcon />} aria-controls="panel1-content" id="panel1-header">
<SummaryIconTextWrapper>
{Icon}
<Typography variant="body2">{title}</Typography>
</SummaryIconTextWrapper>
</Summary>
<Detail>
{majors.map((el, idx) => (
<DetailBox key={idx}>
{Icon}
{el}
</DetailBox>
))}
</Detail>
</CollegeAccordion>
</Container>
);
};
export default AccordionByCollege;
const Container = styled("div")`
${mixinFlex("column")};
flex: 1;
flex-basis: 150px;
height: auto;
`;
const CollegeAccordion = styled(Accordion)`
width: 100%;
border-radius: 8px;
box-shadow: none !important;
&::before {
display: none;
}
& svg {
color: ${({ theme }) => theme.palette.primary.main};
}
`;
const Summary = styled(AccordionSummary)``;
const SummaryIconTextWrapper = styled("div")`
${mixinFlex("row")}
column-gap:8px;
`;
const Detail = styled(AccordionDetails)`
${mixinFlex("column")};
align-items: start;
justify-content: start;
row-gap: 8px;
margin-left: 16px;
`;
const DetailBox = styled("div")`
${mixinFlex("row")}
width:100%;
justify-content: start;
column-gap: 8px;
font-size: 14px;
& svg {
width: 16px;
height: 16px;
}
&:hover {
background-color: ${({ theme }) => theme.palette.primary.main};
color: ${({ theme }) => theme.palette.gray[0]};
& svg {
color: ${({ theme }) => theme.palette.gray[0]};
}
}
`;
컴포넌트 사용 예시 코드
"use client";
import { styled, Typography } from "@mui/material";
import AccordionByCollege from "./AccordionByCollege";
import {
GavelOutlined,
MonitorHeartOutlined,
AccountBalanceOutlined,
SettingsOutlined,
TimelineOutlined,
PsychologyOutlined,
ScienceOutlined,
PaletteOutlined,
SchoolOutlined,
GrassOutlined,
WavesOutlined,
} from "@mui/icons-material";
import { mixinFlex } from "@/styles/mixins";
const MainContainer = () => {
const colleges = [
{ title: "인문대학", majors: ["철학", "역사학", "문학", "언어학", "사회학"], Icon: <AccountBalanceOutlined /> },
{ title: "사회과학대학", majors: ["정치학", "경제학", "행정학", "국제학", "심리학"], Icon: <PsychologyOutlined /> },
{ title: "자연과학대학", majors: ["물리학", "화학", "생물학", "수학", "지구과학"], Icon: <ScienceOutlined /> },
{
title: "공과대학",
majors: ["기계공학", "전기전자공학", "컴퓨터공학", "화학공학", "토목공학"],
Icon: <SettingsOutlined />,
},
{ title: "의과대학", majors: ["의학", "간호학", "의생명과학", "약학"], Icon: <MonitorHeartOutlined /> },
{ title: "법과대학", majors: ["법학", "경찰행정학", "사회복지학"], Icon: <GavelOutlined /> },
{ title: "예술대학", majors: ["미술", "음악", "무용", "연극", "디자인"], Icon: <PaletteOutlined /> },
{ title: "경상대학", majors: ["경영학", "회계학", "마케팅", "금융학"], Icon: <TimelineOutlined /> },
{ title: "교육대학", majors: ["초등교육", "유아교육", "특수교육"], Icon: <SchoolOutlined /> },
{ title: "농업대학", majors: ["농업경제학", "농업생명과학", "환경농업"], Icon: <GrassOutlined /> },
{ title: "해양과학대학", majors: ["해양학", "해양공학", "해양경찰학"], Icon: <WavesOutlined /> },
];
return (
<div>
<Typography variant="h3" color="primary" align="center" sx={{ fontWeight: "bold" }}>
ALLIN
</Typography>
<AccordionByCollegeContainer>
{colleges.map((el, idx) => (
<AccordionByCollege key={idx} title={el.title} majors={el.majors} Icon={el.Icon} />
))}
</AccordionByCollegeContainer>
</div>
);
};
export default MainContainer;
const AccordionByCollegeContainer = styled("div")`
${mixinFlex("row")};
align-items:start;
width: 100%;
flex-wrap: wrap;
`;