Skip to content

Commit

Permalink
Refactor/#465 데스크탑 환경에서 스와이프가 동작하도록 레이아웃을 개선한다. (#487)
Browse files Browse the repository at this point in the history
* feat: Flex 레이아웃 컴포넌트 구현

* design: PC 반응형 디자인 개선 임시 저장

* refactor: Flex 컴포넌트 개선

프로젝트 반응형 사이즈 대응 prop 추가 및 type 선언

* feat: breakPoint type 추가

* design: youtube 컴포넌트의 flex wrapping 제거

* fix: 스타일 컴포넌트가 잘못 참조했던 Flex 컴포넌트 수정

ref 정상 동작하도록 변경

* design: 1페이지 단위의 높이를 가지도록 디자인 변경

* design: 인터페이스 상단 수평선 맞춤

* design: 모든 디바이스에서 스크롤 스냅 적용

* design: 전체 컨테이너의 배경색을 넣어 공간감을 줌

* design: Layout의 상하단 패딩 제거 및 스와이프 관련 컴포넌트 높이 고정

1. 기존 Header를 sticky -> fixed 로 변경하면서, 스와이프 아이템에 header 만큼의 padding-top을 부여하였음.
2. 때문에 더이상 필요하지 않은 반응형 높이 제어를 속성들을 삭제하고 100vh로 고정
3. 마찬가지로 혼동을 주는 Layout의 상하단 padding 삭제 및 0으로 고정

* design: 스크롤 이슈로 main 영역 padding 줄임

* design: 가수, 제목 텍스트 디테일 처리로 듣기 인터페이스 짤리지 않도록 함

* design: FHD 기준 좌우 padding 수정

* refactor: as prop $ 제거 및 default parameter 적용

* refactor(Flex): react 컴포넌트-> styled 컴포넌트로 변경

이미 스타일 컴포넌트가 제공하고 있는 다형성, html attribytes 관련 type 중복을 제거함.

* style: 스타일 린트 적용
  • Loading branch information
Creative-Lee authored Oct 4, 2023
1 parent 790da5f commit b03ace9
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 72 deletions.
10 changes: 8 additions & 2 deletions frontend/src/features/songs/components/KillingPartInterface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from 'react';
import { styled } from 'styled-components';
import CommentList from '@/features/comments/components/CommentList';
import useVideoPlayerContext from '@/features/youtube/hooks/useVideoPlayerContext';
import Flex from '@/shared/components/Flex/Flex';
import Spacing from '@/shared/components/Spacing';
import useTimerContext from '@/shared/components/Timer/hooks/useTimerContext';
import ToggleSwitch from '@/shared/components/ToggleSwitch/ToggleSwitch';
Expand Down Expand Up @@ -120,7 +121,7 @@ const KillingPartInterface = ({ killingParts, songId }: KillingPartInterfaceProp
}, [pause]);

return (
<>
<Flex $direction="column">
<FlexContainer ref={observingTargetRef}>
<TitleWrapper aria-label="Top 3 킬링파트 듣기">
<ItalicTitle aria-hidden="true">Top 3</ItalicTitle>
Expand All @@ -147,7 +148,7 @@ const KillingPartInterface = ({ killingParts, songId }: KillingPartInterfaceProp
{commentsPartId !== DEFAULT_PART_ID && (
<CommentList songId={songId} partId={commentsPartId} />
)}
</>
</Flex>
);
};

Expand Down Expand Up @@ -186,4 +187,9 @@ const FlexContainer = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
height: 60px;
@media (max-width: ${({ theme }) => theme.breakPoints.md}) {
height: auto;
}
`;
55 changes: 35 additions & 20 deletions frontend/src/features/songs/components/SongDetailItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import KillingPartInterface from '@/features/songs/components/KillingPartInterfa
import Thumbnail from '@/features/songs/components/Thumbnail';
import { VideoPlayerProvider } from '@/features/youtube/components/VideoPlayerProvider';
import Youtube from '@/features/youtube/components/Youtube';
import Flex from '@/shared/components/Flex';
import Flex from '@/shared/components/Flex/Flex';
import Spacing from '@/shared/components/Spacing';
import SRHeading from '@/shared/components/SRHeading';
import TimerProvider from '@/shared/components/Timer/TimerProvider';
Expand Down Expand Up @@ -43,20 +43,27 @@ const SongDetailItem = forwardRef<HTMLDivElement, SongDetailItemProps>(
return (
<Container ref={ref} role="article" data-song-id={id}>
<SRHeading>킬링파트 듣기 페이지</SRHeading>
<SongInfoContainer>
<Thumbnail src={albumCoverUrl} size="md" />
<Info>
<SongTitle aria-label={`노래 ${title}`}>{title}</SongTitle>
<Singer aria-label={`가수 ${singer}`}>{singer}</Singer>
</Info>
</SongInfoContainer>
<Spacing direction="vertical" size={16} />
<VideoPlayerProvider>
<Youtube videoId={songVideoId} />
<Spacing direction="vertical" size={12} />
<TimerProvider time={15}>
<KillingPartInterface killingParts={killingParts} songId={id} />
</TimerProvider>
<Flex
$gap={16}
$md={{ $direction: 'column' }}
$css={{ padding: '16px', background: '#121212c8', borderRadius: '8px' }}
>
<Flex $direction="column" $css={{ flex: '3 1 0' }}>
<SongInfoContainer>
<Thumbnail src={albumCoverUrl} size="md" />
<Info>
<SongTitle aria-label={`노래 ${title}`}>{title}</SongTitle>
<Singer aria-label={`가수 ${singer}`}>{singer}</Singer>
</Info>
</SongInfoContainer>
<Spacing direction="vertical" size={16} />
<Youtube videoId={songVideoId} />
</Flex>
<TimerProvider time={15}>
<KillingPartInterface killingParts={killingParts} songId={id} />
</TimerProvider>
</Flex>
</VideoPlayerProvider>
<div ref={navigateToCurrentSongId} />
</Container>
Expand All @@ -68,9 +75,10 @@ SongDetailItem.displayName = 'SongDetailItem';

export default SongDetailItem;

const Container = styled(Flex)`
const Container = styled.div`
display: flex;
flex-direction: column;
height: 100%;
height: 100vh;
padding-top: ${({ theme: { headerHeight } }) => headerHeight.desktop};
@media (max-width: ${({ theme }) => theme.breakPoints.xs}) {
Expand All @@ -97,15 +105,22 @@ const SongInfoContainer = styled.div`
const Info = styled.div``;

const SongTitle = styled.div`
height: 30px;
font-size: 20px;
font-weight: 700;
color: ${({ theme: { color } }) => color.white};
@media (max-width: ${({ theme }) => theme.breakPoints.md}) {
@media (max-width: ${({ theme }) => theme.breakPoints.lg}) {
width: 220px;
font-size: 18px;
}
@media (max-width: ${({ theme }) => theme.breakPoints.xs}) {
overflow: hidden;
font-size: 16px;
text-overflow: ellipsis;
white-space: nowrap;
}
@media (max-width: ${({ theme }) => theme.breakPoints.xxs}) {
font-size: 16px;
}
Expand All @@ -116,11 +131,11 @@ const Singer = styled.div`
font-weight: 700;
color: ${({ theme: { color } }) => color.subText};
@media (max-width: ${({ theme }) => theme.breakPoints.md}) {
@media (max-width: ${({ theme }) => theme.breakPoints.lg}) {
font-size: 16px;
}
@media (max-width: ${({ theme }) => theme.breakPoints.xxs}) {
@media (max-width: ${({ theme }) => theme.breakPoints.xs}) {
font-size: 14px;
}
`;
2 changes: 1 addition & 1 deletion frontend/src/pages/EditProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ const disabledStyle = css<{ disabled: boolean }>`

const Input = styled.input<{ disabled: boolean }>`
${disabledStyle};
font-size: 16px;
padding: 0 8px;
font-size: 16px;
`;

const TextArea = styled.textarea<{ disabled: boolean }>`
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/pages/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,12 @@ const PlatformName = styled.div`
display: flex;
align-items: center;
justify-content: center;
text-align: center;
width: 400px;
height: 60px;
text-align: center;
border-radius: 12px;
@media (max-width: ${({ theme }) => theme.breakPoints.xs}) {
Expand Down
32 changes: 6 additions & 26 deletions frontend/src/pages/SongDetailListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,34 +144,14 @@ export const ObservingTrigger = styled.div`
`;

export const ItemContainer = styled.div`
scroll-snap-type: y mandatory;
overflow-y: scroll;
width: 100%;
height: 100vh;
@media (max-width: ${({ theme }) => theme.breakPoints.md}) {
scroll-snap-type: y mandatory;
overflow-y: scroll;
height: calc(
${({ theme: { mainTopBottomPadding } }) => {
return `100vh - ${mainTopBottomPadding.tablet} * 2`;
}}
);
& > div[role='article'] {
scroll-snap-align: start;
scroll-snap-stop: always;
}
}
@media (max-width: ${({ theme }) => theme.breakPoints.xxs}) {
height: calc(
${({ theme: { mainTopBottomPadding } }) => {
return `100vh - ${mainTopBottomPadding.xxs} * 2`;
}}
);
& > div[role='article'] {
scroll-snap-align: start;
scroll-snap-stop: always;
}
& > div[role='article'] {
scroll-snap-align: start;
scroll-snap-stop: always;
}
`;

Expand Down
69 changes: 69 additions & 0 deletions frontend/src/shared/components/Flex/Flex.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import styled, { css } from 'styled-components';
import type { BreakPoints } from '@/shared/types/theme';
import type { CSSProp } from 'styled-components';

interface FlexBox {
$direction?: React.CSSProperties['flexDirection'];
$wrap?: React.CSSProperties['flexWrap'];
$gap?: number;
$align?: React.CSSProperties['alignItems'];
$justify?: React.CSSProperties['justifyContent'];
$css?: CSSProp;
}

interface ResponsiveFlexBox extends Partial<Record<`$${BreakPoints}`, FlexBox>> {}

interface FlexProps extends FlexBox, ResponsiveFlexBox {}

const Flex = styled.div<FlexProps>`
display: flex;
flex-direction: ${({ $direction = 'row' }) => $direction};
flex-wrap: ${({ $wrap = 'nowrap' }) => $wrap};
gap: ${({ $gap = 0 }) => `${$gap}px`};
align-items: ${({ $align = 'stretch' }) => $align};
justify-content: ${({ $justify = 'flex-start' }) => $justify};
${({ $css }) => $css}
@media (max-width: ${({ theme }) => theme.breakPoints.xxl}) {
${({ $xxl }) => flexCss($xxl)}
}
@media (max-width: ${({ theme }) => theme.breakPoints.xl}) {
${({ $xl }) => flexCss($xl)}
}
@media (max-width: ${({ theme }) => theme.breakPoints.lg}) {
${({ $lg }) => flexCss($lg)}
}
@media (max-width: ${({ theme }) => theme.breakPoints.md}) {
${({ $md }) => flexCss($md)}
}
@media (max-width: ${({ theme }) => theme.breakPoints.sm}) {
${({ $sm }) => flexCss($sm)}
}
@media (max-width: ${({ theme }) => theme.breakPoints.xs}) {
${({ $xs }) => flexCss($xs)}
}
@media (max-width: ${({ theme }) => theme.breakPoints.xxs}) {
${({ $xxs }) => flexCss($xxs)}
}
`;

export default Flex;

const flexCss = (flexBox?: FlexBox) => {
if (!flexBox) return;
const { $align, $direction, $gap, $justify, $wrap } = flexBox;

return css`
flex-direction: ${$direction};
flex-wrap: ${$wrap};
gap: ${$gap && `${$gap}px`};
align-items: ${$align};
justify-content: ${$justify};
`;
};
5 changes: 2 additions & 3 deletions frontend/src/shared/components/Layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ const Container = styled.header`
width: 100%;
height: ${({ theme }) => theme.headerHeight.desktop};
padding: 0 16.66%;
padding: 0 12.33%;
background-color: ${({ theme: { color } }) => color.black};
@media (max-width: ${({ theme }) => theme.breakPoints.xl}) {
@media (max-width: ${({ theme }) => theme.breakPoints.xxl}) {
padding: 0 8.33%;
}
Expand All @@ -59,7 +59,6 @@ const Container = styled.header`
@media (max-width: ${({ theme }) => theme.breakPoints.xxs}) {
height: ${({ theme }) => theme.headerHeight.xxs};
padding: 0 16px;
}
`;

Expand Down
14 changes: 5 additions & 9 deletions frontend/src/shared/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,21 @@ const LayoutContainer = styled.main`
width: 100%;
min-height: 100vh;
padding: ${({ theme: { mainTopBottomPadding } }) => `${mainTopBottomPadding.desktop} 16.66%`};
padding: 0 12.33%;
color: ${({ theme: { color } }) => color.white};
background-color: ${({ theme: { color } }) => color.black};
@media (max-width: ${({ theme }) => theme.breakPoints.xl}) {
padding: ${({ theme: { mainTopBottomPadding } }) => `${mainTopBottomPadding.desktop} 8.33%`};
@media (max-width: ${({ theme }) => theme.breakPoints.xxl}) {
padding: 0 8.33%;
}
@media (max-width: ${({ theme }) => theme.breakPoints.md}) {
padding: ${({ theme: { mainTopBottomPadding } }) => `${mainTopBottomPadding.tablet} 4.16%`};
}
@media (max-width: ${({ theme }) => theme.breakPoints.xs}) {
padding: ${({ theme: { mainTopBottomPadding } }) => `${mainTopBottomPadding.tablet} 4.16%`};
padding: 0 4.16%;
}
@media (max-width: ${({ theme }) => theme.breakPoints.xxs}) {
padding: ${({ theme: { mainTopBottomPadding } }) => `${mainTopBottomPadding.xxs} 16px`};
padding: 0 16px;
}
`;
2 changes: 1 addition & 1 deletion frontend/src/shared/styles/GlobalStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ const GlobalStyles = createGlobalStyle`
color: inherit;
&::-webkit-scrollbar {
display: none;
background: transparent;
width: 0;
height: 0;
background: transparent;
}
}
*,
Expand Down
7 changes: 0 additions & 7 deletions frontend/src/shared/styles/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,6 @@ const theme = {
tablet: '80px',
desktop: '80px',
},

mainTopBottomPadding: {
xxs: '8px',
mobile: '16px',
tablet: '16px',
desktop: '36px',
},
} as const;

export default theme;
4 changes: 2 additions & 2 deletions frontend/src/shared/types/theme.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// eslint-disable-next-line
import theme from '@/shared/styles/theme';
import type theme from '@/shared/styles/theme';

export type ThemeType = typeof theme;
export type BreakPoints = keyof typeof theme.breakPoints;

0 comments on commit b03ace9

Please sign in to comment.