From 4b5de3d17e30c1fc245d87dcf1fb7329b40cf56e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=ED=98=84=EC=A7=80?= Date: Sun, 12 Nov 2023 01:51:37 +0900 Subject: [PATCH] Feat: Skill page UI --- .env | 2 +- .gitignore | 1 + public/favicon.ico | Bin 3870 -> 0 bytes public/favicon.png | Bin 0 -> 18974 bytes {src/images => public/images/intro}/wave.svg | 0 public/images/skillset/arrow.png | Bin 0 -> 2812 bytes public/images/skillset/css3.svg | 1 + public/images/skillset/django.svg | 1 + public/images/skillset/figma.svg | 14 +++ public/images/skillset/firebase.svg | 1 + public/images/skillset/github.svg | 1 + public/images/skillset/html.svg | 1 + public/images/skillset/js.svg | 1 + public/images/skillset/python.svg | 1 + public/images/skillset/qnet.svg | 38 ++++++ public/images/skillset/react.svg | 1 + public/images/skillset/slack.svg | 1 + public/images/skillset/sqld.svg | 58 +++++++++ public/images/skillset/styled-components.svg | 1 + public/images/skillset/ts.svg | 1 + public/images/skillset/zeplin.svg | 1 + public/index.html | 6 +- src/GlobalStyle.tsx | 1 + src/components/HeaderMenu.tsx | 6 +- src/components/Intro/Title.tsx | 5 +- src/components/Intro/WaveBackground.tsx | 6 +- src/components/Skill/ClickMessage.tsx | 47 +++++++ src/components/Skill/RotateSkillCube.tsx | 125 +++++++++++++++++++ src/components/Skill/SkillData.tsx | 72 +++++++++++ src/components/Skill/SkillDetail.tsx | 95 ++++++++++++++ src/components/common/DownButton.tsx | 8 +- src/pages/About.tsx | 14 ++- src/pages/Project.tsx | 1 - src/pages/Skill.tsx | 4 +- 34 files changed, 493 insertions(+), 22 deletions(-) delete mode 100644 public/favicon.ico create mode 100644 public/favicon.png rename {src/images => public/images/intro}/wave.svg (100%) create mode 100644 public/images/skillset/arrow.png create mode 100644 public/images/skillset/css3.svg create mode 100644 public/images/skillset/django.svg create mode 100644 public/images/skillset/figma.svg create mode 100644 public/images/skillset/firebase.svg create mode 100644 public/images/skillset/github.svg create mode 100644 public/images/skillset/html.svg create mode 100644 public/images/skillset/js.svg create mode 100644 public/images/skillset/python.svg create mode 100644 public/images/skillset/qnet.svg create mode 100644 public/images/skillset/react.svg create mode 100644 public/images/skillset/slack.svg create mode 100644 public/images/skillset/sqld.svg create mode 100644 public/images/skillset/styled-components.svg create mode 100644 public/images/skillset/ts.svg create mode 100644 public/images/skillset/zeplin.svg create mode 100644 src/components/Skill/ClickMessage.tsx create mode 100644 src/components/Skill/RotateSkillCube.tsx create mode 100644 src/components/Skill/SkillData.tsx create mode 100644 src/components/Skill/SkillDetail.tsx diff --git a/.env b/.env index eac3d14..a7998db 100644 --- a/.env +++ b/.env @@ -3,4 +3,4 @@ REACT_APP_authDomain= "fe-portfolio-1bd36.firebaseapp.com" REACT_APP_projectId= "fe-portfolio-1bd36" REACT_APP_storageBucket= "fe-portfolio-1bd36.appspot.com" REACT_APP_messagingSenderId= "45357718536" -REACT_APP_appId= "1:45357718536:web:baf536d9d51fafb5e0c5bd \ No newline at end of file +REACT_APP_appId= "1:45357718536:web:baf536d9d51fafb5e0c5bd" diff --git a/.gitignore b/.gitignore index 4d29575..f21726c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ .env.development.local .env.test.local .env.production.local +.env npm-debug.log* yarn-debug.log* diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index a11777cc471a4344702741ab1c8a588998b1311a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/public/favicon.png b/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..dbaf795881bbbfe2101a3c1f4810334c67f5b9cd GIT binary patch literal 18974 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 Jr}zJV202FgJ3;^e literal 0 HcmV?d00001 diff --git a/src/images/wave.svg b/public/images/intro/wave.svg similarity index 100% rename from src/images/wave.svg rename to public/images/intro/wave.svg diff --git a/public/images/skillset/arrow.png b/public/images/skillset/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..398104606c2ef0ab3db20288297399cbd2aa2cbf GIT binary patch literal 2812 zcmcImdpuNWA3t-<%#K5a!Ry+4qSmFDL5ays zG*OW@Y+2+wskSLnTe&O-DQtyYqjh^nm)&>w^ZvW%e9n2k=Xbu}@ALcpp3mnw=LFSd z`wB=40svqIWrqU|01zk{PQjpM_t7Vd`mzBTV(V-R0Hu=6sFQDGgxxHAdn(1=9;R|4 zgIQrr05CiqNT(a`*kCAOsL<(>$LozCP7Ez225Ucz7R`hCq;D%Ttc1 z-V!r>{BKRw@GbnnI5>LtMSl<)?YI)IS$kVlgp`yZZk}t}1(AnQ{Medmjr-2p# z`$SdibW{x*6;wP7bV!)88DV%3?PS40pw%|Av*zt834+#vg|TX zW&y}gaR6|Tjeu=XWB?PUgfl{zG$teHkSqj>z^@zxN+kCc11Zb=)c?r0$Q+wk9$s88 zXD32nWVk6~*~63<&R!+}Havn1hBLVgm=_)v5k=q;^*%8OGQ1qd>A{~U+)$#PmopW% zkK{06OH;flUXKL9Fl@sK3MSAT9KXnAPei@_TrQh{!^OnJn8sL`Msh-MX4cl$IJ`N| z+}uRQFo`-8!DaAFBBJy^n|$?gU`7RUSZppUG6G)qWduZi$0h3NEl>2v@i|W}EBMcu zBBH*OB`XlO{03)cipTvwnXK49^81U5$6$XJeX8p7WH!rI1Xm7=DNA=bDUzAZC;Pv| z{!GqB=1#EZFd5uPjz?r<80qipWrO=WfQ6pQ5tnk|3G#>q3zrw>^hd z0N|Sy6bD-m9%4j#;*8Kz33%#kytLGG;vlp)n2-3yu6@_J&^TqnzRJTF{LW8K4{QaI z7$uk-2O$0tFl*mey0t~9wBNq3H%N=K@ec2m(yaEQpR0`1)f1*xAId(UN)q^Kc+H$g zr9q9Id|$tHP{X2M)p02newr2cw#!?L7LFDgB#xXJ81`H{tHZ_@jYcSRn?P@XiOsDT zfuT;e~QiZcT!2jQA;kE9r;^f`LIozz;_==+xc;=dIgn$1+k0hfp z2D=C2WFj(j(mj@HFy=>gn~mt-xfiTQ*Xpe5!zE~&?uCa!6ehMLX#1eE_ZG{)RuwRB zPRu(>=u+{sa(RAtW4g<}o+Ge&3ySBAloRMGVcj0Jyig*WJ zC)z;CO=Fnv+`$hc3!@E0cw};OuR8|a>USOtWqAA7_&U6}Of+(!ye+ICPYLp(Bb{o- zIyJ-Q^+3oTxL&#nky5?iQJm~cHiXge+k9)j#6a-oLyAGt;KZ+qAo6OL1QFa&9XFHO zcqb0b(=d-OHVl$AVhg{hAAkQ?R={cLl`{GBsyrW9&}(rQR~8igre-f9>E&AP$wv9K zN`X36V`bxYLmhFI&G+Jre*Ejj@%0Z`oL;-*m<^~tigJgZFBT@(RYQ2SH~BH`e$MrhJGwH)jnM0ys*(1p9fVR-^lOoCp7QV3SLvd9Bet98B~WY zEqG0O`>JT6#UmPbVP&WefZ z!Rh(n&Dq#l!?MAS2LcmIL*hr~t8=RZpKOwjHO;>HxG%OH?HAkHh38eW`VJ{vwv-^sjS;HK62IHlV#DM9a>O_8*5vH{JbAhx~48&dgfgSuAA{v zK64zJD%MaXx31$?BJ)$@QK|hFAkEE->ro4>S;+0~NL|RCt5k_y z2=AKWEZ)2HNK4pw`j znI_Drf3&3jLrvB8B_~Gt+IOa+0#skp^aisJmomxgp{2l%c?!)+QTaE^LPrxQq_v@o zo^-j`r2<@+r&8VWqvYXvu@sFbx(?N!%FQbr(ZO1&7@oc*9b!y@ob>0`I?{_3)==3y zdy@5?a)eZE&&1h78?fPZS%(duT1NiGm?!bHS?+X!D(o7d`3OtEk%; zojR3c+Te55#QP3zRi`zxU5xO%ZN2omce0MOHTv^zQ%~KuT05+hm;xG!R#9sNAMO*nPg~(VsHpUf_ zZ5ZzIhL|lcJyoNrzS(wUTPw`1d^YfE;wcC zz4N8&-`vj4(yk{3HQv6F9rt+Oh1F~ZUHUJq)!~5j=c^tfNJwt%ZhkplG9aSP{;nk3 qv5i5 \ No newline at end of file diff --git a/public/images/skillset/django.svg b/public/images/skillset/django.svg new file mode 100644 index 0000000..69a4642 --- /dev/null +++ b/public/images/skillset/django.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/skillset/figma.svg b/public/images/skillset/figma.svg new file mode 100644 index 0000000..7be1d02 --- /dev/null +++ b/public/images/skillset/figma.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/public/images/skillset/firebase.svg b/public/images/skillset/firebase.svg new file mode 100644 index 0000000..5495fef --- /dev/null +++ b/public/images/skillset/firebase.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/skillset/github.svg b/public/images/skillset/github.svg new file mode 100644 index 0000000..0f6b938 --- /dev/null +++ b/public/images/skillset/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/skillset/html.svg b/public/images/skillset/html.svg new file mode 100644 index 0000000..9ff8599 --- /dev/null +++ b/public/images/skillset/html.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/skillset/js.svg b/public/images/skillset/js.svg new file mode 100644 index 0000000..52ca67a --- /dev/null +++ b/public/images/skillset/js.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/skillset/python.svg b/public/images/skillset/python.svg new file mode 100644 index 0000000..a16973b --- /dev/null +++ b/public/images/skillset/python.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/skillset/qnet.svg b/public/images/skillset/qnet.svg new file mode 100644 index 0000000..cd65a21 --- /dev/null +++ b/public/images/skillset/qnet.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/skillset/react.svg b/public/images/skillset/react.svg new file mode 100644 index 0000000..3a27f7c --- /dev/null +++ b/public/images/skillset/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/skillset/slack.svg b/public/images/skillset/slack.svg new file mode 100644 index 0000000..69a4eb6 --- /dev/null +++ b/public/images/skillset/slack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/skillset/sqld.svg b/public/images/skillset/sqld.svg new file mode 100644 index 0000000..49e6dd4 --- /dev/null +++ b/public/images/skillset/sqld.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/skillset/styled-components.svg b/public/images/skillset/styled-components.svg new file mode 100644 index 0000000..84915e1 --- /dev/null +++ b/public/images/skillset/styled-components.svg @@ -0,0 +1 @@ +💅 \ No newline at end of file diff --git a/public/images/skillset/ts.svg b/public/images/skillset/ts.svg new file mode 100644 index 0000000..115062b --- /dev/null +++ b/public/images/skillset/ts.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/skillset/zeplin.svg b/public/images/skillset/zeplin.svg new file mode 100644 index 0000000..e0c7c3d --- /dev/null +++ b/public/images/skillset/zeplin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/index.html b/public/index.html index aa069f2..040b415 100644 --- a/public/index.html +++ b/public/index.html @@ -2,14 +2,14 @@ - + - + - React App + 이현지 | 프론트엔드 포트폴리오 diff --git a/src/GlobalStyle.tsx b/src/GlobalStyle.tsx index 828b46a..be121c0 100644 --- a/src/GlobalStyle.tsx +++ b/src/GlobalStyle.tsx @@ -5,6 +5,7 @@ export const GlobalStyle = createGlobalStyle` margin:0; padding:0; box-sizing:border-box; + } ` \ No newline at end of file diff --git a/src/components/HeaderMenu.tsx b/src/components/HeaderMenu.tsx index 469b398..a438f96 100644 --- a/src/components/HeaderMenu.tsx +++ b/src/components/HeaderMenu.tsx @@ -10,7 +10,7 @@ const HeaderDiv = styled.div` position:fixed; z-index:3; top:0; - width:100vw; + width:100%; padding:0 5%; height:100px; display:flex; @@ -21,6 +21,9 @@ const HeaderDiv = styled.div` @media screen and (max-width:900px){ padding:0; } + @media screen and (min-width:1200px){ + padding: 0 10%; + } ` const Logo = styled.h3` font-size:1.5rem; @@ -126,6 +129,7 @@ function HeaderMenu() { + ); } diff --git a/src/components/Intro/Title.tsx b/src/components/Intro/Title.tsx index a938fd1..17acebd 100644 --- a/src/components/Intro/Title.tsx +++ b/src/components/Intro/Title.tsx @@ -10,12 +10,11 @@ const SlideDownTitle=keyframes` transform: translateY(0px); } ` -const TitleDiv=styled.div<{startAnimation:boolean}>` +const TitleDiv=styled.div` position:absolute; white-space:nowrap; font-family:'jejudoldam'; z-index:1; - animation: ${(props)=>props.startAnimation? SlideDownTitle:null} 0.5s linear; ` const TitleUnmask = styled.h1` color:transparent; @@ -94,7 +93,7 @@ export function Title(){ },[inView]) return( - + Frontend
Portfolio
Frontend
Portfolio
diff --git a/src/components/Intro/WaveBackground.tsx b/src/components/Intro/WaveBackground.tsx index 684d88c..0ca4252 100644 --- a/src/components/Intro/WaveBackground.tsx +++ b/src/components/Intro/WaveBackground.tsx @@ -1,5 +1,4 @@ import styled, {keyframes} from "styled-components"; -import wave1 from '../../images/wave.svg'; const Ocean = styled.div` height: 30%; @@ -27,9 +26,9 @@ const swell=keyframes` transform: translate3d(0, 5px, 0); } ` -// https://s3-us-west-2.amazonaws.com/s.cdpn.io/85486/wave.svg + const Wave = styled.div` - background: url(${wave1}) repeat-x; + background: url("/images/intro/wave.svg") repeat-x; position: absolute; top: -198px; width: 100%; @@ -47,6 +46,7 @@ const Wave = styled.div` ` export function WaveBackground(){ + return( diff --git a/src/components/Skill/ClickMessage.tsx b/src/components/Skill/ClickMessage.tsx new file mode 100644 index 0000000..1ce8648 --- /dev/null +++ b/src/components/Skill/ClickMessage.tsx @@ -0,0 +1,47 @@ +import styled, { keyframes } from "styled-components"; +import "../../fonts/font.css"; + +const swell=keyframes` + 0%, 100% { + transform: translate3d(0, -20px, 0); + } + 50% { + transform: translate3d(0, 5px, 0); + } +` +const MessageDiv=styled.div` + position: absolute; + top:20%; + right: 10%; + text-align:center; + animation: ${swell} 1s infinite linear; + font-family:"SUITE-Regular"; + @media screen and (min-width:1200px){ + right:17%; + } +` +const Message=styled.div` + +` +const Arrow=styled.img` + transform: rotate(145deg); + margin-top:10px; + height:30px; + @media screen and (max-width:900px){ + transform: rotate(125deg); + } +` +type ClickMessageProps={ + running:boolean; +} +export function ClickMessage(prop:ClickMessageProps){ + return( + + + {prop.running? "다시 클릭하면 큐브가 돌아가요!":"큐브를 클릭하면 멈출 수 있어요!"} + + + + ); + +} \ No newline at end of file diff --git a/src/components/Skill/RotateSkillCube.tsx b/src/components/Skill/RotateSkillCube.tsx new file mode 100644 index 0000000..95948b6 --- /dev/null +++ b/src/components/Skill/RotateSkillCube.tsx @@ -0,0 +1,125 @@ +import { useEffect, useState } from "react"; +import { useInView } from "react-intersection-observer"; +import styled, { keyframes } from "styled-components"; +import { ClickMessage } from "./ClickMessage"; +import { SkillDetail } from "./SkillDetail"; + + +const Spin=keyframes` + from {transform: rotateY(0) rotateX(10deg)} + to {transform: rotateY(360deg) rotateX(10deg)} +` + +const CubeDiv=styled.div` + width:400px; + height:400px; + position:relative; + margin:0 auto; + transform-style: preserve-3d; + + &.startAnimation{ + animation : ${Spin} 5s infinite linear; + } + + &.pauseAnimation{ + animation-play-state:paused; + } + + @media screen and (max-width:700px){ + width:200px; + height:200px; + } + +` +const CubeSide=styled.div` + position: absolute; + border: solid 1px black; + display:flex; + align-items:center; + background-color:white; + opacity:0.9; + + width:400px; + height:400px; + &:nth-of-type(1){ + transform: rotateX(90deg) translateZ(200px); + } + &:nth-of-type(2){ + transform: translateZ(200px); + } + &:nth-of-type(3){ + transform: rotateY(90deg) translateZ(200px); + } + &:nth-of-type(4){ + transform: rotateY(180deg) translateZ(200px); + } + &:nth-of-type(5){ + transform: rotateY(-90deg) translateZ(200px); + } + &:nth-of-type(6){ + transform: rotateX(-90deg) translateZ(200px); + } + + @media screen and (max-width:700px){ + width:200px; + height:200px; + &:nth-of-type(1){ + transform: rotateX(90deg) translateZ(100px); + } + &:nth-of-type(2){ + transform: translateZ(100px); + } + &:nth-of-type(3){ + transform: rotateY(90deg) translateZ(100px); + } + &:nth-of-type(4){ + transform: rotateY(180deg) translateZ(100px); + } + &:nth-of-type(5){ + transform: rotateY(-90deg) translateZ(100px); + } + &:nth-of-type(6){ + transform: rotateX(-90deg) translateZ(100px); + } + } +` + + +export function RotateSkillCube(){ + const {ref, inView}=useInView(); + const [onCubeClick, setOnCubeClick]=useState(false); + const [onCube, setOnCube]=useState(true); + + useEffect(()=>{ + if (inView){ + setOnCube(true); + setOnCubeClick(false); + } + else{ + setOnCube(false); + } + },[inView]) + + return ( + <> + + setOnCubeClick(!onCubeClick)}> + + + + + + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/src/components/Skill/SkillData.tsx b/src/components/Skill/SkillData.tsx new file mode 100644 index 0000000..c6ef2b9 --- /dev/null +++ b/src/components/Skill/SkillData.tsx @@ -0,0 +1,72 @@ + +export const FrontendSkillSet=[ + { + title:"HTML", + img:"/images/skillset/html.svg" + }, + { + title:"CSS", + img:"/images/skillset/css3.svg" + }, + { + title:"JavaScript", + img:"/images/skillset/js.svg" + }, + { + title:"TypeScript", + img:"/images/skillset/ts.svg" + }, + { + title:"REACT", + img:"/images/skillset/react.svg" + }, + { + title:"Styled Components", + img:"/images/skillset/styled-components.svg" + }, + + +] +export const BackendSkillSet=[ + { + title:"Python", + img:"/images/skillset/python.svg" + }, + { + title:"Django", + img:"/images/skillset/django.svg" + }, + { + title:"Firebase", + img:"/images/skillset/firebase.svg" + }, + +] +export const CertificateSkillSet=[ + { + title:"정보처리기사", + img:"/images/skillset/qnet.svg" + }, + { + title:"SQLD", + img:"/images/skillset/sqld.svg" + }, +] +export const EtcSkillSet=[ + { + title:"Github", + img:"/images/skillset/github.svg" + }, + { + title:"Figma", + img:"/images/skillset/figma.svg" + }, + { + title:"Zeplin", + img:"/images/skillset/zeplin.svg" + }, + { + title:"Slack", + img:"/images/skillset/slack.svg" + }, +] \ No newline at end of file diff --git a/src/components/Skill/SkillDetail.tsx b/src/components/Skill/SkillDetail.tsx new file mode 100644 index 0000000..953c290 --- /dev/null +++ b/src/components/Skill/SkillDetail.tsx @@ -0,0 +1,95 @@ +import styled from "styled-components"; +import "../../fonts/font.css" +import { FrontendSkillSet, BackendSkillSet, CertificateSkillSet, EtcSkillSet } from "./SkillData"; + +const SkillDiv=styled.div` + width:100%; + height:100%; + padding: 5% 5%; + font-family:"SUITE-Bold"; +` +const SkillTitle=styled.h2` + font-family:"SUITE-Bold"; + height: 10%; + border-bottom: solid 1px black; + @media screen and (max-width: 700px){ + font-size: 1rem; + height: 13%; + } +` + +const SkillSet=styled.div` + display:grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 10px; + padding:5%; +` +const SkillLogoAndName=styled.div` + width:96px; + display:flex; + flex-direction: column; + justify-content:center; + align-items:center; + @media screen and (max-width: 700px){ + width:40px; + font-size:0.4rem; + } +` + +const SkillLogo=styled.img` + width:100%; + height:96px; + @media screen and (max-width: 700px){ + height:40px; + } + +` +const SkillName=styled.span` + background-position: bottom; + background-repeat: no-repeat; + background-size: 100% 20%; + background-image: linear-gradient(90deg, #7FB4E2 0%,#aad4e4 100%); + +` + +type SkillDetailProps={ + subject:string; +} + +export function SkillDetail(subject:SkillDetailProps){ + const RenderData=():JSX.Element[]=>{ + let Data:Record[]=[]; + if (subject.subject==='Frontend'){ + Data=FrontendSkillSet; + } + else if (subject.subject==='Backend'){ + Data=BackendSkillSet; + } + else if (subject.subject==='Certificate'){ + Data=CertificateSkillSet; + } + else if (subject.subject==='etc'){ + Data=EtcSkillSet; + } + const ReturnRenderData=Data.map( + (data)=>{ + return ( + + + {data.title} + + ); + } + ); + return ReturnRenderData; + } + return( + + {subject.subject} + + {RenderData()} + + + + ); +} \ No newline at end of file diff --git a/src/components/common/DownButton.tsx b/src/components/common/DownButton.tsx index 633f5f3..b76b0ac 100644 --- a/src/components/common/DownButton.tsx +++ b/src/components/common/DownButton.tsx @@ -41,7 +41,7 @@ const BellEffect=keyframes` ` -const AnimationEffect_One = styled.div` +const AnimationEffectOne = styled.div` width:20%; height:20%; border-radius:50%; @@ -51,7 +51,7 @@ const AnimationEffect_One = styled.div` animation: ${BellEffect} 3s infinite linear; ` -const AnimationEffect_Two = styled.div` +const AnimationEffectTwo = styled.div` width:20%; height:20%; border-radius:50%; @@ -74,8 +74,8 @@ export function DownButton(location:DownButtonProps){ - - + + ); } \ No newline at end of file diff --git a/src/pages/About.tsx b/src/pages/About.tsx index 9522e09..66180ed 100644 --- a/src/pages/About.tsx +++ b/src/pages/About.tsx @@ -28,11 +28,13 @@ const SlideRightDescription=keyframes` } ` -const Description=styled.div<{startAnimation:boolean}>` +const Description=styled.div` font-size:2rem; line-height:4rem; white-space:nowrap; - animation: ${(props)=>props.startAnimation? SlideRightDescription:null} 1s linear; + &.startAnimation{ + animation: ${SlideRightDescription} 0.5s linear; + } @media screen and (max-width:900px){ font-size:1.2rem; line-height:3rem; @@ -54,7 +56,7 @@ const InfoDiv=styled.div` height:80%; display:flex; flex-direction:column; - justify-content:space-between; + justify-content:center; @media screen and (max-width:900px){ width:100%; } @@ -64,6 +66,7 @@ const InfoDiv=styled.div` const Info=styled.div` width:100%; height:100px; + margin: 10px 0; display:flex; align-items:center; padding: 0 5%; @@ -79,6 +82,7 @@ const Info=styled.div` &:nth-child(4){ animation: ${RotateInfo} 1s 4.5s infinite linear; } + ` const InfoTitle=styled.span` font-size:2rem; @@ -128,7 +132,7 @@ export function About(){ const returnRenderInfoData=InfoData.map( (data)=>{ return ( - + {data.title} {data.content} @@ -148,7 +152,7 @@ export function About(){ },[inView]) return(
- + 성취하며 느낀 행복을 오랫동안 기억하고,
차근차근 꾸준하게 성장 중인 diff --git a/src/pages/Project.tsx b/src/pages/Project.tsx index 8129e42..510c5a6 100644 --- a/src/pages/Project.tsx +++ b/src/pages/Project.tsx @@ -1,4 +1,3 @@ -import { ComponentProps, forwardRef } from "react"; import { styled } from "styled-components"; import { DownButton } from "../components/common/DownButton"; diff --git a/src/pages/Skill.tsx b/src/pages/Skill.tsx index 4ecfd7f..5c8c18d 100644 --- a/src/pages/Skill.tsx +++ b/src/pages/Skill.tsx @@ -1,5 +1,7 @@ import { styled } from "styled-components"; import { DownButton } from "../components/common/DownButton"; +import { ClickMessage } from "../components/Skill/ClickMessage"; +import {RotateSkillCube} from "../components/Skill/RotateSkillCube"; const Div = styled.div` width:100vw; @@ -13,7 +15,7 @@ const Div = styled.div` export function Skill(){ return(
- skill +
); } \ No newline at end of file