Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SP3] 메인 하단 레이아웃 #324

Merged
merged 11 commits into from
Dec 21, 2023
3 changes: 3 additions & 0 deletions src/assets/icons/ic_polygon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions src/hooks/useInView.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { useState } from 'react';
import useIntersectionObserver from './useIntersectionObserver';

function useInView() {
const ref = useIntersectionObserver(() => setIsInView(true));
interface useInViewProps {
options?: IntersectionObserverInit;
}

function useInView({ options }: useInViewProps = {}) {
const ref = useIntersectionObserver((entry) => {
setIsInView(entry.isIntersecting);
}, options);
const [isInView, setIsInView] = useState(false);

return { isInView, ref };
Expand Down
4 changes: 1 addition & 3 deletions src/hooks/useIntersectionObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ const useIntersectionObserver = (
const callback = useCallback(
(entries: IntersectionObserverEntry[], observer: IntersectionObserver) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
onIntersect(entry, observer);
}
onIntersect(entry, observer);
});
},
[onIntersect],
Expand Down
8 changes: 2 additions & 6 deletions src/views/MainPage/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import PageLayout from '@src/components/common/PageLayout';
import BottomLayout from '@src/views/MainPage/components/BottomLayout';
import IntroSection from '@src/views/MainPage/components/IntroSection';
import PartConfig from '@src/views/MainPage/components/PartConfig';
import Activity from './components/Activity';
import Banner from './components/Banner';
import Introduce from './components/Introduce';
import OwnOrganization from './components/OwnOrganization';
import ScrollInteractiveLogo from './components/ScrollInteractiveLogo';

function MainPage() {
Expand All @@ -14,9 +12,7 @@ function MainPage() {
<Introduce />
<IntroSection />
<ScrollInteractiveLogo />
<Activity />
<PartConfig />
<OwnOrganization />
<BottomLayout />
</PageLayout>
);
}
Expand Down
6 changes: 3 additions & 3 deletions src/views/MainPage/components/Activity/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import MobileCard from './MobileCard';
import * as S from './style';

export default function CardHover() {
const isMobileSize = useIsMobile('768px');
const isMobileSize = useIsMobile('428px');

return (
<S.Background>
<div>
<Tab
tab={'(1) 기수내 정기 행사'}
title={'매 기수 진행되는, 다양한 활동들!'}
Expand All @@ -34,6 +34,6 @@ export default function CardHover() {
})}
</S.CardWrapper>
)}
</S.Background>
</div>
);
}
4 changes: 0 additions & 4 deletions src/views/MainPage/components/Activity/style.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import styled from '@emotion/styled';
import { colors } from '@sopt-makers/colors';

Check warning on line 2 in src/views/MainPage/components/Activity/style.ts

View workflow job for this annotation

GitHub Actions / continuous-integration

'colors' is defined but never used

export const Background = styled.section`
background-color: ${colors.white};
`;

export const CardWrapper = styled.main`
display: grid;
grid-template-columns: repeat(3, 1fr);
Expand Down
17 changes: 17 additions & 0 deletions src/views/MainPage/components/ActivitySection/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { forwardRef } from 'react';
import Activity from '@src/views/MainPage/components/Activity';
import OwnOrganization from '@src/views/MainPage/components/OwnOrganization';
import PartConfig from '@src/views/MainPage/components/PartConfig';
import * as S from './style';

function ActivitySection(_props: unknown, ref: React.Ref<HTMLDivElement>) {
return (
<S.Wrapper id="activity" ref={ref}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image 피그마 해당 섹션 위에 여백이 있는데 현재 작업에는 없더라구요..! 작업물 합치고, 헤더 작업을 할때 수정해야할 부분인 것 같습니다! 스크린샷 2023-12-20 오후 2 03 40

<Activity />
Comment on lines +7 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Activity 컴포넌트에 활동 내역이 담겨있어서 Activity라고 명을 지었는데, 메뉴에서 활동/파트/자체기구를 합친 명이 Activity 군요..!
메뉴명과 동일하게 ActivitySection은 유지하는게 맞는 것 같고 Activity 컴포넌트 명을 변경하면 좋을 것 같은데, 어떻게 생각하시나요?!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 찬성해요!!!

<PartConfig />
<OwnOrganization />
</S.Wrapper>
);
}

export default forwardRef(ActivitySection);
9 changes: 9 additions & 0 deletions src/views/MainPage/components/ActivitySection/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import styled from '@emotion/styled';

export const Wrapper = styled.div`
display: flex;
flex-direction: column;
gap: 146px;

margin-bottom: 300px;
`;
62 changes: 62 additions & 0 deletions src/views/MainPage/components/BottomLayout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useScroll, useTransform } from 'framer-motion';
import { RefObject, useRef } from 'react';
import useInView from '@src/hooks/useInView';
import ActivitySection from '@src/views/MainPage/components/ActivitySection';
import * as S from './style';

const MenuList = [
{ name: 'Value', id: 'value' },
{ name: 'Activity', id: 'activity' },
{ name: 'Review', id: 'review' },
{ name: 'Recent news', id: 'news' },
];

export type RefHandler = {
viewRef: RefObject<HTMLDivElement>;
targetRef: RefObject<HTMLDivElement>;
};

function BottomLayout() {
const activity = useInView();
const review = useInView();
const news = useInView();

const targetRef = useRef<HTMLDivElement>(null);
const { scrollYProgress } = useScroll({ target: targetRef, offset: ['start center', 'start'] });

const viewList = [false, activity.isInView, review.isInView, news.isInView];
const minIndex = viewList.findIndex((value) => value === true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minIndex 의 의미는 무엇인가요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intersectionObserver를 사용해서 현재 위치한 섹션의 메뉴명에만 색이 들어오게 하고 있는데 viewport에 두 가지 섹션이 한번에 들어왔을 경우 앞에 있는 섹션에만 색이 들어오도록 하기 위해서 작성한 코드입니다!
image


const wrapperBackground = useTransform(scrollYProgress, [0, 1], ['#FFF', '#090B12']);
const layoutBackground = useTransform(scrollYProgress, [0, 1], ['#F6F8FC', '#0D111F']);
const menuBackground = useTransform(scrollYProgress, [0, 1], ['#fbfcfe', '#fbfcfef']);
const menuColor = useTransform(scrollYProgress, [0, 1], ['#a8acbae0', '#747885']);

return (
<S.Wrapper style={{ backgroundColor: wrapperBackground }}>
<S.FloatingMenu>
{MenuList.map(({ name, id }, index) => (
<S.MenuWrapper
key={id}
isInView={minIndex === index}
style={{ backgroundColor: menuBackground, color: menuColor }}
>
<S.Menu href={`#${id}`}>{name}</S.Menu>
</S.MenuWrapper>
))}
</S.FloatingMenu>
<S.Layout style={{ backgroundColor: layoutBackground }}>
<ActivitySection ref={activity.ref} />
<div ref={targetRef} />
<div id="review" ref={review.ref} style={{ height: '100vh', background: 'blue' }}>
Reviews
</div>
<div id="news" ref={news.ref} style={{ height: '100vh', background: 'yellow' }}>
News
</div>
</S.Layout>
</S.Wrapper>
);
}

export default BottomLayout;
101 changes: 101 additions & 0 deletions src/views/MainPage/components/BottomLayout/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import styled from '@emotion/styled';
import { colors } from '@sopt-makers/colors';
import { motion } from 'framer-motion';
import Link from 'next/link';
import { css } from '@emotion/react';
import icPolygon from '@src/assets/icons/ic_polygon.svg';

export const Wrapper = styled(motion.section)`
display: flex;
gap: 12.25px;

width: 100%;
padding: 0 2.86vw;
background-color: ${colors.white};

@media (max-width: 768px) {
padding: 0 5.98vw;
}
`;

export const FloatingMenu = styled.div`
display: flex;
flex-direction: column;
gap: 9.27px;
position: sticky;
top: 0;

height: fit-content;

@media (max-width: 768px) {
display: none;
}
`;

export const MenuWrapper = styled(motion.div)<{ isInView?: boolean }>`
position: relative;

background-color: #fbfcfe;
border-radius: 10px;
border: 1.2px solid rgba(196, 199, 211, 0.3);

color: rgba(168, 172, 186, 0.88);
text-align: center;
font-family: SUIT;
font-size: 19.46px;
font-style: normal;
font-weight: 500;
line-height: 53.54px; /* 275.126% */
letter-spacing: -0.584px;

${({ isInView }) =>
isInView &&
css`
border-color: transparent;
background-color: #24314d !important;
color: #fff !important;

&::after {
content: '';
position: absolute;
top: 50%;
right: -8px;
transform: translateY(-50%);
z-index: 99;

width: 8px;
height: 11px;
background-image: url(${icPolygon});
background-repeat: no-repeat;
}
`};
`;

export const Menu = styled(Link)`
display: flex;
justify-content: center;
align-items: center;

width: 190px;
height: 72px;

@media (max-width: 1440px) {
width: 152px;
}
`;

export const Layout = styled(motion.div)`
flex: 1;
width: 80%;
padding: 68px 4vw 0 4vw;
border-radius: 20.946px;
background: #f6f8fc;

@media (max-width: 768px) {
padding: 65px 6.25vw 0 6.25vw;
}

@media (max-width: 428px) {
padding: 37.36px 28px 0 28px;
}
`;
4 changes: 2 additions & 2 deletions src/views/MainPage/components/IntroSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import * as S from './style';

export default function IntroCardList() {
return (
<S.IntroSection>
<S.IntroSection >
<S.Header />
<div style={{ overflow: 'hidden' }}>
<div id="value" style={{ overflow: 'hidden' }}>
{INTRO_CONTENT_LIST.map((content) => (
<IntroContent key={content.id} content={content} />
))}
Expand Down
4 changes: 2 additions & 2 deletions src/views/MainPage/components/OwnOrganization/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as S from './style';

export default function OwnOrganization() {
return (
<S.Background>
<div>
<Tab
tab={'(3) 자체 운영 기구'}
title={'SOPT를 운영하는 자체 기구'}
Expand All @@ -18,6 +18,6 @@ export default function OwnOrganization() {
<OwnOrganizationCard key={organization.nameEng} {...organization} />
))}
</S.Wrapper>
</S.Background>
</div>
);
}
5 changes: 0 additions & 5 deletions src/views/MainPage/components/OwnOrganization/style.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import styled from '@emotion/styled';
import { colors } from '@sopt-makers/colors';

Check warning on line 2 in src/views/MainPage/components/OwnOrganization/style.ts

View workflow job for this annotation

GitHub Actions / continuous-integration

'colors' is defined but never used

export const Wrapper = styled.div`
display: flex;
Expand All @@ -15,8 +15,3 @@
gap: 14px;
}
`;

export const Background = styled.section`
background-color: ${colors.white};
padding-top: 146px;
`;
4 changes: 2 additions & 2 deletions src/views/MainPage/components/PartConfig/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function PartConfig() {
} = useInfiniteCarousel<TabType>(carouselList, '(-100% - 20px)');

return (
<S.Background>
<div>
<Tab
tab={'(2) 파트 구성'}
title={'6개의 파트로 이루어져 있어요.'}
Expand Down Expand Up @@ -63,6 +63,6 @@ export default function PartConfig() {
</S.PartConfig>
<S.RequiredAbility href="/recruit#chapter-info">필요 역량이 궁금하다면?</S.RequiredAbility>
</S.Wrapper>
</S.Background>
</div>
);
}
4 changes: 0 additions & 4 deletions src/views/MainPage/components/PartConfig/style.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import styled from '@emotion/styled';
import { colors } from '@sopt-makers/colors';

Check warning on line 2 in src/views/MainPage/components/PartConfig/style.ts

View workflow job for this annotation

GitHub Actions / continuous-integration

'colors' is defined but never used
import Link from 'next/link';

export const Background = styled.section`
background-color: ${colors.white};
`;

export const Wrapper = styled.div`
display: flex;
flex-direction: column;
Expand Down
Loading