From 402e81333b4db2a99ebdd5b1777c5fee24cd22e1 Mon Sep 17 00:00:00 2001 From: MinSeok Kim Date: Mon, 2 Dec 2024 00:31:40 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20q-space=20style=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DetailsHeader/DetailsHead.styles.ts | 30 ++++++ .../DetailsHeader/DetailsHeader.tsx | 42 +++----- .../components/KebabMenu/KebabMenu.styles.ts | 56 +++++++++++ .../components/KebabMenu/KebabMenu.tsx | 63 ++---------- .../MemberContainer/MemberContainer.styles.ts | 59 ++++++++++++ .../MemberContainer/MemberContainer.tsx | 68 ++----------- .../MemberListButton.styles.ts | 23 +++++ .../MemberListButton/MemberListButton.tsx | 24 +---- src/pages/QSpaceDetail/index.tsx | 96 +++---------------- src/pages/QSpaceDetail/styles.ts | 72 ++++++++++++++ .../FloatingButton/FloatingButton.styles.ts | 60 ++++++++++++ .../FloatingButton/FloatingButton.tsx | 62 +----------- .../GroupStateCheckBox.styles.ts | 16 ++++ .../GroupStateCheckBox/GroupStateCheckBox.tsx | 20 +--- src/pages/QSpaceMain/index.tsx | 53 ++-------- src/pages/QSpaceMain/styles.ts | 44 +++++++++ .../QSpacePost/CategorySelectPage.styles.ts | 41 ++++++++ src/pages/QSpacePost/CategorySelectPage.tsx | 55 +++-------- src/pages/QSpacePost/PostGroupPage.styles.ts | 59 ++++++++++++ src/pages/QSpacePost/PostGroupPage.tsx | 89 ++++------------- 20 files changed, 552 insertions(+), 480 deletions(-) create mode 100644 src/pages/QSpaceDetail/components/DetailsHeader/DetailsHead.styles.ts create mode 100644 src/pages/QSpaceDetail/components/KebabMenu/KebabMenu.styles.ts create mode 100644 src/pages/QSpaceDetail/components/MemberContainer/MemberContainer.styles.ts create mode 100644 src/pages/QSpaceDetail/components/MemberListButton/MemberListButton.styles.ts create mode 100644 src/pages/QSpaceDetail/styles.ts create mode 100644 src/pages/QSpaceMain/components/FloatingButton/FloatingButton.styles.ts create mode 100644 src/pages/QSpaceMain/components/GroupStateCheckBox/GroupStateCheckBox.styles.ts create mode 100644 src/pages/QSpaceMain/styles.ts create mode 100644 src/pages/QSpacePost/CategorySelectPage.styles.ts create mode 100644 src/pages/QSpacePost/PostGroupPage.styles.ts diff --git a/src/pages/QSpaceDetail/components/DetailsHeader/DetailsHead.styles.ts b/src/pages/QSpaceDetail/components/DetailsHeader/DetailsHead.styles.ts new file mode 100644 index 0000000..3e4b621 --- /dev/null +++ b/src/pages/QSpaceDetail/components/DetailsHeader/DetailsHead.styles.ts @@ -0,0 +1,30 @@ +import theme from '@/styles/theme'; +import styled from '@emotion/styled'; + +export const Container = styled.div` + display: flex; + align-items: center; + gap: 0.75rem; + padding: 1rem; +`; + +export const TextContent = styled.div` + display: flex; + flex-direction: column; + gap: 0.25rem; +`; + +export const Title = styled.h2` + font-family: ${theme.typography.fontFamily.korean}; + font-size: ${theme.typography.body1.size}; + font-weight: ${theme.typography.weights.semiBold}; + color: ${theme.colors.black}; + margin: 0; +`; + +export const CreatorInfo = styled.p` + font-family: ${theme.typography.fontFamily.korean}; + font-size: ${theme.typography.body3.size}; + color: ${theme.colors.gray[400]}; + margin: 0; +`; diff --git a/src/pages/QSpaceDetail/components/DetailsHeader/DetailsHeader.tsx b/src/pages/QSpaceDetail/components/DetailsHeader/DetailsHeader.tsx index 0583e74..3168ff6 100644 --- a/src/pages/QSpaceDetail/components/DetailsHeader/DetailsHeader.tsx +++ b/src/pages/QSpaceDetail/components/DetailsHeader/DetailsHeader.tsx @@ -1,6 +1,11 @@ -import styled from '@emotion/styled'; import theme from '@/styles/theme'; import ProfileImage from '@/components/ui/ProfileImageCon/ProfileImageCon'; +import { + Container, + CreatorInfo, + TextContent, + Title, +} from '@/pages/QSpaceDetail/components/DetailsHeader/DetailsHead.styles'; interface DetailsHeaderProps { title: string; @@ -11,7 +16,12 @@ interface DetailsHeaderProps { const DetailsHeader = ({ title, creator, profileImage }: DetailsHeaderProps) => { return ( - + {title} {creator} @@ -20,32 +30,4 @@ const DetailsHeader = ({ title, creator, profileImage }: DetailsHeaderProps) => ); }; -const Container = styled.div` - display: flex; - align-items: center; - gap: 0.75rem; - padding: 1rem; -`; - -const TextContent = styled.div` - display: flex; - flex-direction: column; - gap: 0.25rem; -`; - -const Title = styled.h2` - font-family: ${theme.typography.fontFamily.korean}; - font-size: ${theme.typography.body1.size}; - font-weight: ${theme.typography.weights.semiBold}; - color: ${theme.colors.black}; - margin: 0; -`; - -const CreatorInfo = styled.p` - font-family: ${theme.typography.fontFamily.korean}; - font-size: ${theme.typography.body3.size}; - color: ${theme.colors.gray[400]}; - margin: 0; -`; - export default DetailsHeader; diff --git a/src/pages/QSpaceDetail/components/KebabMenu/KebabMenu.styles.ts b/src/pages/QSpaceDetail/components/KebabMenu/KebabMenu.styles.ts new file mode 100644 index 0000000..fa9be64 --- /dev/null +++ b/src/pages/QSpaceDetail/components/KebabMenu/KebabMenu.styles.ts @@ -0,0 +1,56 @@ +import theme from '@/styles/theme'; +import styled from '@emotion/styled'; + +export const Container = styled.div` + position: relative; + display: inline-block; +`; + +export const IconButton = styled.button` + background: none; + border: none; + padding: 0.5rem; + cursor: pointer; + color: ${theme.colors.gray[400]}; + display: flex; + align-items: center; + justify-content: center; + transition: color 0.2s ease-in-out; + + &:hover { + color: ${theme.colors.gray[600]}; + } +`; + +export const MenuPopup = styled.div` + position: absolute; + top: 100%; + right: 0; + min-width: 160px; + background-color: ${theme.colors.white}; + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + overflow: hidden; + z-index: 1000; +`; + +export const MenuItem = styled.button` + width: 100%; + padding: 0.75rem 1rem; + border: none; + background: none; + text-align: left; + font-family: ${theme.typography.fontFamily.korean}; + font-size: ${theme.typography.body2.size}; + color: ${theme.colors.gray[600]}; + cursor: pointer; + transition: background-color 0.2s ease-in-out; + + &:hover { + background-color: ${theme.colors.sub}; + } + + &:not(:last-child) { + border-bottom: 1px solid ${theme.colors.gray[100]}; + } +`; diff --git a/src/pages/QSpaceDetail/components/KebabMenu/KebabMenu.tsx b/src/pages/QSpaceDetail/components/KebabMenu/KebabMenu.tsx index 012f08e..4bc4293 100644 --- a/src/pages/QSpaceDetail/components/KebabMenu/KebabMenu.tsx +++ b/src/pages/QSpaceDetail/components/KebabMenu/KebabMenu.tsx @@ -1,8 +1,11 @@ +import { + Container, + IconButton, + MenuItem, + MenuPopup, +} from '@/pages/QSpaceDetail/components/KebabMenu/KebabMenu.styles'; import { useState, useRef, useEffect } from 'react'; -import styled from '@emotion/styled'; import { VscKebabVertical } from 'react-icons/vsc'; -import theme from '@/styles/theme'; - interface KebabMenuProps { onEditClick?: () => void; onDeleteClick?: () => void; @@ -63,58 +66,4 @@ const KebabMenu = ({ ); }; -const Container = styled.div` - position: relative; - display: inline-block; -`; - -const IconButton = styled.button` - background: none; - border: none; - padding: 0.5rem; - cursor: pointer; - color: ${theme.colors.gray[400]}; - display: flex; - align-items: center; - justify-content: center; - transition: color 0.2s ease-in-out; - - &:hover { - color: ${theme.colors.gray[600]}; - } -`; - -const MenuPopup = styled.div` - position: absolute; - top: 100%; - right: 0; - min-width: 160px; - background-color: ${theme.colors.white}; - border-radius: 8px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); - overflow: hidden; - z-index: 1000; -`; - -const MenuItem = styled.button` - width: 100%; - padding: 0.75rem 1rem; - border: none; - background: none; - text-align: left; - font-family: ${theme.typography.fontFamily.korean}; - font-size: ${theme.typography.body2.size}; - color: ${theme.colors.gray[600]}; - cursor: pointer; - transition: background-color 0.2s ease-in-out; - - &:hover { - background-color: ${theme.colors.sub}; - } - - &:not(:last-child) { - border-bottom: 1px solid ${theme.colors.gray[100]}; - } -`; - export default KebabMenu; diff --git a/src/pages/QSpaceDetail/components/MemberContainer/MemberContainer.styles.ts b/src/pages/QSpaceDetail/components/MemberContainer/MemberContainer.styles.ts new file mode 100644 index 0000000..31f1bd7 --- /dev/null +++ b/src/pages/QSpaceDetail/components/MemberContainer/MemberContainer.styles.ts @@ -0,0 +1,59 @@ +import styled from '@emotion/styled'; +import theme from '@/styles/theme'; + +export const Container = styled.div` + display: flex; + flex-direction: column; + padding: 1rem; + width: 100%; + gap: 1rem; + border-top: 1px solid ${theme.colors.gray[200]}; + background-color: ${theme.colors.background}; +`; + +export const TopSection = styled.div` + display: flex; + justify-content: space-between; +`; + +export const BottomSection = styled.div` + display: flex; + justify-content: space-between; +`; + +export const IconsWrapper = styled.div` + display: flex; + align-items: center; +`; + +export const IconContainer = styled.div<{ size: number; isStacked: boolean }>` + width: ${(props) => props.size}px; + height: ${(props) => props.size}px; + background-color: ${theme.colors.gray[200]}; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-left: ${(props) => (props.isStacked ? '-8px' : '0')}; + border: 2px solid ${theme.colors.white}; + color: ${theme.colors.gray[100]}; +`; + +export const Count = styled.div` + display: flex; + align-items: center; + gap: 0.25rem; + color: ${theme.colors.gray[400]}; + font-family: ${theme.typography.fontFamily.korean}; + font-size: ${theme.typography.body2.size}; + + svg { + color: ${theme.colors.gray[400]}; + } +`; + +export const LastChatTime = styled.span` + color: ${theme.colors.blue}; + font-size: ${theme.typography.body3.size}; + font-family: ${theme.typography.fontFamily.korean}; +`; diff --git a/src/pages/QSpaceDetail/components/MemberContainer/MemberContainer.tsx b/src/pages/QSpaceDetail/components/MemberContainer/MemberContainer.tsx index 6cf3bfb..87e220d 100644 --- a/src/pages/QSpaceDetail/components/MemberContainer/MemberContainer.tsx +++ b/src/pages/QSpaceDetail/components/MemberContainer/MemberContainer.tsx @@ -1,6 +1,13 @@ -import styled from '@emotion/styled'; import { IoPerson } from 'react-icons/io5'; -import theme from '@/styles/theme'; +import { + BottomSection, + Container, + Count, + IconContainer, + IconsWrapper, + LastChatTime, + TopSection, +} from '@/pages/QSpaceDetail/components/MemberContainer/MemberContainer.styles'; import MemberListButton from '@/pages/QSpaceDetail/components/MemberListButton/MemberListButton'; interface MemberContainerProps { @@ -57,61 +64,4 @@ const MemberContainer = ({ ); }; -const Container = styled.div` - display: flex; - flex-direction: column; - padding: 1rem; - width: 100%; - gap: 1rem; - border-top: 1px solid ${theme.colors.gray[200]}; - background-color: ${theme.colors.background}; -`; - -const TopSection = styled.div` - display: flex; - justify-content: space-between; -`; - -const BottomSection = styled.div` - display: flex; - justify-content: space-between; -`; - -const IconsWrapper = styled.div` - display: flex; - align-items: center; -`; - -const IconContainer = styled.div<{ size: number; isStacked: boolean }>` - width: ${(props) => props.size}px; - height: ${(props) => props.size}px; - background-color: ${theme.colors.gray[200]}; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - margin-left: ${(props) => (props.isStacked ? '-8px' : '0')}; - border: 2px solid ${theme.colors.white}; - color: ${theme.colors.gray[100]}; -`; - -const Count = styled.div` - display: flex; - align-items: center; - gap: 0.25rem; - color: ${theme.colors.gray[400]}; - font-family: ${theme.typography.fontFamily.korean}; - font-size: ${theme.typography.body2.size}; - - svg { - color: ${theme.colors.gray[400]}; - } -`; - -const LastChatTime = styled.span` - color: ${theme.colors.blue}; - font-size: ${theme.typography.body3.size}; - font-family: ${theme.typography.fontFamily.korean}; -`; - export default MemberContainer; diff --git a/src/pages/QSpaceDetail/components/MemberListButton/MemberListButton.styles.ts b/src/pages/QSpaceDetail/components/MemberListButton/MemberListButton.styles.ts new file mode 100644 index 0000000..e494ab2 --- /dev/null +++ b/src/pages/QSpaceDetail/components/MemberListButton/MemberListButton.styles.ts @@ -0,0 +1,23 @@ +import styled from '@emotion/styled'; +import theme from '@/styles/theme'; + +export const Button = styled.button` + background-color: ${theme.colors.sub}; + color: ${theme.colors.gray[500]}; + border: none; + border-radius: 6rem; + padding: 0.5rem 0.75rem; + font-family: ${theme.typography.fontFamily.korean}; + font-size: ${theme.typography.body2.size}; + font-weight: ${theme.typography.weights.medium}; + cursor: pointer; + transition: all 0.2s ease-in-out; + + &:hover { + background-color: ${theme.colors.gray[100]}; + } + + &:active { + transform: scale(0.98); + } +`; diff --git a/src/pages/QSpaceDetail/components/MemberListButton/MemberListButton.tsx b/src/pages/QSpaceDetail/components/MemberListButton/MemberListButton.tsx index 8d558a6..95458ae 100644 --- a/src/pages/QSpaceDetail/components/MemberListButton/MemberListButton.tsx +++ b/src/pages/QSpaceDetail/components/MemberListButton/MemberListButton.tsx @@ -1,5 +1,4 @@ -import styled from '@emotion/styled'; -import theme from '@/styles/theme'; +import { Button } from '@/pages/QSpaceDetail/components/MemberListButton/MemberListButton.styles'; interface MemberListButtonProps { onClick?: () => void; @@ -14,25 +13,4 @@ const MemberListButton = ({ onClick, className }: MemberListButtonProps) => { ); }; -const Button = styled.button` - background-color: ${theme.colors.sub}; - color: ${theme.colors.gray[500]}; - border: none; - border-radius: 6rem; - padding: 0.5rem 0.75rem; - font-family: ${theme.typography.fontFamily.korean}; - font-size: ${theme.typography.body2.size}; - font-weight: ${theme.typography.weights.medium}; - cursor: pointer; - transition: all 0.2s ease-in-out; - - &:hover { - background-color: ${theme.colors.gray[100]}; - } - - &:active { - transform: scale(0.98); - } -`; - export default MemberListButton; diff --git a/src/pages/QSpaceDetail/index.tsx b/src/pages/QSpaceDetail/index.tsx index 58da497..174e253 100644 --- a/src/pages/QSpaceDetail/index.tsx +++ b/src/pages/QSpaceDetail/index.tsx @@ -6,8 +6,21 @@ import ChatInputBar from '@/pages/ChatRoom/component/InputBar'; import DetailsHeader from '@/pages/QSpaceDetail/components/DetailsHeader/DetailsHeader'; import KebabMenu from '@/pages/QSpaceDetail/components/KebabMenu/KebabMenu'; import MemberContainer from '@/pages/QSpaceDetail/components/MemberContainer/MemberContainer'; +import { + ChatInputWrapper, + CommentArea, + Container, + Content, + ContentArea, + DiscussionImage, + HeaderWrapper, + ImageContainer, + KebabMenuWrapper, + MainContent, + NavigationBar, + TagWrapper, +} from '@/pages/QSpaceDetail/styles'; import theme from '@/styles/theme'; -import styled from '@emotion/styled'; const QSpaceDetailPage = () => { const { isCreator, discussion, comments } = mockDiscussionData; @@ -81,85 +94,4 @@ const QSpaceDetailPage = () => { ); }; -const Container = styled.div` - display: flex; - flex-direction: column; - min-height: calc(100vh - 6rem); - background-color: ${theme.colors.background}; - position: relative; -`; - -const MainContent = styled.div` - flex: 1; - overflow-y: auto; - padding-bottom: 4rem; /* ChatInputWrapper 높이만큼 여백 추가 */ -`; - -const NavigationBar = styled.div` - padding: 0.5rem 1rem; - display: flex; - align-items: center; - border-bottom: 1px solid ${theme.colors.gray[100]}; -`; - -const HeaderWrapper = styled.div` - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 1px solid ${theme.colors.gray[100]}; -`; - -const KebabMenuWrapper = styled.div` - padding-right: 1rem; -`; - -const ImageContainer = styled.div` - width: 80%; - height: 320px; - background-color: ${theme.colors.gray[100]}; - overflow: hidden; - border-radius: 1rem; - margin: 0 auto; - margin-bottom: 1rem; -`; - -const DiscussionImage = styled.img` - width: 100%; - height: 100%; - object-fit: cover; -`; - -const ContentArea = styled.div` - padding: 1rem; -`; - -const Content = styled.div` - font-size: ${theme.typography.body2.size}; - color: ${theme.colors.black}; - white-space: pre-wrap; - margin-bottom: 1rem; -`; - -const TagWrapper = styled.div` - margin-top: 0.5rem; -`; - -const CommentArea = styled.div` - padding: 0.5rem; - background-color: ${theme.colors.white80}; - padding-bottom: calc(5rem + 12px); -`; - -const ChatInputWrapper = styled.div` - position: fixed; - bottom: 5rem; /* footer 높이만큼 위로 */ - left: 0; - right: 0; - background-color: ${theme.colors.white80}; - padding: 0.5rem; - max-width: 430px; - margin: 0 auto; - z-index: 10; -`; - export default QSpaceDetailPage; diff --git a/src/pages/QSpaceDetail/styles.ts b/src/pages/QSpaceDetail/styles.ts new file mode 100644 index 0000000..137d86c --- /dev/null +++ b/src/pages/QSpaceDetail/styles.ts @@ -0,0 +1,72 @@ +import theme from '@/styles/theme'; +import styled from '@emotion/styled'; + +export const Container = styled.div` + display: flex; + flex-direction: column; + min-height: calc(100vh - 6rem); + background-color: ${theme.colors.background}; + position: relative; +`; +export const MainContent = styled.div` + flex: 1; + overflow-y: auto; + padding-bottom: 4rem; /* ChatInputWrapper 높이만큼 여백 추가 */ +`; +export const NavigationBar = styled.div` + padding: 0.5rem 1rem; + display: flex; + align-items: center; + border-bottom: 1px solid ${theme.colors.gray[100]}; +`; +export const HeaderWrapper = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid ${theme.colors.gray[100]}; +`; +export const KebabMenuWrapper = styled.div` + padding-right: 1rem; +`; +export const ImageContainer = styled.div` + width: 80%; + height: 320px; + background-color: ${theme.colors.gray[100]}; + overflow: hidden; + border-radius: 1rem; + margin: 0 auto; + margin-bottom: 1rem; +`; +export const DiscussionImage = styled.img` + width: 100%; + height: 100%; + object-fit: cover; +`; +export const ContentArea = styled.div` + padding: 1rem; +`; +export const Content = styled.div` + font-size: ${theme.typography.body2.size}; + color: ${theme.colors.black}; + white-space: pre-wrap; + margin-bottom: 1rem; +`; +export const TagWrapper = styled.div` + margin-top: 0.5rem; +`; +export const CommentArea = styled.div` + padding: 0.5rem; + background-color: ${theme.colors.white80}; + padding-bottom: calc(5rem + 12px); +`; +export const ChatInputWrapper = styled.div` + position: fixed; + bottom: 5rem; /* footer 높이만큼 위로 */ + left: 0; + right: 0; + background-color: ${theme.colors.white80}; + padding: 0.5rem; + max-width: 430px; + margin: 0 auto; + z-index: 10; +`; diff --git a/src/pages/QSpaceMain/components/FloatingButton/FloatingButton.styles.ts b/src/pages/QSpaceMain/components/FloatingButton/FloatingButton.styles.ts new file mode 100644 index 0000000..2e2bc16 --- /dev/null +++ b/src/pages/QSpaceMain/components/FloatingButton/FloatingButton.styles.ts @@ -0,0 +1,60 @@ +import styled from '@emotion/styled'; +import theme from '@/styles/theme'; + +export const StyledButton = styled.button` + width: 2.5rem; + height: 2.5rem; + border-radius: 50%; + background-color: ${theme.colors.primary}; + border: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + position: fixed; + right: 1.5rem; + bottom: 6.75rem; + box-shadow: + 0 4px 8px rgba(157, 111, 112, 0.2), + 0 2px 4px rgba(157, 111, 112, 0.1); + transition: all 0.2s ease-in-out; + + @media (min-width: 430px) { + right: calc(50% - 215px + 1.5rem); + } + + &:hover { + transform: translateY(-2px); + box-shadow: + 0 6px 12px rgba(157, 111, 112, 0.2), + 0 4px 6px rgba(157, 111, 112, 0.1); + } +`; + +export const PlusIcon = styled.div` + width: 1rem; + height: 1rem; + position: relative; + + &:before, + &:after { + content: ''; + position: absolute; + background-color: ${theme.colors.white}; + border-radius: 2px; + } + + &:before { + width: 16px; + height: 2px; + top: 7px; + left: 0; + } + + &:after { + width: 2px; + height: 16px; + left: 7px; + top: 0; + } +`; diff --git a/src/pages/QSpaceMain/components/FloatingButton/FloatingButton.tsx b/src/pages/QSpaceMain/components/FloatingButton/FloatingButton.tsx index dcb85b7..1543cbf 100644 --- a/src/pages/QSpaceMain/components/FloatingButton/FloatingButton.tsx +++ b/src/pages/QSpaceMain/components/FloatingButton/FloatingButton.tsx @@ -1,6 +1,8 @@ +import { + PlusIcon, + StyledButton, +} from '@/pages/QSpaceMain/components/FloatingButton/FloatingButton.styles'; import { useNavigate } from 'react-router-dom'; -import styled from '@emotion/styled'; -import theme from '@/styles/theme'; interface FloatingButtonProps { onClick?: () => void; @@ -15,64 +17,10 @@ const FloatingButton = ({ className }: FloatingButtonProps) => { }; return ( - + ); }; export default FloatingButton; - -const StyledButton = styled.button` - width: 2.5rem; - height: 2.5rem; - border-radius: 50%; - background-color: ${theme.colors.primary}; - border: none; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - position: fixed; - right: 1.5rem; - bottom: 6.75rem; - box-shadow: 0 4px 8px rgba(157, 111, 112, 0.2), 0 2px 4px rgba(157, 111, 112, 0.1); - transition: all 0.2s ease-in-out; - - @media (min-width: 430px) { - right: calc(50% - 215px + 1.5rem); - } - - &:hover { - transform: translateY(-2px); - box-shadow: 0 6px 12px rgba(157, 111, 112, 0.2), 0 4px 6px rgba(157, 111, 112, 0.1); - } -`; - -const PlusIcon = styled.div` - width: 1rem; - height: 1rem; - position: relative; - - &:before, - &:after { - content: ''; - position: absolute; - background-color: ${theme.colors.white}; - border-radius: 2px; - } - - &:before { - width: 16px; - height: 2px; - top: 7px; - left: 0; - } - - &:after { - width: 2px; - height: 16px; - left: 7px; - top: 0; - } -`; diff --git a/src/pages/QSpaceMain/components/GroupStateCheckBox/GroupStateCheckBox.styles.ts b/src/pages/QSpaceMain/components/GroupStateCheckBox/GroupStateCheckBox.styles.ts new file mode 100644 index 0000000..1e9bc56 --- /dev/null +++ b/src/pages/QSpaceMain/components/GroupStateCheckBox/GroupStateCheckBox.styles.ts @@ -0,0 +1,16 @@ +import styled from '@emotion/styled'; +import theme from '@/styles/theme'; + +export const StyledContainer = styled.div` + display: flex; + align-items: center; + gap: 0.5rem; +`; + +export const StyledTitle = styled.span` + color: ${theme.colors.gray[400]}; + font-family: ${theme.typography.body2.fontFamily}; + font-size: ${theme.typography.body2.size}; + font-weight: ${theme.typography.body2.weight}; + line-height: ${theme.typography.body2.lineHeight}; +`; diff --git a/src/pages/QSpaceMain/components/GroupStateCheckBox/GroupStateCheckBox.tsx b/src/pages/QSpaceMain/components/GroupStateCheckBox/GroupStateCheckBox.tsx index 1a0fd81..19da6ee 100644 --- a/src/pages/QSpaceMain/components/GroupStateCheckBox/GroupStateCheckBox.tsx +++ b/src/pages/QSpaceMain/components/GroupStateCheckBox/GroupStateCheckBox.tsx @@ -1,7 +1,9 @@ import { Checkbox } from '@chakra-ui/react'; -import styled from '@emotion/styled'; import theme from '@/styles/theme'; - +import { + StyledContainer, + StyledTitle, +} from '@/pages/QSpaceMain/components/GroupStateCheckBox/GroupStateCheckBox.styles'; interface GroupStateCheckBoxProps { initialChecked?: boolean; onChange?: (isChecked: boolean) => void; @@ -43,17 +45,3 @@ const GroupStateCheckBox = ({ initialChecked = false, onChange }: GroupStateChec }; export default GroupStateCheckBox; - -const StyledContainer = styled.div` - display: flex; - align-items: center; - gap: 0.5rem; -`; - -const StyledTitle = styled.span` - color: ${theme.colors.gray[400]}; - font-family: ${theme.typography.body2.fontFamily}; - font-size: ${theme.typography.body2.size}; - font-weight: ${theme.typography.body2.weight}; - line-height: ${theme.typography.body2.lineHeight}; -`; diff --git a/src/pages/QSpaceMain/index.tsx b/src/pages/QSpaceMain/index.tsx index 0e48d76..39e3aae 100644 --- a/src/pages/QSpaceMain/index.tsx +++ b/src/pages/QSpaceMain/index.tsx @@ -1,11 +1,18 @@ import { useState } from 'react'; -import styled from '@emotion/styled'; -import theme from '@/styles/theme'; import GroupStateCheckBox from '@/pages/QSpaceMain/components/GroupStateCheckBox/GroupStateCheckBox'; import FloatingButton from '@/pages/QSpaceMain/components/FloatingButton/FloatingButton'; import CategoryButton from '@/components/ui/CategoryButtons/CategoryButton'; import Header from '@/components/common/Header'; import QSpaceCard from '@/components/ui/QSpaceCard/QSpaceCard'; +import { + Body, + CategoryList, + CategorySection, + Container, + FilterSection, + QSpaceList, + Title, +} from '@/pages/QSpaceMain/styles'; const categories = ['전체', '여행', '스포츠', '패션', '문화', '맛집', '기타']; @@ -89,46 +96,4 @@ const QSpaceMainPage = () => { ); }; -const Container = styled.div` - margin: 0 auto; -`; - -const Body = styled.div` - padding: 0 1rem; - background-color: ${theme.colors.background}; - height: 100vh; -`; - -const CategorySection = styled.div` - padding: 1rem 0; - overflow-x: auto; - white-space: nowrap; -`; - -const CategoryList = styled.div` - display: flex; - gap: 0.5rem; - padding: 0 1rem; -`; - -const FilterSection = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - padding: 0; -`; - -const Title = styled.h2` - font-size: 1.25rem; - font-weight: bold; - margin: 1rem 0; - color: ${theme.colors.black}; -`; - -const QSpaceList = styled.div` - display: flex; - flex-direction: column; - gap: 1rem; -`; - export default QSpaceMainPage; diff --git a/src/pages/QSpaceMain/styles.ts b/src/pages/QSpaceMain/styles.ts new file mode 100644 index 0000000..7ec870f --- /dev/null +++ b/src/pages/QSpaceMain/styles.ts @@ -0,0 +1,44 @@ +import theme from '@/styles/theme'; +import styled from '@emotion/styled'; + +export const Container = styled.div` + margin: 0 auto; +`; + +export const Body = styled.div` + padding: 0 1rem; + background-color: ${theme.colors.background}; + height: 100vh; +`; + +export const CategorySection = styled.div` + padding: 1rem 0; + overflow-x: auto; + white-space: nowrap; +`; + +export const CategoryList = styled.div` + display: flex; + gap: 0.5rem; + padding: 0 1rem; +`; + +export const FilterSection = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + padding: 0; +`; + +export const Title = styled.h2` + font-size: 1.25rem; + font-weight: bold; + margin: 1rem 0; + color: ${theme.colors.black}; +`; + +export const QSpaceList = styled.div` + display: flex; + flex-direction: column; + gap: 1rem; +`; diff --git a/src/pages/QSpacePost/CategorySelectPage.styles.ts b/src/pages/QSpacePost/CategorySelectPage.styles.ts new file mode 100644 index 0000000..adde5a8 --- /dev/null +++ b/src/pages/QSpacePost/CategorySelectPage.styles.ts @@ -0,0 +1,41 @@ +import theme from '@/styles/theme'; +import styled from '@emotion/styled'; + +export const Container = styled.div` + display: flex; + flex-direction: column; + min-height: calc(100vh - 56px); // footer height 제외 + max-width: 430px; + margin: 0 auto; + background-color: ${theme.colors.background}; + position: relative; +`; + +export const HeaderSection = styled.header` + padding: 1rem; + position: sticky; + top: 0; + z-index: 10; + background-color: ${theme.colors.background}; +`; + +export const ContentSection = styled.main` + flex: 1; + display: flex; + flex-direction: column; + padding: 1rem; + margin-top: 2rem; +`; + +export const ButtonSection = styled.div` + padding: 1rem; + margin-bottom: 2rem; +`; + +export const Title = styled.h1` + text-align: center; + font-size: 1.125rem; + font-weight: 600; + margin: 1rem 0 5rem; + color: ${theme.colors.black}; +`; diff --git a/src/pages/QSpacePost/CategorySelectPage.tsx b/src/pages/QSpacePost/CategorySelectPage.tsx index 538f35e..6597367 100644 --- a/src/pages/QSpacePost/CategorySelectPage.tsx +++ b/src/pages/QSpacePost/CategorySelectPage.tsx @@ -1,8 +1,14 @@ import BackButton from '@/components/ui/BackButton/BackButton'; import CategorySelectContainer from '@/components/ui/CategorySelectContainer/CategorySelectContainer'; +import { + ButtonSection, + Container, + ContentSection, + HeaderSection, + Title, +} from '@/pages/QSpacePost/CategorySelectPage.styles'; import theme from '@/styles/theme'; import { Button } from '@chakra-ui/react'; -import styled from '@emotion/styled'; import { useState } from 'react'; const CategorySelectPage = () => { @@ -32,14 +38,14 @@ const CategorySelectPage = () => { @@ -48,43 +54,4 @@ const CategorySelectPage = () => { ); }; -const Container = styled.div` - display: flex; - flex-direction: column; - min-height: calc(100vh - 56px); // footer height 제외 - max-width: 430px; - margin: 0 auto; - background-color: ${theme.colors.background}; - position: relative; -`; - -const HeaderSection = styled.header` - padding: 1rem; - position: sticky; - top: 0; - z-index: 10; - background-color: ${theme.colors.background}; -`; - -const ContentSection = styled.main` - flex: 1; - display: flex; - flex-direction: column; - padding: 1rem; - margin-top: 2rem; -`; - -const ButtonSection = styled.div` - padding: 1rem; - margin-bottom: 2rem; -`; - -const Title = styled.h1` - text-align: center; - font-size: 1.125rem; - font-weight: 600; - margin: 1rem 0 5rem; - color: ${theme.colors.black}; -`; - export default CategorySelectPage; diff --git a/src/pages/QSpacePost/PostGroupPage.styles.ts b/src/pages/QSpacePost/PostGroupPage.styles.ts new file mode 100644 index 0000000..e778626 --- /dev/null +++ b/src/pages/QSpacePost/PostGroupPage.styles.ts @@ -0,0 +1,59 @@ +import theme from '@/styles/theme'; +import { Button } from '@chakra-ui/react'; +import styled from '@emotion/styled'; + +export const Container = styled.div` + background-color: ${theme.colors.background}; + min-height: calc(100vh - 5rem); // Footer 높이 5rem 제외 + padding-bottom: 5rem; // Footer 높이만큼 padding +`; + +export const Header = styled.header` + padding: 1rem; + display: flex; + align-items: center; +`; + +export const Content = styled.main` + padding: 0 1.5rem; + display: flex; + flex-direction: column; + gap: 3rem; + margin-top: 2rem; +`; + +export const InputWrapper = styled.div` + display: flex; + flex-direction: column; + gap: 0.5rem; + position: relative; +`; + +export const Label = styled.label` + color: ${theme.colors.black}; + font-size: ${theme.typography.body1.size}; + font-weight: ${theme.typography.weights.medium}; +`; + +export const CharCount = styled.span` + position: absolute; + right: 0.5rem; + bottom: -1.5rem; + font-size: ${theme.typography.body3.size}; + color: ${theme.colors.gray[400]}; +`; + +export const ButtonWrapper = styled.div` + position: fixed; + bottom: 5rem; // Footer 높이만큼 띄우기 + left: 1rem; + right: 1rem; + padding: 1rem 0; + background-color: ${theme.colors.background}; +`; + +export const CreateButton = styled(Button)` + width: 100%; + margin-bottom: 1rem; + border-radius: 1rem; +`; diff --git a/src/pages/QSpacePost/PostGroupPage.tsx b/src/pages/QSpacePost/PostGroupPage.tsx index 880bc7a..22d5bf6 100644 --- a/src/pages/QSpacePost/PostGroupPage.tsx +++ b/src/pages/QSpacePost/PostGroupPage.tsx @@ -1,9 +1,18 @@ import { useState } from 'react'; -import styled from '@emotion/styled'; -import { Input, Button, Textarea } from '@chakra-ui/react'; +import { Input, Textarea } from '@chakra-ui/react'; import theme from '@/styles/theme'; import BackButton from '@/components/ui/BackButton/BackButton'; import { ImageUpload } from '@/components/ui/ImageUpload/ImageUpload'; +import { + ButtonWrapper, + CharCount, + Container, + Content, + CreateButton, + Header, + InputWrapper, + Label, +} from '@/pages/QSpacePost/PostGroupPage.styles'; const PostGroupPage = () => { const [title, setTitle] = useState(''); @@ -31,10 +40,10 @@ const PostGroupPage = () => { value={title} onChange={(e) => setTitle(e.target.value)} height={14} - border='none' + border="none" borderRadius={12} maxLength={24} - bg='white' + bg="white" /> {title.length}/24 @@ -45,11 +54,11 @@ const PostGroupPage = () => { value={description} onChange={(e) => setDescription(e.target.value)} maxLength={300} - height='10rem' - border='none' + height="10rem" + border="none" borderRadius={12} - bg='white' - resize='none' + bg="white" + resize="none" /> {description.length}/300 @@ -61,11 +70,11 @@ const PostGroupPage = () => { 방 만들기 @@ -76,60 +85,4 @@ const PostGroupPage = () => { ); }; -const Container = styled.div` - background-color: ${theme.colors.background}; - min-height: calc(100vh - 5rem); // Footer 높이 5rem 제외 - padding-bottom: 5rem; // Footer 높이만큼 padding -`; - -const Header = styled.header` - padding: 1rem; - display: flex; - align-items: center; -`; - -const Content = styled.main` - padding: 0 1.5rem; - display: flex; - flex-direction: column; - gap: 3rem; - margin-top: 2rem; -`; - -const InputWrapper = styled.div` - display: flex; - flex-direction: column; - gap: 0.5rem; - position: relative; -`; - -const Label = styled.label` - color: ${theme.colors.black}; - font-size: ${theme.typography.body1.size}; - font-weight: ${theme.typography.weights.medium}; -`; - -const CharCount = styled.span` - position: absolute; - right: 0.5rem; - bottom: -1.5rem; - font-size: ${theme.typography.body3.size}; - color: ${theme.colors.gray[400]}; -`; - -const ButtonWrapper = styled.div` - position: fixed; - bottom: 5rem; // Footer 높이만큼 띄우기 - left: 1rem; - right: 1rem; - padding: 1rem 0; - background-color: ${theme.colors.background}; -`; - -const CreateButton = styled(Button)` - width: 100%; - margin-bottom: 1rem; - border-radius: 1rem; -`; - export default PostGroupPage;