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 a11777c..0000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/favicon.png b/public/favicon.png new file mode 100644 index 0000000..dbaf795 Binary files /dev/null and b/public/favicon.png differ 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 0000000..3981046 Binary files /dev/null and b/public/images/skillset/arrow.png differ diff --git a/public/images/skillset/css3.svg b/public/images/skillset/css3.svg new file mode 100644 index 0000000..a992542 --- /dev/null +++ b/public/images/skillset/css3.svg @@ -0,0 +1 @@ + \ 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