diff --git a/.firebase/hosting.YnVpbGQ.cache b/.firebase/hosting.YnVpbGQ.cache index 0effcdf..014a25b 100644 --- a/.firebase/hosting.YnVpbGQ.cache +++ b/.firebase/hosting.YnVpbGQ.cache @@ -1,32 +1,48 @@ -asset-manifest.json,1699968681132,217aaa39a9463c9fedd477644a9571744a853811ed6e47df53a73b62a825f0f8 -index.html,1699968681132,30f49d8b46fcaefa46fbad7de369626f7896d30ee634e27cc1512ea3ef6657a8 -robots.txt,1699968672647,391d14b3c2f8c9143a27a28c7399585142228d4d1bdbe2c87ac946de411fa9a2 -images/board/snowman.png,1699968672640,9cc2e6f125dc0f5774292c6f54b1d241701fafddcc35bb73e4b78c474f47c892 -images/board/write.png,1699968672640,5473773d23481ebdd97943f540d4da1d27efddca99c7bcb522b1080ac8c0a15b -images/intro/wave.svg,1699968672641,6151d95838f42150e8c78e0c3973747e09ccd76be9fc84af17ed6ac457bd6de1 -images/skillset/css3.svg,1699968672642,811935f4f923aaaaf32657099da4c6b2479b7223925c578d4a2c54346efee5aa -images/skillset/arrow.png,1699968672641,f43a1625e422049c809d51f92a186fb9096a69f4fc412cf2e0330dcf804867f7 -images/skillset/django.svg,1699968672642,80a481dd97dd5c2c020e6d669c664cc600805d305156af3cd4a69f78bd2533a2 -images/skillset/figma.svg,1699968672642,429f024f6e8927d7aa6af473a8c83f56f97239788c48ecaafde378144aab6483 -images/skillset/github.svg,1699968672643,8a7e2d52d47289ea7d8aafe2ef74805aa7c0a142c2dfa3e0d26729822514e106 -images/skillset/firebase.svg,1699968672642,e72d249bc93151e9cc0d0b1759c38db6a058097269b074d46edafd674abacabc -images/skillset/js.svg,1699968672643,59c30d67021f35934f46ba864a2a9895b9e718e58b28c1d2f8e3ec481d55782e -images/skillset/python.svg,1699968672643,12ce1785f64589d3ff06296f4aae99507b460a780420cac766440cead01549c9 -images/skillset/html.svg,1699968672643,3f9690a7d12e4e6a9547029700af6182af5a649478f9d52ee50bb4221252adb1 -images/skillset/react.svg,1699968672644,9a6a3af9cd8950b71d5222495d285326b2e603d3bc8d10f18f3e0cfa0a434f41 -images/skillset/qnet.svg,1699968672644,13de1d298717d37cc8732ff92a94f31131b99e58b184307f18bc94a83f92e8a3 -images/skillset/styled-components.svg,1699968672645,5384e068549ad22dbfd59d421aa3434ab6c76c72d0b339f7d63fe4d9b7dd8e88 -images/skillset/slack.svg,1699968672644,b53b44465c98a16a8cb00e41ba1b74e1da7831cfebd452f937d1e1d249a55dfc -images/skillset/ts.svg,1699968672645,1181a5aeee960fa5e8f13df3a4e2be54fa324aef32e29281fc617470f688dd29 -static/css/main.43ab9f8e.css.map,1699968681151,d5c98c9051147fa26ceca15c69e8fc1675a7387041d557b42ed6fea24b68f350 -images/skillset/zeplin.svg,1699968672645,7e318a83c540f699d820e217dfbea626f5b40f1ecea1ea85a93de8fc5b65c0a1 -static/css/main.43ab9f8e.css,1699968681151,a1f22ab015b278105326b876a18cd6941cc4a487cc1a1bb6a4257c2878e2c19c -static/js/main.92bc8100.js.LICENSE.txt,1699968681151,78a24cfe1f25d5978ef92a1d7f46c0d40cdbd747a4d1c15168de8371b1b19a22 -images/skillset/sqld.svg,1699968672644,e2a8d0b40e96c2d3844d200d1bcebe64f97ece72800d1cd31e6413cd7c4106ac -images/board/message_bubble.png,1699968672639,e73ba70bf7456717ad0998c131dd1f9b8b5751bdb2b3ab95c9dacdd35ebb4959 -logo.svg,1699968672646,0765f2bdc493af04ef7819d6a3395430138973cb0599cb016b0aba1f84396afe -static/media/SUITE-Regular.680ae46430dcc1be483d.otf,1699968681151,96be007d3c4e799ae9c5b282e6c41cdcb24b8621ab9bebfb4d2d3988ea40bf8c -static/media/SUITE-Bold.e22c698474e4f4301302.otf,1699968681151,bd924b000f9a5f9543b042cd934d0a215936249a370f2e6af6b3c31ed066cc5c -static/js/main.92bc8100.js,1699968681150,26cd534dc68e79b6fd2c242d30d638fe72f0dc237aea5cd79828862b6d81d79f -static/js/main.92bc8100.js.map,1699968681151,956c80b18b793c68d83b7d2573dcd76b5467dd132881ba2bc5dea5abf9f092a3 -static/media/EF_jejudoldam.d02e2b7a6d2b97821dfb.otf,1699968681150,6be32030a0f7165c88b2c3a5a0930bdaf2bae0e5450c7a9cda2af26f737d5abc +asset-manifest.json,1700008372049,5f4f0fabca59d1d7d91c664902a8e094a2c01ea00028e55b83f3e2fcb1860f06 +index.html,1700008372049,3612a8cb27d9f3cb10009cb597009578c9fda945c48f156093bf5a049af5714a +robots.txt,1700008363967,391d14b3c2f8c9143a27a28c7399585142228d4d1bdbe2c87ac946de411fa9a2 +images/board/snowman.png,1700008363874,9cc2e6f125dc0f5774292c6f54b1d241701fafddcc35bb73e4b78c474f47c892 +images/intro/wave.svg,1700008363875,6151d95838f42150e8c78e0c3973747e09ccd76be9fc84af17ed6ac457bd6de1 +images/board/write.png,1700008363874,5473773d23481ebdd97943f540d4da1d27efddca99c7bcb522b1080ac8c0a15b +images/skillset/arrow.png,1700008363955,f43a1625e422049c809d51f92a186fb9096a69f4fc412cf2e0330dcf804867f7 +images/skillset/css3.svg,1700008363955,811935f4f923aaaaf32657099da4c6b2479b7223925c578d4a2c54346efee5aa +images/skillset/firebase.svg,1700008363956,e72d249bc93151e9cc0d0b1759c38db6a058097269b074d46edafd674abacabc +images/skillset/figma.svg,1700008363956,429f024f6e8927d7aa6af473a8c83f56f97239788c48ecaafde378144aab6483 +images/skillset/github.svg,1700008363956,8a7e2d52d47289ea7d8aafe2ef74805aa7c0a142c2dfa3e0d26729822514e106 +images/skillset/django.svg,1700008363955,80a481dd97dd5c2c020e6d669c664cc600805d305156af3cd4a69f78bd2533a2 +images/skillset/js.svg,1700008363956,59c30d67021f35934f46ba864a2a9895b9e718e58b28c1d2f8e3ec481d55782e +images/skillset/html.svg,1700008363956,3f9690a7d12e4e6a9547029700af6182af5a649478f9d52ee50bb4221252adb1 +images/skillset/python.svg,1700008363957,12ce1785f64589d3ff06296f4aae99507b460a780420cac766440cead01549c9 +images/skillset/slack.svg,1700008363965,b53b44465c98a16a8cb00e41ba1b74e1da7831cfebd452f937d1e1d249a55dfc +images/skillset/react.svg,1700008363957,9a6a3af9cd8950b71d5222495d285326b2e603d3bc8d10f18f3e0cfa0a434f41 +images/skillset/ts.svg,1700008363966,1181a5aeee960fa5e8f13df3a4e2be54fa324aef32e29281fc617470f688dd29 +images/skillset/qnet.svg,1700008363957,13de1d298717d37cc8732ff92a94f31131b99e58b184307f18bc94a83f92e8a3 +images/skillset/zeplin.svg,1700008363966,7e318a83c540f699d820e217dfbea626f5b40f1ecea1ea85a93de8fc5b65c0a1 +images/skillset/styled-components.svg,1700008363965,5384e068549ad22dbfd59d421aa3434ab6c76c72d0b339f7d63fe4d9b7dd8e88 +static/css/main.43ab9f8e.css.map,1700008372066,d5c98c9051147fa26ceca15c69e8fc1675a7387041d557b42ed6fea24b68f350 +static/js/main.8d158dfd.js.LICENSE.txt,1700008372066,cd5416542907cd17a5a0433b74fd8fbe4b37e2ec21b8636c57dd54ffa5fdf267 +images/skillset/sqld.svg,1700008363965,e2a8d0b40e96c2d3844d200d1bcebe64f97ece72800d1cd31e6413cd7c4106ac +static/css/main.43ab9f8e.css,1700008372066,a1f22ab015b278105326b876a18cd6941cc4a487cc1a1bb6a4257c2878e2c19c +images/board/message_bubble.png,1700008363873,e73ba70bf7456717ad0998c131dd1f9b8b5751bdb2b3ab95c9dacdd35ebb4959 +logo.svg,1700008363967,0765f2bdc493af04ef7819d6a3395430138973cb0599cb016b0aba1f84396afe +static/media/SUITE-Regular.680ae46430dcc1be483d.otf,1700008372066,96be007d3c4e799ae9c5b282e6c41cdcb24b8621ab9bebfb4d2d3988ea40bf8c +static/media/SUITE-Bold.e22c698474e4f4301302.otf,1700008372066,bd924b000f9a5f9543b042cd934d0a215936249a370f2e6af6b3c31ed066cc5c +static/js/main.8d158dfd.js,1700008372067,fe5602f2861c3a8946f0bb8da53ba26e958d25570700d0a9e1dbc27428dd4fb9 +images/project/portfolio/portfolio-1.png,1700008363954,20fd5479ca8fada9b60e33651a05982578ea370d8157b8671674b943169dabc3 +images/project/artistella/artistella-2.png,1700008363880,0dad5fd038e906abc21c27a83cd6e252a9d974c56602d163834f835ddbc9010b +images/project/artistella/artistella-3.png,1700008363881,ebde0de43eb3f3d0b0e8814a64c81fe6b98f29ed1eaeaeac80c324c29a1abf5e +images/project/hallo/hallo-7.png,1700008363907,9fdcd7800360783fa4e45795aac973a3a4deed651ce8bca3a8de8a344990d170 +images/project/hallo/hallo-6.png,1700008363905,222fa0af81c331f33c58b9b70f5038200f454b2e1b9e4b74535a84c9b967a061 +images/project/nxdflotto/lotto-5.png,1700008363952,6453834769c94fa38ad2676b6f8857e2e32d7f0f0dd7984fbde06baf2e173377 +images/project/hallo/hallo-4.png,1700008363897,a5acde0b2d0058da2824d88678f335af0da24fa47418b8943e63ec738a53b98c +images/project/hallo/hallo-2.png,1700008363889,80a3b1d977a8bb38705658e71f64b54028a6fa31c438965b64f4ec6d902b3d09 +images/project/hallo/hallo-1.png,1700008363886,91e778d3f29245cb0f7e5587f49647f8e2c312ad7172cd5388d2e69dea87fc85 +images/project/hallo/hallo-3.png,1700008363895,9ec68e8fdf63e734ad783eb57ac06cb957f93b2969bdfdc4378b5d978d47bd37 +images/project/artistella/artistella-1.png,1700008363879,b503ddc090abb0eee498c9a6626a03b1d5d9cb83f889b105f3894ffd0e3c9523 +images/project/hallo/hallo-5.png,1700008363902,a469866cb61e92e1c388e751f65836d331e43ecfea9721e4a1179c51bea9b125 +images/project/nxdflotto/lotto-3.png,1700008363937,575dcadaee72b157d17ece976975e7fc7558335c389875c6459ec440f5332aab +images/project/nxdflotto/lotto-4.png,1700008363945,db1cff59d358f9bdf2c9777d26a7d98fb21c88fc137b13a058502e71c8a0e69d +images/project/nxdflotto/lotto-2.png,1700008363927,0a272cd644bd2f843a6dfce085a02eed632283887747aceee2701bec89c2391f +images/project/nxdflotto/lotto-1.png,1700008363916,cdfb205bc93e8e94358ce1147ca6d69d5008fca2b294d349eb46932c77d447c3 +static/js/main.8d158dfd.js.map,1700008372066,cf4c2ff07fbc6413794a0eef498474d97f5e7234b8cbaf030da1798a17432d99 +static/media/EF_jejudoldam.d02e2b7a6d2b97821dfb.otf,1700008372067,6be32030a0f7165c88b2c3a5a0930bdaf2bae0e5450c7a9cda2af26f737d5abc diff --git a/public/images/project/portfolio/portfolio-2.png b/public/images/project/portfolio/portfolio-2.png new file mode 100644 index 0000000..0e2ae51 Binary files /dev/null and b/public/images/project/portfolio/portfolio-2.png differ diff --git a/public/images/project/portfolio/portfolio-3.png b/public/images/project/portfolio/portfolio-3.png new file mode 100644 index 0000000..9701fee Binary files /dev/null and b/public/images/project/portfolio/portfolio-3.png differ diff --git a/public/images/project/portfolio/portfolio-4.png b/public/images/project/portfolio/portfolio-4.png new file mode 100644 index 0000000..51d82b2 Binary files /dev/null and b/public/images/project/portfolio/portfolio-4.png differ diff --git a/public/images/project/qrcode/qrcode-1.png b/public/images/project/qrcode/qrcode-1.png new file mode 100644 index 0000000..12c5b84 Binary files /dev/null and b/public/images/project/qrcode/qrcode-1.png differ diff --git a/public/images/project/qrcode/qrcode-2.png b/public/images/project/qrcode/qrcode-2.png new file mode 100644 index 0000000..109e9d4 Binary files /dev/null and b/public/images/project/qrcode/qrcode-2.png differ diff --git a/public/images/project/qrcode/qrcode-3.png b/public/images/project/qrcode/qrcode-3.png new file mode 100644 index 0000000..854bb3e Binary files /dev/null and b/public/images/project/qrcode/qrcode-3.png differ diff --git a/public/images/project/qrcode/qrcode-4.png b/public/images/project/qrcode/qrcode-4.png new file mode 100644 index 0000000..391f6b7 Binary files /dev/null and b/public/images/project/qrcode/qrcode-4.png differ diff --git a/public/images/project/qrcode/qrcode-5.png b/public/images/project/qrcode/qrcode-5.png new file mode 100644 index 0000000..943cbd8 Binary files /dev/null and b/public/images/project/qrcode/qrcode-5.png differ diff --git a/public/images/project/qrcode/qrcode-6.png b/public/images/project/qrcode/qrcode-6.png new file mode 100644 index 0000000..df5e407 Binary files /dev/null and b/public/images/project/qrcode/qrcode-6.png differ diff --git a/src/components/About/CommonInfo.tsx b/src/components/About/CommonInfo.tsx index 7bc2bd9..5cd7a77 100644 --- a/src/components/About/CommonInfo.tsx +++ b/src/components/About/CommonInfo.tsx @@ -4,10 +4,9 @@ export const Info=styled.div` width:100%; height:100%; margin: 10px 0; + flex-shrink:0; padding: 10% 10%; - /* position:absolute; */ - background-color:white; - box-shadow: rgba(149, 160, 165, 0.2) 0px 8px 24px; + background-color:#7FB4E226; overflow:scroll; @media screen and (max-width:900px){ padding: 6% 6%; diff --git a/src/components/About/Descriptions.tsx b/src/components/About/Descriptions.tsx new file mode 100644 index 0000000..e23a1b0 --- /dev/null +++ b/src/components/About/Descriptions.tsx @@ -0,0 +1,59 @@ +import React, { useEffect, useState } from 'react'; +import { useInView } from 'react-intersection-observer'; +import { keyframes, styled } from 'styled-components'; + +const SlideRightDescription=keyframes` + 0%{ + transform: translateX(-100%); + } + 100%{ + transform: translateX(0px); + } +` + +const Description=styled.div` + font-size:2rem; + line-height:4rem; + white-space:nowrap; + &.startanimation{ + animation: ${SlideRightDescription} 0.5s linear; + } + @media screen and (max-width:900px){ + font-size:1.2rem; + line-height:3rem; + } +` + +const BoldFont=styled.span` + font-family:"SUITE-Bold"; +` + +const BorderBottomGradient=styled.span` + background-position: bottom; + background-repeat: no-repeat; + background-size: 100% 30%; + background-image: linear-gradient(90deg, #7FB4E2 0%,#aad4e4 100%); +` + +export function Descriptions() { + const {ref, inView}=useInView(); + const [onAbout, setOnAbout]=useState(true); + useEffect(()=>{ + if (inView){ + setOnAbout(true) + } + else{ + setOnAbout(false) + } + },[inView]) + + return ( + + 성취하며 느낀 행복을 오랫동안 기억하고, +
+ 차근차근 꾸준하게 성장 중인 +
+ 프론트엔드 개발자 이현지입니다. +
+ ); +} diff --git a/src/components/Board/BoardList.tsx b/src/components/Board/BoardList.tsx index 8ef2143..a112ecf 100644 --- a/src/components/Board/BoardList.tsx +++ b/src/components/Board/BoardList.tsx @@ -8,14 +8,13 @@ const BoardDiv=styled.div` display:grid; grid-template-columns: repeat(3, 1fr); grid-gap: 4%; - padding: 5% 5%; width: 100%; height:90%; - border-top-left-radius:25px; - border-top-right-radius:25px; overflow:scroll; background-color: white; - z-index:5; + @media screen and (max-width:500px){ + grid-template-columns: 1fr; + } ` diff --git a/src/components/Board/InputMessage.tsx b/src/components/Board/InputMessage.tsx index 1f26905..36aef14 100644 --- a/src/components/Board/InputMessage.tsx +++ b/src/components/Board/InputMessage.tsx @@ -9,20 +9,18 @@ const InputForm=styled.form` width: 100%; height:80px; display:flex; - z-index:5; + justify-content:space-between; + position:relative; /* justify-content:space-between; */ ` const ContentInput=styled.input` width:100%; height:100%; - /* padding: 0 1%; */ + padding-left:1%; + border: none; + border-bottom: solid 1px gray; font-family:"SUITE-Regular"; - border:none; - border-bottom-left-radius:25px; - /* border-left:solid 1px black; */ - /* border-bottom:solid 1px black; */ - padding-left:6%; &:focus{ outline:none; } @@ -30,29 +28,30 @@ const ContentInput=styled.input` const NameInput=styled.input` width:100%; height:100%; - /* padding: 0 1%; */ - padding-left:6%; + padding-left:1%; + margin-bottom:5px; border:none; - /* border-left:solid 1px black; */ + border-bottom: solid 1px gray; font-family:"SUITE-Regular"; &:focus{ outline:none; } ` const InputDiv=styled.div` - width:100%; + width:90%; height: 80px; display:flex; flex-direction:column; + @media screen and (max-width:700px){ + width:80%; + } ` const SubmitButton=styled.button` width:5%; height:100%; border:none; - border-bottom-right-radius:25px; - /* border-right: solid 1px black; */ - /* border-bottom: solid 1px black; */ + border-radius: 5px; color:white; background-color: #87CEEB; @media screen and (max-width:700px){ @@ -60,12 +59,9 @@ const SubmitButton=styled.button` } ` -type InputMessageProps={ - confetti:Function -} -export function InputMessage(prop:InputMessageProps) { +export function InputMessage() { const [inputAuthor, setInputAuthor]=useState(''); const [inputContent, setInputContent]=useState(''); @@ -77,7 +73,7 @@ export function InputMessage(prop:InputMessageProps) { } const onSubmitMessage=(e:React.FormEvent)=>{ e.preventDefault(); - if (inputAuthor!='' && inputContent!=''){ + if (inputAuthor!=='' && inputContent!==''){ postMessage({ author:inputAuthor, content:inputContent, @@ -85,7 +81,6 @@ export function InputMessage(prop:InputMessageProps) { }); setInputAuthor(''); setInputContent(''); - prop.confetti(true); } else{ alert('내용을 입력해주세요!') diff --git a/src/components/HeaderMenu.tsx b/src/components/HeaderMenu.tsx index 4aeacb7..93f3b75 100644 --- a/src/components/HeaderMenu.tsx +++ b/src/components/HeaderMenu.tsx @@ -17,10 +17,10 @@ const HeaderDiv = styled.div` align-items:center; justify-content:space-between; font-family:'jejudoldam'; - /* background-color:white; */ - /* backdrop-filter:blur(3px); */ + backdrop-filter:blur(3px); @media screen and (max-width:900px){ padding:0; + position:sticky; } @media screen and (min-width:1200px){ padding: 0 10%; @@ -55,6 +55,7 @@ const MenuLi=styled.li` const ResponsiveMenu=styled.div` font-size:1.5rem; position: absolute; + right:5%; @media screen and (min-width:900px){ display:none; @@ -64,15 +65,16 @@ const ResponsiveMenu=styled.div` const RespMenuUnderLogo=styled.ul` list-style:none; - background-color:white; position:absolute; display:flex; flex-direction:column; justify-content:space-around; - width:100vw; + width:100%; height:200%; text-align:center; top:100px; + z-index:3; + /* backdrop-filter:blur(3px); */ font-family:"SUITE-Bold"; @media screen and (min-width:900px){ display:none; @@ -88,35 +90,35 @@ const HeaderMenu=(prop:HeaderMenuProps)=>{ const onClickIntro=()=>{ setRespMenu(false); if (typeof prop.menuRef[0]!=="function"){ - console.log(prop.menuRef[0]?.current?.scrollIntoView({behavior:"smooth"})); + prop.menuRef[0]?.current?.scrollIntoView({behavior:"smooth"}); } } const onClickAbout=()=>{ setRespMenu(false); if (typeof prop.menuRef[1]!=="function"){ - console.log(prop.menuRef[1]?.current?.scrollIntoView({behavior:"smooth"})); + prop.menuRef[1]?.current?.scrollIntoView({behavior:"smooth"}); } } const onClickSkill=()=>{ setRespMenu(false); if (typeof prop.menuRef[2]!=="function"){ - console.log(prop.menuRef[2]?.current?.scrollIntoView({behavior:"smooth"})); + prop.menuRef[2]?.current?.scrollIntoView({behavior:"smooth"}); } } const onClickProject=()=>{ setRespMenu(false); if (typeof prop.menuRef[3]!=="function"){ - console.log(prop.menuRef[3]?.current?.scrollIntoView({behavior:"smooth"})); + prop.menuRef[3]?.current?.scrollIntoView({behavior:"smooth"}); } } const onClickBoard=()=>{ setRespMenu(false); if (typeof prop.menuRef[4]!=="function"){ - console.log(prop.menuRef[4]?.current?.scrollIntoView({behavior:"smooth"})); + prop.menuRef[4]?.current?.scrollIntoView({behavior:"smooth"}); } } return ( diff --git a/src/components/Intro/Title.tsx b/src/components/Intro/Title.tsx index 17acebd..363b677 100644 --- a/src/components/Intro/Title.tsx +++ b/src/components/Intro/Title.tsx @@ -45,7 +45,7 @@ const translateTitleMask=(move:number)=>keyframes` ` interface TitleProps{ height:number; - startAnimation:boolean; + startanimation:boolean; } const TextBackgroundOnMouseMove=styled.div` @@ -56,7 +56,7 @@ const TextBackgroundOnMouseMove=styled.div` top:0; overflow:hidden; -webkit-text-stroke: 1px black; - animation: ${(props)=>props.startAnimation? translateBackgroundMask(props.height) :null} 5s linear infinite; + animation: ${(props)=>props.startanimation? translateBackgroundMask(props.height) :null} 5s linear infinite; @media screen and (max-width:900px){ height:50px; } @@ -64,7 +64,7 @@ const TextBackgroundOnMouseMove=styled.div` const TitleMask = styled.h1` font-size:7.9rem; - animation: ${(props)=>props.startAnimation? translateTitleMask(-props.height) :null} 5s linear infinite; + animation: ${(props)=>props.startanimation? translateTitleMask(-props.height) :null} 5s linear infinite; @media screen and (max-width:900px){ font-size:5rem; } @@ -95,8 +95,8 @@ export function Title(){ return( Frontend
Portfolio
- - Frontend
Portfolio
+ + Frontend
Portfolio
diff --git a/src/components/Intro/WaveBackground.tsx b/src/components/Intro/WaveBackground.tsx index b893fc2..0379dbc 100644 --- a/src/components/Intro/WaveBackground.tsx +++ b/src/components/Intro/WaveBackground.tsx @@ -35,7 +35,7 @@ const Wave = styled.div` top: -198px; width: 100%; height: 198px; - &.startAnimation{ + &.startanimation{ -webkit-animation: ${wave} 7s cubic-bezier(0.36, 0.45, 0.63, 0.53) infinite; animation: ${wave} 7s cubic-bezier(0.36, 0.45, 0.63, 0.53) infinite; transform: translate3d(0, 0, 0); @@ -64,8 +64,8 @@ export function WaveBackground(){ return( - - + + ); diff --git a/src/components/Project/ProjectCard.tsx b/src/components/Project/ProjectCard.tsx index 8261660..f70d774 100644 --- a/src/components/Project/ProjectCard.tsx +++ b/src/components/Project/ProjectCard.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import styled from 'styled-components'; +import { useEffect, useRef } from 'react'; +import styled,{keyframes} from 'styled-components'; import ProjectImageSlider from './ProjectImageSlider'; import "../../fonts/font.css"; @@ -17,9 +17,29 @@ const CardDiv=styled.div` font-size:0.8rem; } ` +const SlideDownInfo=keyframes` + from{ + transform:translateY(-100%); + } + to{ + transform: translateY(0); + } +` +const SlideLeftInfo=keyframes` + from{ + transform:translateX(100%); + } + to{ + transform: translateX(0); + } + +` const CardInfo=styled.div` margin-right:10%; + &.startanimation{ + animation: ${SlideDownInfo} 0.3s linear; + } @media screen and (max-width:900px){ margin-right:0; margin-bottom:20px; @@ -61,6 +81,9 @@ const Tag=styled.span` ` const CardDetailDiv=styled.div` + &.startanimation{ + animation: ${SlideLeftInfo} 0.3s linear; + } ` @@ -97,10 +120,35 @@ type ProjectCardProp={ skillstack:string } + function ProjectCard(prop:ProjectCardProp) { + const CardInfoRef=useRef(null); + const CardDetailRef=useRef(null); + const mutationObserver=new MutationObserver(async()=>{ + // CardInfo랑 CardDetailDiv 애니메이션 실행 + if (CardInfoRef.current && CardDetailRef.current){ + CardInfoRef.current.classList.remove("startanimation"); + CardDetailRef.current.classList.remove("startanimation"); + //브라우저에 dom에 대한 정보(width)를 요청하면서 강제로 브라우저에게 일을 시키게 할 뿐이다 + void CardInfoRef.current.offsetHeight; + CardInfoRef.current.classList.add("startanimation"); + CardDetailRef.current.classList.add("startanimation"); + } + + + }) + useEffect(()=>{ + if (CardInfoRef.current){ + mutationObserver.observe(CardInfoRef.current, { + childList:true, + subtree:true, + }) + } + + },[]) return ( - + {prop.title} {prop.member} @@ -115,7 +163,7 @@ function ProjectCard(prop:ProjectCardProp) { {prop.hosturl} :<>} - + 프로젝트 소개 {prop.introduce} 구현 사항 diff --git a/src/components/Project/ProjectData.tsx b/src/components/Project/ProjectData.tsx index c5524ff..893b80e 100644 --- a/src/components/Project/ProjectData.tsx +++ b/src/components/Project/ProjectData.tsx @@ -15,22 +15,32 @@ export const ProjectData=[ { title:"Portfolio", member:"Solo Project", - images:["/images/project/portfolio/portfolio-1.png"], + images:["/images/project/portfolio/portfolio-1.png","/images/project/portfolio/portfolio-2.png","/images/project/portfolio/portfolio-3.png","/images/project/portfolio/portfolio-4.png"], github:"https://github.com/hyunji-lee99/fe_portfolio", hosturl:"https://1eehyunji.com/", - introduce:"지금까지 쌓아온 프론트엔드 기술 역량을 보여주고, 개발 과정에서 더 나은 코드와 구조와 기술에 대한 학습을 위해 동적인 웹 프론트엔드 포트폴리오 페이지를 개발 중에 있습니다. 꾸준히 코드 리팩토링을 진행할 예정입니다.", - implementation:"", - skillstack:"" + introduce:"지금까지 쌓아온 프론트엔드 기술 역량을 보여주고, 개발 과정에서 더 나은 코드와 구조, 기술에 대한 학습을 위해 동적인 반응형 웹 프론트엔드 포트폴리오 페이지를 개발 중에 있습니다. 꾸준히 코드 리팩토링을 진행할 예정입니다.", + implementation:`메인 페이지 + 개인 소개 페이지 + 회전하는 큐브로 표현한 기술 스택 페이지 + 프로젝트 소개 페이지(슬라이더 구현) + 방문자가 메시지를 남길 수 있는 보드 페이지 + 옵저버 패턴을 적용한 애니메이션 + ` + , + skillstack:"React, TypeScript, Styled-components, Firebase" }, { title:"QRcode 모바일 명함", member:"Team Project", - images:[], + images:["/images/project/qrcode/qrcode-1.png","/images/project/qrcode/qrcode-2.png","/images/project/qrcode/qrcode-3.png","/images/project/qrcode/qrcode-4.png","/images/project/qrcode/qrcode-5.png","/images/project/qrcode/qrcode-6.png"], github:"https://github.com/GDG-hackathon-14", hosturl:"", - introduce:"", - implementation:"", - skillstack:"" + introduce:"자신의 직무와 이름, 연락처 등을 QR코드로 쉽고 빠르게 전달할 수 있도록 사용자가 자신의 정보를 입력하면 디자인된 템플릿 형태로 전자 명함을 발행할 수 있는 모바일 웹입니다. 해당 전자 명함의 QR코드를 공유하여 자신의 정보를 원활하게 공유할 수 있습니다. ", + implementation:`웹 시작 페이지 + 사진, 이름, 직무, MBTI 등 사용자 정보 입력 페이지 + 전자 명함 발행 페이지(사용자 정보 템플릿된 형태로 출력) + `, + skillstack:"React, JavaScript, Styled-components" }, { title:"Aristella", @@ -38,9 +48,12 @@ export const ProjectData=[ images:["/images/project/artistella/artistella-1.png","/images/project/artistella/artistella-2.png","/images/project/artistella/artistella-3.png" ], github:"", hosturl:"", - introduce:"NFT 마켓 플레이스인 Aritstella는 다양한 NFT 작품을 탐색하고, 전자지갑을 연동하여 NFT 작품을 거래할 수 있습니다. 업무를 지시받아 구현한 React를 이용한 첫 프로젝트입니다.", - implementation:"", - skillstack:"" + introduce:"NFT 마켓 플레이스인 Aritstella는 다양한 NFT 작품을 탐색하고, 전자지갑을 연동하여 NFT 작품을 거래할 수 있습니다. 업무를 지시받아 React를 이용해서 웹 프론트엔드를 구현한 첫 프로젝트입니다.", + implementation:`주요 작품을 보여주는 메인 페이지 + 작품명, 작가명, 거래 내역 등을 보여주는 작품 상세 페이지 + 전체 작품을 보여주는 작품 탐색 페이지 + `, + skillstack:"React, JavaScript, Styled-components" }, { title:"NXDF Lotto", @@ -49,7 +62,10 @@ export const ProjectData=[ github:"", hosturl:"", introduce:"회사에서 발행한 토큰에 관심이 있는 유저를 대상으로 실시한 이벤트 페이지입니다. 특정 가격의 Lotto Draw 티켓을 구입하면 번호를 뽑을 수 있고, 해당 번호 당첨 시 토큰으로 당첨금을 수령합니다.", - implementation:"", - skillstack:"" + implementation:`당첨시 받을 수 있는 금액과 다음 Draw까지 남은 시간을 알려주는 메인 페이지 + 티켓을 구매한 사람을 보여주는 Ticket Buyer 페이지 + 이벤트를 소개하는 About us 페이지 + `, + skillstack:"React, TypeScript, Styled-Components, Firebase" }, ] \ No newline at end of file diff --git a/src/components/Project/ProjectImageSlider.tsx b/src/components/Project/ProjectImageSlider.tsx index 4f90d28..38bec17 100644 --- a/src/components/Project/ProjectImageSlider.tsx +++ b/src/components/Project/ProjectImageSlider.tsx @@ -12,7 +12,6 @@ const SliderDiv=styled.div` @media screen and (max-width:700px){ width:300px; height:200px; - } ` const SliderWrapper=styled.div` @@ -27,11 +26,10 @@ const Image=styled.img` @media screen and (max-width:700px){ width:300px; height:200px; - } ` const ImageDiv=styled.div` - display:flex; */ + display:flex; align-items:center; justify-content:center; width:100%; @@ -66,14 +64,20 @@ type ProjectImageSliderProp={ function ProjectImageSlider(prop:ProjectImageSliderProp) { const SlideRef=useRef(null); const [index, setIndex]=useState(0); - // const slideRange=400*index; - + const mutationObserver=new MutationObserver(async ()=>{ + setIndex(0); + }) useEffect(()=>{ - if(SlideRef.current?.style!=null){ + if(SlideRef.current){ const slideRange=SlideRef.current.offsetWidth*index; SlideRef.current.style.transition = "all 0.5s ease-in-out"; SlideRef.current.style.transform=`translateX(-${slideRange}px)` + + mutationObserver.observe(SlideRef.current, { + childList:true, + subtree:true + }) } },[index]) diff --git a/src/components/Skill/RotateSkillCube.tsx b/src/components/Skill/RotateSkillCube.tsx index 812131c..b0494c3 100644 --- a/src/components/Skill/RotateSkillCube.tsx +++ b/src/components/Skill/RotateSkillCube.tsx @@ -17,7 +17,7 @@ const CubeDiv=styled.div` margin:0 auto; transform-style: preserve-3d; - &.startAnimation{ + &.startanimation{ animation : ${Spin} 5s infinite linear; } @@ -102,7 +102,7 @@ export function RotateSkillCube(){ return (
- setOnCubeClick(!onCubeClick)}> diff --git a/src/pages/About.tsx b/src/pages/About.tsx index b487555..c6881e4 100644 --- a/src/pages/About.tsx +++ b/src/pages/About.tsx @@ -1,16 +1,16 @@ -import { keyframes, styled } from "styled-components"; -import { DownButton } from "../components/common/DownButton"; -import '../fonts/font.css'; +import { useEffect, useRef, useState } from "react"; +import { styled } from "styled-components"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faArrowRight, faArrowLeft } from "@fortawesome/free-solid-svg-icons"; -import { useInView } from 'react-intersection-observer'; -import { useEffect, useState } from "react"; + +import { DownButton } from "../components/common/DownButton"; import { RenderEducation } from "../components/About/RenderEducation"; import { RenderCareer } from "../components/About/RenderCareer"; import { RenderEtc } from "../components/About/RenderEtc"; import { RenderContact } from "../components/About/RenderContact"; import { RenderPrize } from "../components/About/RenderPrize"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { IconProp } from "@fortawesome/fontawesome-svg-core"; +import { Descriptions } from "../components/About/Descriptions"; +import '../fonts/font.css'; const Div = styled.div` width:100vw; @@ -27,52 +27,31 @@ const Div = styled.div` } ` -const SlideRightDescription=keyframes` - 0%{ - transform: translateX(-100%); - } - 100%{ - transform: translateX(0px); - } -` - -const Description=styled.div` - font-size:2rem; - line-height:4rem; - white-space:nowrap; - &.startAnimation{ - animation: ${SlideRightDescription} 0.5s linear; - } - @media screen and (max-width:900px){ - font-size:1.2rem; - line-height:3rem; - } -` - const InfoDiv=styled.div` - width:40%; - height:80%; + width:100%; + height:100%; + max-width:500px; + min-width:310px; + overflow:hidden; display:flex; justify-content:center; align-items:center; - position:relative; - @media screen and (max-width:900px){ +` +const InfoSliderWrapper=styled.div` + width:100%; + height:100%; + display:flex; +` +const SliderButtonWrapper=styled.div` + position:relative; + display:flex; + width:40%; + height:80%; + @media screen and (max-width:900px){ width:100%; height: 60%; } ` - -const BoldFont=styled.span` - font-family:"SUITE-Bold"; -` - -const BorderBottomGradient=styled.span` - background-position: bottom; - background-repeat: no-repeat; - background-size: 100% 30%; - background-image: linear-gradient(90deg, #7FB4E2 0%,#aad4e4 100%); -` - const Button=styled.button` font-size:1rem; border-radius:50%; @@ -87,6 +66,7 @@ const Button=styled.button` align-items:center; justify-content:center; position:absolute; + top:50%; @media screen and (max-width:768px){ width:20px; height:20px; @@ -99,23 +79,20 @@ type AboutProps={ } export function About(prop:AboutProps){ - const {ref, inView}=useInView(); - const [onAbout, setOnAbout]=useState(true); - const [currentInfo, setCurrentInfo]=useState(1); - - useEffect(()=>{ - if (inView){ - setOnAbout(true) - } - else{ - setOnAbout(false) - } - },[inView]) - - + const [currentInfo, setCurrentInfo]=useState(0); + const SlideRef=useRef(null); + + useEffect(()=>{ + if(SlideRef.current){ + const slideRange=SlideRef.current.offsetWidth*currentInfo; + SlideRef.current.style.transition = "all 0.5s ease-in-out"; + SlideRef.current.style.transform=`translateX(-${slideRange}px)` + } + },[currentInfo]) + const onClickPrevButton=()=>{ - if (currentInfo===1){ - setCurrentInfo(5); + if (currentInfo===0){ + setCurrentInfo(4); } else{ setCurrentInfo((cur)=>cur-1); @@ -123,8 +100,8 @@ export function About(prop:AboutProps){ } const onClickNextButton=()=>{ - if (currentInfo===5){ - setCurrentInfo(1); + if (currentInfo===4){ + setCurrentInfo(0); } else{ setCurrentInfo((cur)=>cur+1); @@ -132,27 +109,25 @@ export function About(prop:AboutProps){ } return(
- - 성취하며 느낀 행복을 오랫동안 기억하고, -
- 차근차근 꾸준하게 성장 중인 -
- 프론트엔드 개발자 이현지입니다. -
- - - {currentInfo===1?RenderContact():null} - {currentInfo===2?RenderEducation():null} - {currentInfo===3?RenderCareer():null} - {currentInfo===4?RenderPrize():null} - {currentInfo===5?RenderEtc():null} - + + + + {RenderContact()} + {RenderEducation()} + {RenderCareer()} + {RenderPrize()} + {RenderEtc()} + - + +
); diff --git a/src/pages/Board.tsx b/src/pages/Board.tsx index 8cfe684..3ccbab0 100644 --- a/src/pages/Board.tsx +++ b/src/pages/Board.tsx @@ -1,9 +1,10 @@ -import { useState } from "react"; -import ConfettiExplosion, { ConfettiProps } from "react-confetti-explosion"; + import { styled } from "styled-components"; import { BoardList } from "../components/Board/BoardList"; import { InputMessage } from "../components/Board/InputMessage"; import Snowfall from "react-snowfall"; +import { useInView } from "react-intersection-observer"; +import { useEffect, useState } from "react"; const Div = styled.div` @@ -17,21 +18,39 @@ const Div = styled.div` justify-content:center; background-image:linear-gradient(0deg, #ffffff 0%,#7FB4E280 100%); ` +const BoardWrapper=styled.div` + width:100%; + height:100%; + z-index:2; + padding: 5% 5%; + background-color:white; + border-radius:10px; +` type BoardProps={ boardRef:React.ForwardedRef; } export function Board(prop:BoardProps){ - const [onConfeti,setOnConfetti]=useState(true); + const {ref, inView}=useInView(); + const [onSnow, setOnSnow]=useState(false); + useEffect(()=>{ + if (inView){ + setOnSnow(true) + } + else { + setOnSnow(false) + } + },[inView]) + return(
- - {/* {onConfeti && - setOnConfetti(false)} - colors={['#7FB4E2','#6F3A00','#FFECCC','#8B7356','#87ceeb']}/>} */} - - + {/* 뷰 안에 요소가 들어오면 animation 실행 */} +
+ {onSnow?:null} + + + +
); } \ No newline at end of file