From b03ace95d3e2ef120c30d67a3c422a2f3914f56e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=9D=B4=EB=8F=84=ED=98=84?=
<77152650+Creative-Lee@users.noreply.github.com>
Date: Wed, 4 Oct 2023 10:52:50 +0900
Subject: [PATCH] =?UTF-8?q?Refactor/#465=20=EB=8D=B0=EC=8A=A4=ED=81=AC?=
=?UTF-8?q?=ED=83=91=20=ED=99=98=EA=B2=BD=EC=97=90=EC=84=9C=20=EC=8A=A4?=
=?UTF-8?q?=EC=99=80=EC=9D=B4=ED=94=84=EA=B0=80=20=EB=8F=99=EC=9E=91?=
=?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=A0=88=EC=9D=B4=EC=95=84?=
=?UTF-8?q?=EC=9B=83=EC=9D=84=20=EA=B0=9C=EC=84=A0=ED=95=9C=EB=8B=A4.=20?=
=?UTF-8?q?=20(#487)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 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: 스타일 린트 적용
---
.../songs/components/KillingPartInterface.tsx | 10 ++-
.../songs/components/SongDetailItem.tsx | 55 +++++++++------
frontend/src/pages/EditProfilePage.tsx | 2 +-
frontend/src/pages/LoginPage.tsx | 3 +-
frontend/src/pages/SongDetailListPage.tsx | 32 ++-------
frontend/src/shared/components/Flex/Flex.tsx | 69 +++++++++++++++++++
.../src/shared/components/Layout/Header.tsx | 5 +-
.../src/shared/components/Layout/Layout.tsx | 14 ++--
frontend/src/shared/styles/GlobalStyles.ts | 2 +-
frontend/src/shared/styles/theme.ts | 7 --
frontend/src/shared/types/theme.ts | 4 +-
11 files changed, 131 insertions(+), 72 deletions(-)
create mode 100644 frontend/src/shared/components/Flex/Flex.tsx
diff --git a/frontend/src/features/songs/components/KillingPartInterface.tsx b/frontend/src/features/songs/components/KillingPartInterface.tsx
index ec89b4ebe..b2aec0997 100644
--- a/frontend/src/features/songs/components/KillingPartInterface.tsx
+++ b/frontend/src/features/songs/components/KillingPartInterface.tsx
@@ -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';
@@ -120,7 +121,7 @@ const KillingPartInterface = ({ killingParts, songId }: KillingPartInterfaceProp
}, [pause]);
return (
- <>
+
Top 3
@@ -147,7 +148,7 @@ const KillingPartInterface = ({ killingParts, songId }: KillingPartInterfaceProp
{commentsPartId !== DEFAULT_PART_ID && (
)}
- >
+
);
};
@@ -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;
+ }
`;
diff --git a/frontend/src/features/songs/components/SongDetailItem.tsx b/frontend/src/features/songs/components/SongDetailItem.tsx
index cfb76f912..b69d40b14 100644
--- a/frontend/src/features/songs/components/SongDetailItem.tsx
+++ b/frontend/src/features/songs/components/SongDetailItem.tsx
@@ -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';
@@ -43,20 +43,27 @@ const SongDetailItem = forwardRef(
return (
킬링파트 듣기 페이지
-
-
-
- {title}
- {singer}
-
-
-
-
-
-
-
-
+
+
+
+
+
+ {title}
+ {singer}
+
+
+
+
+
+
+
+
+
@@ -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}) {
@@ -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;
}
@@ -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;
}
`;
diff --git a/frontend/src/pages/EditProfilePage.tsx b/frontend/src/pages/EditProfilePage.tsx
index 1ca633601..4191e8e0c 100644
--- a/frontend/src/pages/EditProfilePage.tsx
+++ b/frontend/src/pages/EditProfilePage.tsx
@@ -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 }>`
diff --git a/frontend/src/pages/LoginPage.tsx b/frontend/src/pages/LoginPage.tsx
index 68e9aefe8..2b18b499a 100644
--- a/frontend/src/pages/LoginPage.tsx
+++ b/frontend/src/pages/LoginPage.tsx
@@ -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}) {
diff --git a/frontend/src/pages/SongDetailListPage.tsx b/frontend/src/pages/SongDetailListPage.tsx
index 353b6055e..7c14447b3 100644
--- a/frontend/src/pages/SongDetailListPage.tsx
+++ b/frontend/src/pages/SongDetailListPage.tsx
@@ -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;
}
`;
diff --git a/frontend/src/shared/components/Flex/Flex.tsx b/frontend/src/shared/components/Flex/Flex.tsx
new file mode 100644
index 000000000..83818cf7c
--- /dev/null
+++ b/frontend/src/shared/components/Flex/Flex.tsx
@@ -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> {}
+
+interface FlexProps extends FlexBox, ResponsiveFlexBox {}
+
+const Flex = styled.div`
+ 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};
+ `;
+};
diff --git a/frontend/src/shared/components/Layout/Header.tsx b/frontend/src/shared/components/Layout/Header.tsx
index aaf3c48bd..e3201c7f6 100644
--- a/frontend/src/shared/components/Layout/Header.tsx
+++ b/frontend/src/shared/components/Layout/Header.tsx
@@ -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%;
}
@@ -59,7 +59,6 @@ const Container = styled.header`
@media (max-width: ${({ theme }) => theme.breakPoints.xxs}) {
height: ${({ theme }) => theme.headerHeight.xxs};
- padding: 0 16px;
}
`;
diff --git a/frontend/src/shared/components/Layout/Layout.tsx b/frontend/src/shared/components/Layout/Layout.tsx
index e34f96cda..a0d6aaf7a 100644
--- a/frontend/src/shared/components/Layout/Layout.tsx
+++ b/frontend/src/shared/components/Layout/Layout.tsx
@@ -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;
}
`;
diff --git a/frontend/src/shared/styles/GlobalStyles.ts b/frontend/src/shared/styles/GlobalStyles.ts
index b1f6e3913..e34e3eed7 100644
--- a/frontend/src/shared/styles/GlobalStyles.ts
+++ b/frontend/src/shared/styles/GlobalStyles.ts
@@ -18,9 +18,9 @@ const GlobalStyles = createGlobalStyle`
color: inherit;
&::-webkit-scrollbar {
display: none;
- background: transparent;
width: 0;
height: 0;
+ background: transparent;
}
}
*,
diff --git a/frontend/src/shared/styles/theme.ts b/frontend/src/shared/styles/theme.ts
index 0824ae00b..06172117b 100644
--- a/frontend/src/shared/styles/theme.ts
+++ b/frontend/src/shared/styles/theme.ts
@@ -37,13 +37,6 @@ const theme = {
tablet: '80px',
desktop: '80px',
},
-
- mainTopBottomPadding: {
- xxs: '8px',
- mobile: '16px',
- tablet: '16px',
- desktop: '36px',
- },
} as const;
export default theme;
diff --git a/frontend/src/shared/types/theme.ts b/frontend/src/shared/types/theme.ts
index d761ce1f2..bd038daa8 100644
--- a/frontend/src/shared/types/theme.ts
+++ b/frontend/src/shared/types/theme.ts
@@ -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;