From 3a3a3705f4a6fdb90d7a1aae865700f061168161 Mon Sep 17 00:00:00 2001 From: y00eunji Date: Wed, 30 Apr 2025 09:02:49 +0900 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20MUI=20=ED=85=8C=EB=A7=88=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B8=80=EB=A1=9C=EB=B2=8C=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- emotion.d.ts | 6 +++ src/App.tsx | 15 +++++- src/styles/globalStyles.ts | 101 +++++++++++++++++++++++++++++++++++++ src/theme/index.ts | 39 ++++++++++++-- tsconfig.app.json | 2 +- 5 files changed, 156 insertions(+), 7 deletions(-) create mode 100644 emotion.d.ts create mode 100644 src/styles/globalStyles.ts diff --git a/emotion.d.ts b/emotion.d.ts new file mode 100644 index 0000000..9ea5bd3 --- /dev/null +++ b/emotion.d.ts @@ -0,0 +1,6 @@ +import "@emotion/react"; +import { Theme as MuiTheme } from "@mui/material/styles"; + +declare module "@emotion/react" { + export interface Theme extends MuiTheme {} +} diff --git a/src/App.tsx b/src/App.tsx index b7ec56c..41425f5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,18 @@ -import Test from "./components/Test"; +import { Global } from "@emotion/react"; +import { ThemeProvider } from "@mui/material/styles"; +import { CssBaseline } from "@mui/material"; +import { muiTheme, globalStyles } from "./styles/globalStyles"; + +import Header from "./components/layout/Header"; function App() { - return ; + return ( + + + +
+ + ); } export default App; diff --git a/src/styles/globalStyles.ts b/src/styles/globalStyles.ts new file mode 100644 index 0000000..7680e35 --- /dev/null +++ b/src/styles/globalStyles.ts @@ -0,0 +1,101 @@ +import { css } from "@emotion/react"; +import { createTheme } from "@mui/material/styles"; + +export const muiTheme = createTheme({ + typography: { + fontFamily: + 'Pretendard, -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif', + }, + palette: { + primary: { + main: "#259299", + light: "#B6D8D7", + dark: "#126D7F", + }, + secondary: { + main: "#259299", + light: "#B6D8D7", + dark: "#126D7F", + }, + text: { + primary: "#000000", + secondary: "#666666", + disabled: "#999999", + }, + background: { + default: "#FFFFFF", + paper: "#FFFFFF", + }, + common: { + black: "#000000", + white: "#FFFFFF", + }, + error: { + main: "#d32f2f", + light: "#ef5350", + dark: "#c62828", + }, + warning: { + main: "#ed6c02", + light: "#ff9800", + dark: "#e65100", + }, + info: { + main: "#0288d1", + light: "#03a9f4", + dark: "#01579b", + }, + success: { + main: "#2e7d32", + light: "#4caf50", + dark: "#1b5e20", + }, + }, +}); + +export const globalStyles = css` + @import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css"); + + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + html, + body { + font-family: + "Pretendard", + -apple-system, + BlinkMacSystemFont, + system-ui, + Roboto, + "Helvetica Neue", + "Segoe UI", + "Apple SD Gothic Neo", + "Noto Sans KR", + "Malgun Gothic", + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + a { + text-decoration: none; + color: inherit; + } + + button { + border: none; + background: none; + cursor: pointer; + } + + ul, + ol { + list-style: none; + } +`; diff --git a/src/theme/index.ts b/src/theme/index.ts index f6dde35..73a8311 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -2,12 +2,43 @@ import { createTheme } from "@mui/material"; export const theme = createTheme({ palette: { - mode: "light", primary: { - main: "#1976d2", + main: "#259299", + light: "#B6D8D7", + dark: "#126D7F", }, - secondary: { - main: "#9c27b0", + text: { + primary: "#000000", + secondary: "#666666", + disabled: "#999999", + }, + background: { + default: "#FFFFFF", + paper: "#FFFFFF", + }, + common: { + black: "#000000", + white: "#FFFFFF", + }, + error: { + main: "#d32f2f", + light: "#ef5350", + dark: "#c62828", + }, + warning: { + main: "#ed6c02", + light: "#ff9800", + dark: "#e65100", + }, + info: { + main: "#0288d1", + light: "#03a9f4", + dark: "#01579b", + }, + success: { + main: "#2e7d32", + light: "#4caf50", + dark: "#1b5e20", }, }, }); diff --git a/tsconfig.app.json b/tsconfig.app.json index adadc51..ef21932 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -23,5 +23,5 @@ "noUncheckedSideEffectImports": true, "forceConsistentCasingInFileNames": false }, - "include": ["src"] + "include": ["src", "emotion.d.ts"] } From 0c0547128db18afede5b7804c6fac88a902b6224 Mon Sep 17 00:00:00 2001 From: y00eunji Date: Wed, 30 Apr 2025 09:20:45 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20Header=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EB=A7=88=ED=81=AC=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/langIcon.png | Bin 0 -> 2360 bytes src/assets/pyconLogo.png | Bin 0 -> 5231 bytes src/components/layout/Header/index.tsx | 79 +++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/assets/langIcon.png create mode 100644 src/assets/pyconLogo.png create mode 100644 src/components/layout/Header/index.tsx diff --git a/src/assets/langIcon.png b/src/assets/langIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..1157c55f03a509ce1f00332efcacf094325c23fe GIT binary patch literal 2360 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 eUACYfp8W%9yu?8oE-BIg0000(bQ literal 0 HcmV?d00001 diff --git a/src/assets/pyconLogo.png b/src/assets/pyconLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b1d5c7ba55221d98f756ea2197f70dab4a45a6d1 GIT binary patch literal 5231 zcmV-#6p-tQP)NU_4M@Kz5VZ#?AWm_OSYvf{Z5{3 z>23FZ_uub*F9h-jlKRbiKVRha`fGK4b{Ut>D5G?Cg+!`LI4v^>_W{@kOHNPX&XnmQ$? zWaf%Mab3{?^BU~)e7o!FizNBSwNyI275mf9IX5{cy$6m3z3jM<%u8z+(rmFjZz3RzVmt0 z`2M}I?hheHM2=Ty`WpA|e!uS;o&Vo7i7wg47>^@yVqdOp#Sjf*Le-~GiN-iTyw*ru zf1eh455JNi$u)y(C#kpcMjbGW_i?3H~ukYu~(ao7blZ`u}AS6<-HB*x5KGR$~FB-ZL zjt=msrE#d8kK6VzZgd};R(wc1hY}t)x9iBzY z74>}#7YsQ`=*hs{AP8v;5F$GWeXpXsV=;`vE@snlOUys__-?BJ`pj;|4CMs0b=d-) zAH#s2`X%YWq;SV1$dbfNRoEi$3%74&0HkO3GL|?M$P*BeLL5nKW#&ZF7wBGd(z&oc?VJl2o<8;nHgUZi0oZ{pO^h#4J=f$nwqHT~QFKwUG z5hyJ$Ep;xH?4Q;#(~wSa@_K<%NOerxJDE9eo4epKNRl`#Ptq{o3$l!NsO@Vc&xL18 zCuN*6dXO0Qe=?;Dr%TFP8x8&7a0k+1zDsO%`&I`zD?e$2yfH!q+!$>bOBLn)A0!>h zkis?;H*}Tio_@DYt=omFdm`qw`2@1YorG?l5$XIkB!!C|v;WxRfvtBH)qllwoAftM zo`9(2Oro^PCBYl-8pfex_xD#}A&uq(-f0gd%uql+5lT^_NY=X@Cx}2BHPQSx#q|ax zBb@<4*Z%_&R;~W8oxOFK#Z8(o0ig@4`qeV+st6kUAf=EU}wbW?*|!-&Tq zaOG7{v;H^9nG4j9L~9TwuLKwpL6wnXc5dSQnFyt9M4o^kPpEG3 z%{PIwtO5zmeba?4#v0v zdf8aG6I_!{1Ig!uY+=Ttd7C&D!?aLRE)WX_K=?xOCAF8_?lvQ0Rv+>Tw11wn&xVDc zZi6ZJ-46@)?ir;=C4)Ypf`fw_;Nd#>Qk$D6u-6Rt^HG~iu`nQtbN3VM_P@uET<8FC zDBf?7c%Fk*VntULiLUwctj&_jV`ICaz8ea7n4fD%SOPk!9U7?@4p0xY6FcasaMy!> zm9Z$C#=2n=ZVFyINNo_q+6l>m(q@cX&zIEi{}*WQ%6|W>N(@ZxCJG~ge33}NXlqM4 zf;3qMm1K~M10xbxi4@eKKYWtb!e*rs8YDk-6BSgMB6X}UBM^a`0ivG-ig^z#K(lqJ z-Ut^O`@zI!v`{DR9hn1EV?LWo7m2@RYS`yVECy{DJgZ_3f1I>fkYmJpKu-(~i^MH9 zS5~IImGG%9j}I1wLogElRXH0rPC5^&0#0z4Juq9`14;i&-A*)(Dijy^F|!%GBxZ|T z2CpeqPyia-pzVaa;yXlHAA-n*l!i#56NUKi5_G?^D!b2+k-!6z+ZwI$0Krfs8ft^G zOP4_9!~X%wgtAfDHp|OeabkMk_E|`Wr&e7D*DXJP!1qGBZ@lJV*zoc@P*E}gFEy}# zcC?WbdDt4rXYHrMGxoXglh{Xat5yelr2-f(uoTCm9fZja$4uF#6wZ>k2@SLW;$-ZB zjOer=Z`Ru9A+T&|<~D3NWKc*@&;z%(cMm?5aajA}N@)9b7`AWQ18$KX4s{FM0w_d6 z>h5!#0~^#Dcp>r{N}?U&mdX!CI}Sz-&@)lx*%Wb!R_cI#)Hh~3s7Je@^5$EUT6Dg{{*XxAKFFp^nSbW6e1u-J@aiHv-<-5UJ z(P-y`?WbU=mdI7qAck0r3`Ip2gmOL?@FNQjJY914;k`AppyL*GmD|suW`xdUO;f^f(k=eI?`@ zkysdoJ-xIqIBOat%0q1p^1VFQJtT%vAa6|C%CP*%nw@Th$OOg6id zi*d7riD$VN%!hnINL?hN!R~#Zz!?jtr#-f$)DJGZ6S9TKUiMNyJc9Lu3LYJ>uZM$; z@_vz@19kmfWfE*rN{7_@ks!uLE-8V0K!hm5zFqsh2VhcJEzDa`n>Hx7*%fd*ooSC5 z3c@ftHwWWfdC|%x0+Fmf67~ zu$7W2mKhEw3!;5?lb{VUAVO8l9D0{DCx0obY=tK~>zd%!n^wWDJzJpZz*dVGlEz~T zvfVBhBs4Q?$1c2c5$k~m9cRLm(YK)qQ$zt_G-SfLj<;5O4;HadD@NigoQvR*o)1xc zy(n2(1lS}4=Yiyj4maF*3mkZ1J=O$cAV!jff+jvZbDRUMq!?WXMPo(Y*XwL>uk|d4LgDDrW)Se-Fslt7DnOM zwplO_bHyw41~^Dv8Rdvp&^uDbA;?49^(Vg{>w9W(WK; zs&XM#I2I=k!+tt)swX7Kh(tgxO=Aa9ZR-|)3v9juIQ!7SqnQSFj7Uc(2{WD6q8Wxu z;x>_J4@g9U(V_rDz1Nf}@MG#CDQKvIL1!%n)o;r@&lHZT4W5q6UeSfej*3kyQx2wJCiIF!Gc|?JJVHRTAyq*kJsSt>jx%r>jsJ_enlXZ?1p~JXgW*R7{c3Fjt`Go`@MtK{Nu14eN)^ zg$=yQy|e_!FZa1JPM}$N^2V1wf`*1BYkkI8A+8W2IID=Izec8fVqI}s`EBin8TDtQ zQ`Sl({Mm+OFfr#K<``zMc9;wipy9pnv+hGyIY}JZzu~*~G{dZ!*MS~;2PAoTk2q3b zJQ8}#ke`3H7v{~s8EPt~V1zaH2Q`J+646L~^kp_9qB*S$T+>_MP-O2?5sYSjp=1G~ z1S9lbGCz|_;UiKGac325n0PI`_vh7c+LY1(=M}hBkTB;SDXJ9YwKR7^YfC3eQFft+ zj04ltqro#zyb4b|`vTOISB(pKy}*9+R?heAMdxl27}X9uUF;&+)H7nxjO(H35!YOeWe> zJ#Q~llQTS?n>4;D+$nsX-vTSAt-%QeJsU4mvR(DF+4PXQW)1Y-Z{bWN|_BuS1X z*;Xsk!LnnN4D`6X??+mQ48!hFt!*Uab2&hiNW9n#9eD^~AN0%oNhHzm6D3(?IDX4P z(?E=CZ{8b^Cv)cUv}+lI+Q`9J+v?OO-bY|C^!aui_BNiE^|aZ`jBs#Wp(vCGz6)OG zIT)IJnAQa32)qJAzSp7sDM)oA$(2(>VtH>=&un8dan4=0{{nPff+-WG z!VSys?~_0gF6C(%HP=jScXOmU*w?OpJL#d&+s{eFhLvibGu;p_D%cscO7SeqHGSW? zcmcF`H=+YN1ket}6>o$Sc<%S%C zDT*)A*z&@)aP-X|g9x$~PtT~lvrCV6IIVmo2N3Fbq%8>Z{%$(F^y-5UC@IM3y#Coq zds`S*-1RuDUH>}NR8Gbj!JIBM=TuUOsYmW;XnX0&{yTQOqjZgJIaW=P+#DvJ3vW zX&da=Sr3KoV(@$2eFcM@fpb$)Jx6vOd|G4x1D+!ul0e*8P1%hfV}1Edo_a-7t{@~z zNKZ$!6MEutYw4qkWie4(WY%*cSn_4b2PRcX2A9nZKDW~v0G=1m!410-kb~WSncCX* zK@%MF=A)rh)OzGS(Y*gW=fqjDxZZB$N|mkVAqlb~K}kU%>+^CC!m!jQck2fqMDiM7 z2yGlLkm4cu+OWxmTb%X@H=0Z{GMjEY#X!W{;+*w+Tb>t=L)82RMJMSZQ7IhTx2MQ) zdM)b9T%Ih|-;k||DQy)m4 z(^f9GYJZ*xLp9}I5oonjoe-lU%{h+|1l*;53 zB#~oIWJmJ4^~Qyb!8hNBeothkLpDyqBD=J7jw7Ict5eg1Qu1_uvU_JP93*O&6bP?l`z>M<3CY?nql5?1l_qx(JfuU=pZgpb!k=P%~gTcDql}8z; zHlqnkl21~hZJagXjyDrDexaG@$!V~i8!!VW(qw9qx9gjK^&J@Ht3k&S*I7AXbYqIxgG3ZK(pF|6~A-y`~jP>y9M zB37B9#2<_#4m_zO^vAyrZ5EGurWOxCPO7f?sICl{`78A=I9-LJ>+SZED`e`d!RSXZ z%$U$P?7R-W)9}Zx(-8$$o@%m$b1FnEODAHPPa+i8+qP=jk##+!`;~CGzN6oLPul;C zV5Iw{I<<;AozIqe)zVtiAafkHl4{1{l~i^VtCFvjgDDm+a;#dn_rzO*NMZ|~*$|C4 pe+8g_p}KART3U8QhrfRA@mIf(G3s~Q9@GE;002ovPDHLkV1lE`%VGck literal 0 HcmV?d00001 diff --git a/src/components/layout/Header/index.tsx b/src/components/layout/Header/index.tsx new file mode 100644 index 0000000..e9174ab --- /dev/null +++ b/src/components/layout/Header/index.tsx @@ -0,0 +1,79 @@ +import styled from "@emotion/styled"; + +export default function Header() { + return ( + + + pyconLogo + + + + + + langIcon + KO + EN + +
로그인
+
+
+ ); +} + +const HeaderContainer = styled.header` + background-color: ${({ theme }) => theme.palette.primary.light}; + font-color: ${({ theme }) => theme.palette.primary.dark}; + font-size: 0.8125rem; + font-weight: 500; + width: 100%; + height: 3.625rem; + padding: 0.5625rem 7.125rem; + display: flex; + justify-content: space-between; + align-items: center; +`; + +const HeaderLogo = styled.div` + display: flex; + align-items: center; + justify-content: center; +`; + +const HeaderNav = styled.ul` + display: flex; + align-items: center; + gap: 2rem; + font-size: 0.875rem; + font-weight: 500; +`; + +const HeaderLeft = styled.div` + display: flex; + align-items: center; + gap: 1.125rem; +`; + +const HeaderItem = styled.div` + display: flex; + align-items: center; + gap: 0.625rem; +`; From 764e90dd66ca72dfc67b161b13a66ae3a8b96136 Mon Sep 17 00:00:00 2001 From: y00eunji Date: Fri, 2 May 2025 09:27:51 +0900 Subject: [PATCH 3/8] =?UTF-8?q?feat:=20react-router-dom=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EA=B5=AC=EC=84=B1=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 +- pnpm-lock.yaml | 51 +++++++++ src/App.tsx | 15 ++- src/assets/Footer/blog.svg | 3 + src/assets/Footer/facebook.svg | 3 + src/assets/Footer/flickr.svg | 3 + src/assets/Footer/github.svg | 3 + src/assets/Footer/instagram.svg | 3 + src/assets/Footer/linkedin.svg | 3 + src/assets/Footer/message.svg | 3 + src/assets/Footer/x.svg | 8 ++ src/assets/Footer/youtube.svg | 3 + src/components/layout/Footer/index.tsx | 143 +++++++++++++++++++++++++ src/components/layout/Header/index.tsx | 2 +- src/components/layout/index.tsx | 15 +++ vite.config.ts | 4 +- 16 files changed, 257 insertions(+), 8 deletions(-) create mode 100644 src/assets/Footer/blog.svg create mode 100644 src/assets/Footer/facebook.svg create mode 100644 src/assets/Footer/flickr.svg create mode 100644 src/assets/Footer/github.svg create mode 100644 src/assets/Footer/instagram.svg create mode 100644 src/assets/Footer/linkedin.svg create mode 100644 src/assets/Footer/message.svg create mode 100644 src/assets/Footer/x.svg create mode 100644 src/assets/Footer/youtube.svg create mode 100644 src/components/layout/Footer/index.tsx create mode 100644 src/components/layout/index.tsx diff --git a/package.json b/package.json index 1e11a03..6ca1e40 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.2", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "react-router-dom": "^7.5.3" }, "devDependencies": { "@eslint/js": "^9.21.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 51e9b12..06d6025 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: react-dom: specifier: ^19.0.0 version: 19.1.0(react@19.1.0) + react-router-dom: + specifier: ^7.5.3 + version: 7.5.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) devDependencies: '@eslint/js': specifier: ^9.21.0 @@ -1001,6 +1004,10 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} + cosmiconfig@7.1.0: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} @@ -2077,6 +2084,23 @@ packages: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} + react-router-dom@7.5.3: + resolution: {integrity: sha512-cK0jSaTyW4jV9SRKAItMIQfWZ/D6WEZafgHuuCb9g+SjhLolY78qc+De4w/Cz9ybjvLzShAmaIMEXt8iF1Cm+A==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + + react-router@7.5.3: + resolution: {integrity: sha512-3iUDM4/fZCQ89SXlDa+Ph3MevBrozBAI655OAfWQlTm9nBR0IKlrmNwFow5lPHttbwvITZfkeeeZFP6zt3F7pw==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + react-transition-group@4.4.5: resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} peerDependencies: @@ -2167,6 +2191,9 @@ packages: engines: {node: '>=10'} hasBin: true + set-cookie-parser@2.7.1: + resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -2303,6 +2330,9 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + turbo-stream@2.4.0: + resolution: {integrity: sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -3388,6 +3418,8 @@ snapshots: convert-source-map@2.0.0: {} + cookie@1.0.2: {} + cosmiconfig@7.1.0: dependencies: '@types/parse-json': 4.0.2 @@ -4803,6 +4835,21 @@ snapshots: react-refresh@0.14.2: {} + react-router-dom@7.5.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-router: 7.5.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + + react-router@7.5.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + cookie: 1.0.2 + react: 19.1.0 + set-cookie-parser: 2.7.1 + turbo-stream: 2.4.0 + optionalDependencies: + react-dom: 19.1.0(react@19.1.0) + react-transition-group@4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@babel/runtime': 7.27.0 @@ -4963,6 +5010,8 @@ snapshots: semver@7.7.1: {} + set-cookie-parser@2.7.1: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -5119,6 +5168,8 @@ snapshots: tslib@2.8.1: {} + turbo-stream@2.4.0: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 diff --git a/src/App.tsx b/src/App.tsx index 41425f5..bf1da0c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,16 +1,23 @@ -import { Global } from "@emotion/react"; +import { BrowserRouter, Routes, Route } from "react-router-dom"; import { ThemeProvider } from "@mui/material/styles"; import { CssBaseline } from "@mui/material"; +import { Global } from "@emotion/react"; import { muiTheme, globalStyles } from "./styles/globalStyles"; - -import Header from "./components/layout/Header"; +import MainLayout from "./components/layout"; +import Test from "./components/Test"; function App() { return ( -
+ + + }> + } /> + + + ); } diff --git a/src/assets/Footer/blog.svg b/src/assets/Footer/blog.svg new file mode 100644 index 0000000..ecb62c2 --- /dev/null +++ b/src/assets/Footer/blog.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/Footer/facebook.svg b/src/assets/Footer/facebook.svg new file mode 100644 index 0000000..95bbb43 --- /dev/null +++ b/src/assets/Footer/facebook.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/Footer/flickr.svg b/src/assets/Footer/flickr.svg new file mode 100644 index 0000000..cae2f99 --- /dev/null +++ b/src/assets/Footer/flickr.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/Footer/github.svg b/src/assets/Footer/github.svg new file mode 100644 index 0000000..d429ea8 --- /dev/null +++ b/src/assets/Footer/github.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/Footer/instagram.svg b/src/assets/Footer/instagram.svg new file mode 100644 index 0000000..dd65c88 --- /dev/null +++ b/src/assets/Footer/instagram.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/Footer/linkedin.svg b/src/assets/Footer/linkedin.svg new file mode 100644 index 0000000..7e2ad8e --- /dev/null +++ b/src/assets/Footer/linkedin.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/Footer/message.svg b/src/assets/Footer/message.svg new file mode 100644 index 0000000..69646e0 --- /dev/null +++ b/src/assets/Footer/message.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/Footer/x.svg b/src/assets/Footer/x.svg new file mode 100644 index 0000000..8d47316 --- /dev/null +++ b/src/assets/Footer/x.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/Footer/youtube.svg b/src/assets/Footer/youtube.svg new file mode 100644 index 0000000..d130f81 --- /dev/null +++ b/src/assets/Footer/youtube.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/layout/Footer/index.tsx b/src/components/layout/Footer/index.tsx new file mode 100644 index 0000000..6ff8f33 --- /dev/null +++ b/src/components/layout/Footer/index.tsx @@ -0,0 +1,143 @@ +import styled from "@emotion/styled"; + +interface LinkItem { + text: string; + href: string; +} + +interface FooterProps { + slogan?: string; + description?: string; + links?: LinkItem[]; +} + +export default function Footer({ + slogan = "Weave with Python, 파이콘 한국 2025", + description = "파이콘 한국 2025는 파이콘 한국 준비위원회가 만들고 있습니다\n파이썬 웹 프레임워크 Django로 만들었습니다", + links = [ + { text: "파이콘 한국 행동 강령(CoC)", href: "#" }, + { text: "서비스 이용 약관", href: "#" }, + { text: "개인 정보 처리 방침", href: "#" }, + ], +}: FooterProps) { + return ( + + + {slogan} + {description.split("\n").map((line, index) => ( +
{line}
+ ))} + + {links.map((link, index) => ( + <> + + {link.text} + + {index < links.length - 1 && |} + + ))} + + + message + facebook + youtube + x + + github + instagram + linkedin + blog + flickr + +
+
+ ); +} + +const FooterContainer = styled.footer` + background-color: ${({ theme }) => theme.palette.primary.main}; + color: ${({ theme }) => theme.palette.common.white}; + font-size: 0.75rem; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + height: 267px; +`; + +const FooterContent = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.75rem; +`; + +const FooterSlogan = styled.div` + font-weight: 600; +`; + +const FooterLinks = styled.div` + display: flex; + align-items: center; + gap: 0.625rem; +`; +const FooterIcons = styled.div` + display: flex; + align-items: center; + gap: 9px; +`; + +const Link = styled.a` + color: ${({ theme }) => theme.palette.common.white}; + text-decoration: none; + &:hover { + text-decoration: underline; + } +`; + +const Separator = styled.span` + color: ${({ theme }) => theme.palette.common.white}; + opacity: 0.5; +`; diff --git a/src/components/layout/Header/index.tsx b/src/components/layout/Header/index.tsx index e9174ab..5a9d5c8 100644 --- a/src/components/layout/Header/index.tsx +++ b/src/components/layout/Header/index.tsx @@ -41,7 +41,7 @@ export default function Header() { const HeaderContainer = styled.header` background-color: ${({ theme }) => theme.palette.primary.light}; - font-color: ${({ theme }) => theme.palette.primary.dark}; + color: ${({ theme }) => theme.palette.primary.dark}; font-size: 0.8125rem; font-weight: 500; width: 100%; diff --git a/src/components/layout/index.tsx b/src/components/layout/index.tsx new file mode 100644 index 0000000..dfe5c1d --- /dev/null +++ b/src/components/layout/index.tsx @@ -0,0 +1,15 @@ +import { Outlet } from "react-router-dom"; +import Header from "./Header"; +import Footer from "./Footer"; + +export default function MainLayout() { + return ( + <> +
+
+ +
+