Skip to content

Commit 7ff0cc8

Browse files
authored
Merge pull request #23 from pythonkr/feature/add-styled-details
feat: 스타일링된 `Accordion` 추가
2 parents 9aefdcc + 99c004d commit 7ff0cc8

File tree

9 files changed

+195
-2
lines changed

9 files changed

+195
-2
lines changed

apps/pyconkr-admin/src/consts/mdx_components.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ const MUIMDXComponents: MDXComponents = {
131131
};
132132

133133
const PyConKRCommonMDXComponents: MDXComponents = {
134+
Common__Components__MDX__PrimaryStyledDetails: Common.Components.MDX.PrimaryStyledDetails,
135+
Common__Components__MDX__SecondaryStyledDetails: Common.Components.MDX.SecondaryStyledDetails,
134136
Common__Components__MDX__Map: Common.Components.MDX.Map,
135137
};
136138

apps/pyconkr/src/components/pages/test.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import { Button, Stack } from "@mui/material";
22
import * as React from "react";
33

44
import { BackendTestPage } from "../../debug/page/backend_test";
5+
import { ComponentTestPage } from "../../debug/page/component_test";
56
import { MapTestPage } from "../../debug/page/map_test";
67
import { MdiTestPage } from "../../debug/page/mdi_test";
78
import { ShopTestPage } from "../../debug/page/shop_test";
89

910
const LOCAL_STORAGE_KEY = "selectedTab";
10-
type SelectedTabType = "shop" | "mdi" | "backend" | "map";
11+
type SelectedTabType = "shop" | "mdi" | "backend" | "map" | "component";
1112

1213
const getTabFromLocalStorage = (): SelectedTabType =>
1314
(localStorage.getItem(LOCAL_STORAGE_KEY) as SelectedTabType) || "shop";
@@ -22,6 +23,7 @@ const TabList: { [key in SelectedTabType]: React.ReactNode } = {
2223
mdi: <MdiTestPage />,
2324
backend: <BackendTestPage />,
2425
map: <MapTestPage />,
26+
component: <ComponentTestPage />,
2527
};
2628

2729
export const Test: React.FC = () => {

apps/pyconkr/src/consts/mdx_components.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ const MUIMDXComponents: MDXComponents = {
131131
};
132132

133133
const PyConKRCommonMDXComponents: MDXComponents = {
134+
Common__Components__MDX__PrimaryStyledDetails: Common.Components.MDX.PrimaryStyledDetails,
135+
Common__Components__MDX__SecondaryStyledDetails: Common.Components.MDX.SecondaryStyledDetails,
134136
Common__Components__MDX__Map: Common.Components.MDX.Map,
135137
};
136138

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import * as Common from "@frontend/common";
2+
import { Chip, Stack, Table, TableBody, TableCell, TableRow } from "@mui/material";
3+
import * as React from "react";
4+
5+
const HighlightedChip: React.FC<{ label: string }> = ({ label }) => (
6+
<Chip
7+
label={label}
8+
sx={(theme) => ({
9+
borderColor: theme.palette.highlight.light,
10+
backgroundColor: theme.palette.highlight.main,
11+
color: "#fff",
12+
fontWeight: 600,
13+
})}
14+
/>
15+
);
16+
17+
export const ComponentTestPage: React.FC = () => {
18+
return (
19+
<Stack direction="column" spacing={2} sx={{ p: 2 }}>
20+
<Common.Components.MDX.PrimaryStyledDetails summary="자가용 이용시">
21+
모든 자동차의 출입은 동국대 정문으로만 가능
22+
<Table>
23+
<TableBody>
24+
<TableRow>
25+
<TableCell>
26+
<HighlightedChip label="분당방면" />
27+
</TableCell>
28+
<TableCell>한남대교 → 남산국립극장 400m 전방 → 동국대 정문</TableCell>
29+
</TableRow>
30+
<TableRow>
31+
<TableCell>
32+
<HighlightedChip label="강남방면" />
33+
</TableCell>
34+
<TableCell>동호대교 → 장충체육관 앞 사거리에서 좌회전 300m 전방 → 동국대 정문</TableCell>
35+
</TableRow>
36+
<TableRow>
37+
<TableCell>
38+
<HighlightedChip label="용산방면" />
39+
</TableCell>
40+
<TableCell>남산 2호터널 통과 후 좌회전 100m 전방 → 동국대 정문</TableCell>
41+
</TableRow>
42+
<TableRow>
43+
<TableCell>
44+
<HighlightedChip label="동대문방면" />
45+
</TableCell>
46+
<TableCell>장충사거리 200m 전방 → 동국대 정문</TableCell>
47+
</TableRow>
48+
</TableBody>
49+
</Table>
50+
</Common.Components.MDX.PrimaryStyledDetails>
51+
52+
<Common.Components.MDX.SecondaryStyledDetails summary="자가용 이용시">
53+
모든 자동차의 출입은 동국대 정문으로만 가능
54+
<Table>
55+
<TableBody>
56+
<TableRow>
57+
<TableCell>
58+
<HighlightedChip label="분당방면" />
59+
</TableCell>
60+
<TableCell>한남대교 → 남산국립극장 400m 전방 → 동국대 정문</TableCell>
61+
</TableRow>
62+
<TableRow>
63+
<TableCell>
64+
<HighlightedChip label="강남방면" />
65+
</TableCell>
66+
<TableCell>동호대교 → 장충체육관 앞 사거리에서 좌회전 300m 전방 → 동국대 정문</TableCell>
67+
</TableRow>
68+
<TableRow>
69+
<TableCell>
70+
<HighlightedChip label="용산방면" />
71+
</TableCell>
72+
<TableCell>남산 2호터널 통과 후 좌회전 100m 전방 → 동국대 정문</TableCell>
73+
</TableRow>
74+
<TableRow>
75+
<TableCell>
76+
<HighlightedChip label="동대문방면" />
77+
</TableCell>
78+
<TableCell>장충사거리 200m 전방 → 동국대 정문</TableCell>
79+
</TableRow>
80+
</TableBody>
81+
</Table>
82+
</Common.Components.MDX.SecondaryStyledDetails>
83+
</Stack>
84+
);
85+
};

apps/pyconkr/src/styles/globalStyles.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ export const muiTheme = createTheme({
1818
light: "#B6D8D7",
1919
dark: "#126D7F",
2020
},
21+
highlight: {
22+
main: "#E17101",
23+
light: "#EE8D74",
24+
dark: "#C66900",
25+
contrastText: "#FFFFFF",
26+
},
2127
text: {
2228
primary: "#000000",
2329
secondary: "#666666",

packages/common/src/components/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import { ErrorFallback as ErrorFallbackComponent } from "./error_handler";
99
import { MDXRenderer as MDXRendererComponent } from "./mdx";
1010
import type { MapPropType as MapComponentPropType } from "./mdx_components/map";
1111
import { Map as MapComponent } from "./mdx_components/map";
12+
import {
13+
PrimaryStyledDetails as PrimaryStyledDetailsComponent,
14+
HighlightedStyledDetails as SecondaryStyledDetailsComponent,
15+
} from "./mdx_components/styled_details";
1216
import { MDXEditor as MDXEditorComponent } from "./mdx_editor";
1317
import { PythonKorea as PythonKoreaComponent } from "./pythonkorea";
1418

@@ -24,6 +28,8 @@ namespace Components {
2428
export const ErrorFallback = ErrorFallbackComponent;
2529

2630
export namespace MDX {
31+
export const PrimaryStyledDetails = PrimaryStyledDetailsComponent;
32+
export const SecondaryStyledDetails = SecondaryStyledDetailsComponent;
2733
export const Map = MapComponent;
2834
export type MapPropType = MapComponentPropType;
2935
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { ExpandMore } from "@mui/icons-material";
2+
import {
3+
Accordion,
4+
AccordionActions,
5+
AccordionDetails,
6+
AccordionSummary,
7+
PaletteColor,
8+
styled,
9+
SxProps,
10+
Typography,
11+
useTheme,
12+
} from "@mui/material";
13+
import * as React from "react";
14+
15+
type StyledDetailsProps = React.PropsWithChildren<{
16+
expandIcon?: React.ReactNode;
17+
open?: boolean;
18+
summary?: React.ReactNode;
19+
actions?: React.ReactNode;
20+
}>;
21+
22+
type BaseStyledDetailsProps = StyledDetailsProps & {
23+
paletteColor: PaletteColor;
24+
transparencyOnExpand?: number;
25+
};
26+
27+
const BaseStyledDetails: React.FC<BaseStyledDetailsProps> = ({
28+
expandIcon,
29+
open,
30+
summary,
31+
children,
32+
actions,
33+
paletteColor,
34+
transparencyOnExpand,
35+
}) => {
36+
const StyledAccordion = styled(Accordion)(({ theme }) => ({
37+
width: "100%",
38+
paddingRight: theme.spacing(1),
39+
paddingLeft: theme.spacing(1),
40+
border: `1px solid ${paletteColor.dark}`,
41+
borderRadius: "0.5rem",
42+
fontWeight: 500,
43+
}));
44+
45+
const StyledAccordionSummary = styled(AccordionSummary)(() => ({
46+
color: paletteColor.dark,
47+
}));
48+
49+
const rootSx: SxProps = {
50+
transition: "background-color 0.3s ease",
51+
"&.Mui-expanded": {
52+
backgroundColor: `color-mix(in srgb, ${paletteColor.light} ${transparencyOnExpand || 10}%, transparent)`,
53+
},
54+
};
55+
56+
const DefaultExpandIcon = styled(ExpandMore)(({ theme }) => ({
57+
color: paletteColor.dark,
58+
fontSize: theme.typography.h4.fontSize,
59+
}));
60+
61+
return (
62+
<StyledAccordion expanded={open} disableGutters square elevation={0} slotProps={{ root: { sx: rootSx } }}>
63+
{summary && (
64+
<StyledAccordionSummary expandIcon={expandIcon || <DefaultExpandIcon />}>
65+
{typeof summary === "string" ? <Typography variant="h5">{summary}</Typography> : summary}
66+
</StyledAccordionSummary>
67+
)}
68+
<AccordionDetails sx={{ pt: "0", pb: "1rem", px: "2rem" }}>{children}</AccordionDetails>
69+
{actions && <AccordionActions sx={{ pt: "0", pb: "1rem", px: "2rem" }}>{actions}</AccordionActions>}
70+
</StyledAccordion>
71+
);
72+
};
73+
74+
export const PrimaryStyledDetails: React.FC<StyledDetailsProps> = (props) => {
75+
const { palette } = useTheme();
76+
return <BaseStyledDetails {...props} paletteColor={palette.primary} transparencyOnExpand={20} />;
77+
};
78+
79+
export const HighlightedStyledDetails: React.FC<StyledDetailsProps> = (props) => {
80+
const { palette } = useTheme();
81+
return <BaseStyledDetails {...props} paletteColor={palette.highlight} transparencyOnExpand={10} />;
82+
};

packages/common/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
"strict": true,
99
"jsx": "react"
1010
},
11-
"include": ["src"]
11+
"include": ["src", "vite.config.ts", "vite-env.d.ts", "../../types"],
1212
}

types/emotion.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ import "@emotion/react";
22
import { type Theme as MuiTheme } from "@mui/material/styles";
33

44
declare module "@mui/material/styles" {
5+
interface Palette {
6+
highlight: PaletteColor;
7+
}
8+
9+
interface PaletteOptions {
10+
highlight: PaletteColor;
11+
}
12+
513
interface PaletteColor {
614
nonFocus?: string;
715
}

0 commit comments

Comments
 (0)