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