diff --git a/src/hooks/useInfiniteCarousel.ts b/src/hooks/useInfiniteCarousel.ts index 7850de6b..eeb7211f 100644 --- a/src/hooks/useInfiniteCarousel.ts +++ b/src/hooks/useInfiniteCarousel.ts @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import { MutableRefObject, useEffect, useRef, useState } from 'react'; const SWIPE_THRESHOLD = 50; const NEXT = 1; @@ -6,7 +6,11 @@ const PREVIOUS = -1; export type DirectionType = typeof PREVIOUS | typeof NEXT; -const useInfiniteCarousel = (carouselList: Array, x: string) => { +const useInfiniteCarousel = ( + carouselList: Array, + x: string, + dotRef?: MutableRefObject, +) => { const TOTAL_SLIDE = carouselList.length; const [infiniteCarouselList, setInfiniteCarouselList] = useState(carouselList); const [currentIndex, setCurrentIndex] = useState(0); @@ -51,13 +55,24 @@ const useInfiniteCarousel = (carouselList: Array, x: string) => { const handleCarouselSwipe = (direction: DirectionType) => { const totalSlide = carouselList.length; - const newIndex = slideIndex + direction; + const nextIndex = slideIndex + direction; + let newIndex; if (direction === NEXT) { - setSlideIndex(newIndex === totalSlide ? 0 : newIndex); + newIndex = nextIndex === totalSlide ? 0 : nextIndex; + setSlideIndex(newIndex); } else { - setSlideIndex(newIndex === -1 ? totalSlide - 1 : newIndex); + newIndex = nextIndex === -1 ? totalSlide - 1 : nextIndex; + setSlideIndex(newIndex); } handleSwipe(direction); + + if (dotRef) { + dotRef.current[newIndex].scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + inline: 'nearest', + }); + } }; const handleTouchStart = (e: React.TouchEvent) => { diff --git a/src/lib/constants/main.ts b/src/lib/constants/main.ts index 6ebbfe5c..0127a560 100644 --- a/src/lib/constants/main.ts +++ b/src/lib/constants/main.ts @@ -189,14 +189,14 @@ export const partList: PartListType = { { content: 'Kotlin 언어를 활용', weight: 'bold' }, { content: '해 안드로이드 ', weight: 'normal' }, { content: 'UI 구현 기초/심화', weight: 'bold' }, - { content: '부터 ', weight: 'normal' }, + { content: ', ', weight: 'normal' }, { content: '서버 통신 ', weight: 'bold' }, { - content: '등 앱 제작에 필요한 내용들을 배웁니다. 안드로이드에 몰입할 수 있는 세미나, ', + content: '등 앱 제작에 필요한 내용들을 배웁니다. 세미나, ', weight: 'normal', }, { content: '페어 프로그래밍', weight: 'bold' }, - { content: '을 통한 실습, 스터디, 합동세미나 등 여러 활동에 참여합니다.', weight: 'normal' }, + { content: '을 통한 실습 등 여러 활동에 참여합니다.', weight: 'normal' }, ], }, [Part.IOS]: { @@ -204,22 +204,18 @@ export const partList: PartListType = { label: 'iOS', description: [ { content: 'Swift와 UI Kit', weight: 'bold' }, - { content: '를 이용해서 ', weight: 'normal' }, + { content: '를 이용해 ', weight: 'normal' }, { content: 'iOS 앱 서비스', weight: 'bold' }, { - content: '를 만들 수 있는 능력을 기를 수 있습니다. iOS가 처음인 분들을 위한', + content: '를 만들 수 있습니다. iOS가 처음인 분들을 위한', weight: 'normal', }, { content: '왕초보 스터디', weight: 'bold' }, { content: '와 ', weight: 'normal' }, { content: '보충 세미나', weight: 'bold' }, - { content: ', 그리고 실력적 도약을 위한 ', weight: 'normal' }, + { content: ', 실력적 도약을 위한 ', weight: 'normal' }, { content: '심화 세미나', weight: 'bold' }, - { - content: - '까지. 자신의 성장을 위해 열정적으로 도전하는 사람들과 함께 활동에 필요한 부분들을 학습할 수 있습니다.', - weight: 'normal', - }, + { content: '까지 존재합니다.', weight: 'normal' }, ], }, [Part.WEB]: { @@ -229,7 +225,6 @@ export const partList: PartListType = { { content: 'UI 구현, 서버 통신 등 ', weight: 'normal' }, { content: '웹 서비스 개발', weight: 'bold' }, { content: '에 필요한 역량들을 ', weight: 'normal' }, - { content: '기초부터 심화까지 ', weight: 'bold' }, { content: '학습합니다. 또한 기획자, 디자이너, 서버 개발자와의 협업 경험을 통해 개발 협업 방식을 익힐 수 있습니다.', @@ -244,16 +239,13 @@ export const partList: PartListType = { { content: 'Spring 프레임 워크', weight: 'bold' }, { content: ', ', weight: 'normal' }, { content: '관계형 데이터베이스', weight: 'bold' }, - { - content: '와', - weight: 'normal', - }, + { content: '와', weight: 'normal' }, { content: 'AWS를 기반', weight: 'bold' }, { content: '으로 ', weight: 'normal' }, - { content: '서버 애플리케이션을 구축', weight: 'bold' }, + { content: '서버를 구축', weight: 'bold' }, { content: - '하고 운영하는 과정을 학습합니다. 또한 세미나, 코드리뷰, 스터디를 통해 개발 실력을 증진시키고, 기획자, 디자이너, 클라이언트 개발자와의 협업을 통해 협업 방식을 익힐 수 있습니다.', + '및 운영하는 과정을 학습합니다. 세미나, 코드리뷰, 스터디를 통해 개발 실력을 증진시킵니다.', weight: 'normal', }, ], @@ -367,14 +359,14 @@ export const keywordList: KeywordListType = { content: 'iOS 앱 서비스', ...indigoStyle, desktop: { top: '82.31px', right: 'calc(102px + 10vw)' }, - tablet: { top: '305px', right: 'calc(100px + 9.11vw)' }, + tablet: { top: '285px', right: 'calc(100px + 9.11vw)' }, mobile: { top: '178px', right: 'calc(50px + 12vw)' }, }, { content: 'Swift와 UI Kit', ...yellowStyle, desktop: { top: '117.6px', right: '6.72vw' }, - tablet: { top: '324px', right: '6.38vw' }, + tablet: { top: '314px', right: '6.38vw' }, mobile: { top: '188px', right: '6.07vw' }, }, { @@ -382,14 +374,14 @@ export const keywordList: KeywordListType = { backgroundColor: '#D65438', color: '#fff', desktop: { top: '223.74px', right: 'calc(33px + 5vw)' }, - tablet: { top: '400px', right: '16.79vw' }, + tablet: { top: '390px', right: '16.79vw' }, mobile: { top: '235px', right: '15.42vw' }, }, { content: '왕초보 스터디', ...blueStyle, desktop: { top: '275.88px', right: '19.02vw' }, - tablet: { top: '360px', right: '39.97vw' }, + tablet: { top: '350px', right: '33.97vw' }, mobile: { top: '212px', right: '38.78vw' }, }, ], @@ -421,28 +413,28 @@ export const keywordList: KeywordListType = { content: '서버 애플리케이션 구축', ...greenStyle, desktop: { top: '92.97px', right: '8.16vw' }, - tablet: { top: '301px', right: '12.10vw' }, + tablet: { top: '301px', right: '10.10vw' }, mobile: { top: '178px', right: '15.42vw' }, }, { content: '관계형 데이터베이스', ...indigoStyle, desktop: { top: '157.13px', right: 'calc(30px + 3.69vw)' }, - tablet: { top: '346px', right: '5.2vw' }, + tablet: { top: '346px', right: '4.2vw' }, mobile: { top: '203px', right: '8.4vw' }, }, { content: 'AWS 기반', ...skyStyle, desktop: { top: '192px', right: 'calc(110px + 15.1vw)' }, - tablet: { top: '323px', right: 'calc(110px + 28vw)' }, + tablet: { top: '323px', right: 'calc(100px + 22vw)' }, mobile: { top: '196px', right: '45.79vw' }, }, { content: 'Spring 프레임 워크', ...blueStyle, desktop: { top: '282.28px', right: '10.83vw' }, - tablet: { top: '389px', right: '25vw' }, + tablet: { top: '389px', right: '23vw' }, mobile: { top: '235px', right: '25.7vw' }, }, ], diff --git a/src/views/MainPage/components/Activity/Card/style.ts b/src/views/MainPage/components/Activity/Card/style.ts index cdc19a88..78976183 100644 --- a/src/views/MainPage/components/Activity/Card/style.ts +++ b/src/views/MainPage/components/Activity/Card/style.ts @@ -12,17 +12,20 @@ export const Background = styled(motion.main)` position: relative; z-index: 2; + @media (max-width: 768px) { + width: calc(100% - 5.46vw - 54px); + } + @media (max-width: 428px) and (min-width: 376px) { border-radius: 21px; max-width: 296px; - width: 100%; + width: calc(100% - 5.46vw - 31px); height: 188px; } @media (max-width: 375px) { border-radius: 21px; max-width: 258px; - width: 100%; height: 164px; } `; diff --git a/src/views/MainPage/components/Activity/MobileCard/index.tsx b/src/views/MainPage/components/Activity/MobileCard/index.tsx index 35956679..ca3231d7 100644 --- a/src/views/MainPage/components/Activity/MobileCard/index.tsx +++ b/src/views/MainPage/components/Activity/MobileCard/index.tsx @@ -22,40 +22,51 @@ export default function MobileCard() { return ( - - {infiniteCarouselList.map(({ value }, index) => { - const { img, navKor, navEng, description } = Activity[value]; - return ( - - - 왼쪽 화살표 handleCarouselSwipe(-1)} - /> - - - - 오른쪽 화살표 handleCarouselSwipe(1)} + + + 왼쪽 화살표 handleCarouselSwipe(-1)} + /> + + + {infiniteCarouselList.map(({ value }, index) => { + const { img, navKor, navEng, description } = Activity[value]; + return ( + + - - - ); - })} - + + ); + })} + + + 오른쪽 화살표 handleCarouselSwipe(1)} + /> + + + + 오른쪽 화살표 handleCarouselSwipe(1)} + /> + img:hover { cursor: pointer; @@ -63,11 +64,9 @@ export const Arrow = styled.div` @media (max-width: 768px) { width: 26px; - margin: 0 2.73vw 0 0; } @media (max-width: 428px) { - margin: 0 2.72vw 0 0; width: 15.293px; & > img { height: 24.138px; @@ -76,25 +75,15 @@ export const Arrow = styled.div` `; export const LeftArrow = styled(Arrow)` - margin: 0 0 0 1.5625vw; - - @media (max-width: 768px) { - margin: 0 2.73vw 0 0; - } - - @media (max-width: 428px) { - margin: 0 2.72vw 0 0; - } + left: 0; `; export const RightArrow = styled(Arrow)` - margin: 0 1.5625vw 0 0; - - @media (max-width: 768px) { - margin: 0 0 0 2.73vw; - } + right: 0; +`; - @media (max-width: 428px) { - margin: 0 0 0 2.72vw; - } +export const CarouselWrapper = styled.div` + position: relative; + overflow: hidden; + border-radius: 19px; `; diff --git a/src/views/MainPage/components/ActivitySection/style.ts b/src/views/MainPage/components/ActivitySection/style.ts index 310fd696..89cf9a6d 100644 --- a/src/views/MainPage/components/ActivitySection/style.ts +++ b/src/views/MainPage/components/ActivitySection/style.ts @@ -6,4 +6,13 @@ export const Wrapper = styled.div` gap: 146px; margin-bottom: 300px; + padding-top: 68px; + + @media (max-width: 768px) { + padding-top: 65px; + } + + @media (max-width: 428px) { + padding-top: 37.36px; + } `; diff --git a/src/views/MainPage/components/BottomLayout/index.tsx b/src/views/MainPage/components/BottomLayout/index.tsx index 2040b58c..5555a7f5 100644 --- a/src/views/MainPage/components/BottomLayout/index.tsx +++ b/src/views/MainPage/components/BottomLayout/index.tsx @@ -62,6 +62,7 @@ function BottomLayout() {
+
diff --git a/src/views/MainPage/components/BottomLayout/style.ts b/src/views/MainPage/components/BottomLayout/style.ts index 82dadc02..26b2809c 100644 --- a/src/views/MainPage/components/BottomLayout/style.ts +++ b/src/views/MainPage/components/BottomLayout/style.ts @@ -23,7 +23,7 @@ export const FloatingMenu = styled.div` flex-direction: column; gap: 9.27px; position: sticky; - top: 0; + top: 104px; height: fit-content; @@ -87,18 +87,17 @@ export const Menu = styled(Link)` export const Layout = styled(motion.div)` flex: 1; width: 80%; - padding: 68px 4vw 0 4vw; - border-radius: 20.946px; + padding: 0 4vw 0 4vw; + border-radius: 20.946px 20.946px 0 0; background: #f6f8fc; z-index: 1; @media (max-width: 768px) { width: 100%; - padding: 65px 6.25vw 0 6.25vw; - border-radius: 20.946px 20.946px 0 0; + padding: 0 6.25vw 0 6.25vw; } @media (max-width: 428px) { - padding: 37.36px 28px 0 28px; + padding: 0 6.54vw 0 6.54vw; } `; diff --git a/src/views/MainPage/components/IntroSection/IntroContent/style.ts b/src/views/MainPage/components/IntroSection/IntroContent/style.ts index 81c84b02..24c0c18e 100644 --- a/src/views/MainPage/components/IntroSection/IntroContent/style.ts +++ b/src/views/MainPage/components/IntroSection/IntroContent/style.ts @@ -84,8 +84,6 @@ export const Circle = styled(motion.div)` @media (max-width: 1440px) and (min-width: 769px) { grid-template-rows: auto 1fr; grid-gap: 24px 0px; - top: -170px; - left: -300.91px; } @media (max-width: 768px) { @@ -105,8 +103,8 @@ export const Content = styled(motion.div)` 'title image' 'desc image'; grid-template-rows: auto 1fr; - grid-template-columns: 590px minmax(323px, 707px); - grid-gap: 24px 57px; + grid-template-columns: max(540px, 30vw) minmax(323px, auto); + grid-gap: 24px max(36px, 2.96vw); position: relative; z-index: 20; @@ -130,7 +128,7 @@ export const Content = styled(motion.div)` export const ContentTitle = styled(motion.h2)` grid-area: title; - margin-top: 38px; + margin-top: 1.97vw; background: linear-gradient(93deg, #e1edf0 78.65%, #fff 128.82%, #e6eff2 137.19%); background-clip: text; @@ -138,7 +136,7 @@ export const ContentTitle = styled(motion.h2)` -webkit-text-fill-color: transparent; font-family: SUIT; - font-size: 48px; + font-size: max(40px, 2.5vw); font-style: normal; font-weight: 700; line-height: normal; @@ -162,7 +160,7 @@ export const ContentDetail = styled(motion.h3)` color: #b9c7c8; font-family: SUIT; - font-size: 24px; + font-size: max(20px, 1.25vw); font-style: normal; font-weight: 500; line-height: 160%; /* 38.4px */ @@ -171,7 +169,6 @@ export const ContentDetail = styled(motion.h3)` @media (max-width: 1440px) and (min-width: 769px) { font-size: 20px; - letter-spacing: -0.4px; word-break: keep-all; } @@ -191,12 +188,13 @@ export const ContentDetail = styled(motion.h3)` export const ContentImage = styled(Image)` grid-area: image; - width: 100%; + width: max(540px, 36.8vw); height: auto; - border-radius: 50px; + border-radius: max(36px, 2.6vw); object-fit: cover; @media (max-width: 1440px) and (min-width: 769px) { + width: 100%; max-width: 540px; min-height: 270px; border-radius: 36px; @@ -213,13 +211,13 @@ export const ContentImage = styled(Image)` export const BackLight = styled.div<{ isContentVisible: boolean }>` position: absolute; - top: -114.94px; - left: 385.37px; + top: 50%; + left: calc(300px - 5vw); z-index: -99; - width: 1954px; - height: 1084px; - transform: rotate(7.639deg); + width: max(1500px, 101.77vw); + height: max(900px, 56.45vw); + transform: rotate(7.639deg) translateY(-50%); background: radial-gradient(45.16% 45.16% at 50% 50%, #2c3242 0%, rgba(15, 15, 18, 0) 100%); opacity: ${({ isContentVisible }) => (isContentVisible ? '1' : '0')}; diff --git a/src/views/MainPage/components/PartConfig/PartButton.tsx/index.tsx b/src/views/MainPage/components/PartConfig/PartButton.tsx/index.tsx index 3e7793f3..4a9b09d7 100644 --- a/src/views/MainPage/components/PartConfig/PartButton.tsx/index.tsx +++ b/src/views/MainPage/components/PartConfig/PartButton.tsx/index.tsx @@ -1,3 +1,4 @@ +import { forwardRef, Ref } from 'react'; import * as S from './style'; interface PartButtonProps { @@ -7,10 +8,22 @@ interface PartButtonProps { handleSelectPart: (index: number) => void; } -export default function PartButton({ index, label, isSelected, handleSelectPart }: PartButtonProps) { +function PartButton( + { index, label, isSelected, handleSelectPart }: PartButtonProps, + ref: Ref, +) { return ( - handleSelectPart(index)}> + { + handleSelectPart(index); + e.currentTarget.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' }); + }} + > {label} ); } + +export default forwardRef(PartButton); diff --git a/src/views/MainPage/components/PartConfig/PartSlide/index.tsx b/src/views/MainPage/components/PartConfig/PartSlide/index.tsx index 7efeb9ab..9850ef1a 100644 --- a/src/views/MainPage/components/PartConfig/PartSlide/index.tsx +++ b/src/views/MainPage/components/PartConfig/PartSlide/index.tsx @@ -1,20 +1,15 @@ -import Image from 'next/image'; -import IcArrowLeft from '@src/assets/icons/ic_arrow_left.svg'; -import IcArrowRight from '@src/assets/icons/ic_arrow_right.svg'; import { useIsMobile, useIsTablet } from '@src/hooks/useDevice'; -import { DirectionType } from '@src/hooks/useInfiniteCarousel'; import { keywordList, partList } from '@src/lib/constants/main'; import { Part } from '@src/lib/types/universal'; import * as S from './style'; interface PartSlideProps { part: Part; - handleCarouselSwipe: (direction: DirectionType) => void; } -export default function PartSlide({ part, handleCarouselSwipe }: PartSlideProps) { +export default function PartSlide({ part }: PartSlideProps) { const { value, label, description } = partList[part]; - const isTablet = useIsTablet('429px', '768px'); + const isTablet = useIsTablet('429px', '1200px'); const isMobile = useIsMobile('428px'); const contentDraw = { initial: (custom: number) => ({ opacity: 0, y: 10 * (custom % 2) + 10 }), @@ -27,15 +22,6 @@ export default function PartSlide({ part, handleCarouselSwipe }: PartSlideProps) return ( - - 왼쪽 화살표 handleCarouselSwipe(-1)} - /> - @@ -66,15 +52,6 @@ export default function PartSlide({ part, handleCarouselSwipe }: PartSlideProps) ); })} - - 오른쪽 화살표 handleCarouselSwipe(1)} - /> - ); } diff --git a/src/views/MainPage/components/PartConfig/PartSlide/style.ts b/src/views/MainPage/components/PartConfig/PartSlide/style.ts index f1abd0d1..94067a4a 100644 --- a/src/views/MainPage/components/PartConfig/PartSlide/style.ts +++ b/src/views/MainPage/components/PartConfig/PartSlide/style.ts @@ -12,8 +12,8 @@ export const PartSlide = styled.div` border-radius: 19px; background: linear-gradient(98deg, #1a2035 33.84%, #304f84 96.92%); - @media (max-width: 768px) { - justify-content: normal; + @media (max-width: 1200px) { + justify-content: center; position: static; height: 488.493px; @@ -26,67 +26,25 @@ export const PartSlide = styled.div` } `; -export const Arrow = styled.div` - display: flex; - justify-content: center; - align-items: center; - margin: 0 0 0 1.5625vw; - - & > img:hover { - cursor: pointer; - } - - @media (max-width: 768px) { - width: 26px; - margin: 0 2.73vw 0 0; - } - - @media (max-width: 428px) { - margin: 0 2.72vw 0 0; - width: 15.293px; - & > img { - height: 24.138px; - } - } -`; - -export const LeftArrow = styled(Arrow)` - margin: 0 0 0 1.5625vw; - - @media (max-width: 768px) { - margin: 0 2.73vw 0 0; - } - - @media (max-width: 428px) { - margin: 0 2.72vw 0 0; - } -`; - -export const RightArrow = styled(Arrow)` - margin: 0 1.5625vw 0 0; - - @media (max-width: 768px) { - margin: 0 0 0 2.73vw; - } - - @media (max-width: 428px) { - margin: 0 0 0 2.72vw; - } -`; - export const Wrapper = styled.div` display: flex; width: 100%; - padding: 77px 0 62px 4.375vw; + padding: 77px 0 62px calc(4.375vw + 1.5625vw + 42px); - @media (max-width: 768px) { + @media (max-width: 1200px) { + width: calc(100% - 5.46vw - 54px); position: relative; - padding: 6.57vw 6.5vw 0 6.5vw; + padding: 4.57vw 5.5vw 0 5.5vw; border-radius: 19px; background: linear-gradient(98deg, #1a2035 33.84%, #304f84 96.92%); } + @media (max-width: 768px) { + padding: 6.57vw 6.5vw 0 6.5vw; + } + @media (max-width: 428px) { + width: calc(100% - 5.46vw - 31px); padding: 6.78vw 6.71vw 0 6.71vw; border-radius: 10.919px; } @@ -97,9 +55,9 @@ export const PartDetail = styled.div` flex-direction: column; justify-content: space-between; height: 100%; - width: calc(250px + 11vw); + width: calc(70px + 20vw); - @media (max-width: 768px) { + @media (max-width: 1200px) { justify-content: normal; width: 100%; } @@ -110,8 +68,8 @@ export const PartTop = styled.div` flex-direction: column; gap: 17px; - @media (max-width: 768px) { - gap: 5px; + @media (max-width: 1200px) { + gap: calc(3px + 0.4vw); } @media (max-width: 428px) { @@ -123,7 +81,6 @@ export const PartBadge = styled.div` display: flex; justify-content: center; align-items: center; - /* gap: 10px; */ width: fit-content; padding: 6px 15px; @@ -140,7 +97,7 @@ export const PartBadge = styled.div` line-height: 100%; /* 19px */ letter-spacing: -0.38px; - @media (max-width: 768px) { + @media (max-width: 1200px) { border-radius: 8.836px; font-size: 15px; letter-spacing: -0.3px; @@ -168,9 +125,9 @@ export const PartTitle = styled.div` line-height: 100%; /* 56px */ letter-spacing: -1.12px; - @media (max-width: 768px) { - height: 53.88px; - font-size: max(30px, 4.94vw); + @media (max-width: 1200px) { + height: calc(40px + 1.8vw); + font-size: max(30px, 4.34vw); line-height: 96%; /* 36.48px */ letter-spacing: -0.76px; @@ -198,8 +155,13 @@ export const Content = styled.span<{ weight: 'normal' | 'bold' }>` line-height: 162%; /* 30.78px */ letter-spacing: -0.38px; + @media (max-width: 1200px) { + font-size: 18px; + letter-spacing: -0.34px; + } + @media (max-width: 768px) { - font-size: max(14px, 2.21vw); + font-size: max(16px, 2.41vw); letter-spacing: -0.34px; } @@ -226,9 +188,15 @@ export const Keyword = styled(motion.div)` line-height: 162%; /* 35.64px */ letter-spacing: -0.44px; - @media (max-width: 768px) { + @media (max-width: 1200px) { padding: 13.115px 18.215px; - font-size: 16px; + font-size: max(16px, 1.5vw); + letter-spacing: -0.32px; + } + + @media (max-width: 768px) { + padding: 11.115px 16.215px; + font-size: max(14px, 2vw); letter-spacing: -0.32px; } diff --git a/src/views/MainPage/components/PartConfig/index.tsx b/src/views/MainPage/components/PartConfig/index.tsx index 8a5b0165..63c567e9 100644 --- a/src/views/MainPage/components/PartConfig/index.tsx +++ b/src/views/MainPage/components/PartConfig/index.tsx @@ -1,3 +1,7 @@ +import Image from 'next/image'; +import { useRef } from 'react'; +import IcArrowLeft from '@src/assets/icons/ic_arrow_left.svg'; +import IcArrowRight from '@src/assets/icons/ic_arrow_right.svg'; import useDrag from '@src/hooks/useDrag'; import useInfiniteCarousel from '@src/hooks/useInfiniteCarousel'; import { tabs as carouselList } from '@src/lib/constants/tabs'; @@ -9,6 +13,7 @@ import * as S from './style'; export default function PartConfig() { const { dragRef, handleMouseDown, handleMouseMove, initDragging } = useDrag(); + const partRef = useRef([]); const { carouselRef, infiniteCarouselList, @@ -17,7 +22,7 @@ export default function PartConfig() { handleCarouselSwipe, handleTouchStart, handleTouchEnd, - } = useInfiniteCarousel(carouselList, '(-100% - 20px)'); + } = useInfiniteCarousel(carouselList, '(-100% - 20px)', partRef); return (
@@ -40,6 +45,7 @@ export default function PartConfig() { {carouselList.map(({ label }, index) => ( (partRef.current[index] = el)} key={index} index={index} label={label} @@ -50,15 +56,33 @@ export default function PartConfig() { + + 왼쪽 화살표 handleCarouselSwipe(-1)} + /> + {infiniteCarouselList.map(({ value }, index) => ( - + ))} + + 오른쪽 화살표 handleCarouselSwipe(1)} + /> + 필요 역량이 궁금하다면? diff --git a/src/views/MainPage/components/PartConfig/style.ts b/src/views/MainPage/components/PartConfig/style.ts index ba59f013..27427f0b 100644 --- a/src/views/MainPage/components/PartConfig/style.ts +++ b/src/views/MainPage/components/PartConfig/style.ts @@ -1,5 +1,4 @@ import styled from '@emotion/styled'; -import { colors } from '@sopt-makers/colors'; import Link from 'next/link'; export const Wrapper = styled.div` @@ -27,7 +26,7 @@ export const PartButtonList = styled.div` display: flex; gap: 15px; - @media (max-width: 768px) { + @media (max-width: 1200px) { width: 776px; gap: 12.39px; } @@ -39,8 +38,14 @@ export const PartButtonList = styled.div` `; export const CarouselWrapper = styled.div` + position: relative; width: 100%; overflow: hidden; + border-radius: 19px; + + @media (max-width: 428px) { + border-radius: 10.919px; + } `; export const Carousel = styled.div` @@ -59,7 +64,7 @@ export const RequiredAbility = styled(Link)` letter-spacing: -0.8px; text-decoration-line: underline; - @media (max-width: 768px) { + @media (max-width: 1200px) { text-align: center; font-size: 15px; } @@ -68,3 +73,45 @@ export const RequiredAbility = styled(Link)` font-size: 10px; } `; + +export const Arrow = styled.div` + display: flex; + justify-content: center; + align-items: center; + + position: absolute; + top: 50%; + transform: translateY(-50%); + z-index: 99; + + & > img:hover { + cursor: pointer; + } + + @media (max-width: 1200px) { + width: 26px; + } + + @media (max-width: 428px) { + width: 15.293px; + & > img { + height: 24.138px; + } + } +`; + +export const LeftArrow = styled(Arrow)` + left: 1.5625vw; + + @media (max-width: 1200px) { + left: 0; + } +`; + +export const RightArrow = styled(Arrow)` + right: 1.5625vw; + + @media (max-width: 1200px) { + right: 0; + } +`; diff --git a/src/views/MainPage/components/RecentNews/index.tsx b/src/views/MainPage/components/RecentNews/index.tsx index 8c85ceca..ab6eaabd 100644 --- a/src/views/MainPage/components/RecentNews/index.tsx +++ b/src/views/MainPage/components/RecentNews/index.tsx @@ -5,7 +5,7 @@ import * as S from './style'; function RecentNews(_props: unknown, ref: React.Ref) { return ( -
+ 최신소식 SOPT의 최신 소식이 궁금하다면! @@ -27,7 +27,7 @@ function RecentNews(_props: unknown, ref: React.Ref) { 더 많은 소식이 궁금하다면 -
+ ); } diff --git a/src/views/MainPage/components/RecentNews/style.ts b/src/views/MainPage/components/RecentNews/style.ts index 55ea4584..6d8d529b 100644 --- a/src/views/MainPage/components/RecentNews/style.ts +++ b/src/views/MainPage/components/RecentNews/style.ts @@ -4,7 +4,15 @@ import Link from 'next/link'; import Slider from 'react-slick'; import { ReactComponent as IconInstagram } from '@src/assets/icons/ic_instagram.svg'; -export const TitleWrapper = styled.section` +export const RecentNews = styled.section` + padding-top: 75px; + + @media (max-width: 768px) { + padding-top: 0; + } +`; + +export const TitleWrapper = styled.div` margin-left: 10px; @media (max-width: 768px) and (min-width: 429px) {