From f30c9a0732063225043aff4477c05b9a4f1b7682 Mon Sep 17 00:00:00 2001 From: leejiho9898 <84016039+leejiho9898@users.noreply.github.com> Date: Mon, 13 Feb 2023 03:43:46 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[CZ-372]=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=ED=83=80=EC=9D=B4=ED=8B=80=20=ED=8C=8C=ED=8A=B8=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20QA=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 선택지를 입력해주세요 padding-bottom 수정 * fix: subText 폰트 컬러 변경 * fix: 문구와 이미지 간격 조절 --- apps/web/components/post/ImageTitleSection.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/web/components/post/ImageTitleSection.tsx b/apps/web/components/post/ImageTitleSection.tsx index 3bf63717..ddf62923 100644 --- a/apps/web/components/post/ImageTitleSection.tsx +++ b/apps/web/components/post/ImageTitleSection.tsx @@ -117,12 +117,12 @@ const Container = styled.div` const QuestionText = styled.div` font-size: 20px; font-weight: 700; - padding-bottom: 4px; + padding-bottom: 8px; `; const SubText = styled.div` font-size: 16px; - color: ${({ theme }) => theme.palette.border.dark}; + color: ${({ theme }) => theme.palette.ink.base}; `; const InvisibleInput = styled.input` @@ -132,7 +132,7 @@ const InvisibleInput = styled.input` const ImageWrapper = styled.div` gap: 12px; overflow: hidden; - margin-top: 32px; + margin-top: 16px; width: 100%; background: ${({ theme }) => theme.palette.background.hard}; border-radius: 8px; From a273407cd41451487b13877ef3bd926a30ec3611 Mon Sep 17 00:00:00 2001 From: Leejha <57664427+Leejha@users.noreply.github.com> Date: Tue, 14 Feb 2023 03:25:24 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[CZ-366]=20=20select=20component=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: select 컴포넌트를 위한 훅 추가 * feat: select 컴포넌트 구현 * feat: category select box 추가 * feat: 투표 리스트 페이지에 category select box 추가 --- apps/web/app/voteList/page.tsx | 36 +++++++----------- .../common/select/CategorySelect.tsx | 31 ++++++++++++++++ apps/web/components/common/select/Option.tsx | 23 ++++++++++++ .../components/common/select/OptionList.tsx | 27 ++++++++++++++ .../components/common/select/SelectButton.tsx | 37 +++++++++++++++++++ apps/web/components/common/select/index.ts | 1 + apps/web/hooks/useSelect.ts | 13 +++++++ apps/web/lib/constants.ts | 2 +- apps/web/public/icons/FilterIcon.svg | 3 -- apps/web/public/icons/SelectBoxIcon.svg | 3 ++ apps/web/public/icons/index.ts | 6 +-- 11 files changed, 153 insertions(+), 29 deletions(-) create mode 100644 apps/web/components/common/select/CategorySelect.tsx create mode 100644 apps/web/components/common/select/Option.tsx create mode 100644 apps/web/components/common/select/OptionList.tsx create mode 100644 apps/web/components/common/select/SelectButton.tsx create mode 100644 apps/web/components/common/select/index.ts create mode 100644 apps/web/hooks/useSelect.ts delete mode 100644 apps/web/public/icons/FilterIcon.svg create mode 100644 apps/web/public/icons/SelectBoxIcon.svg diff --git a/apps/web/app/voteList/page.tsx b/apps/web/app/voteList/page.tsx index f2890605..d0f0a113 100644 --- a/apps/web/app/voteList/page.tsx +++ b/apps/web/app/voteList/page.tsx @@ -1,33 +1,31 @@ "use client"; +import { CategorySelect } from "components/common/select"; import { VoteList } from "components/voteList"; -import { CATEGORY_LIST } from "lib/constants"; -import { FilterIcon } from "public/icons"; +import { useState } from "react"; import useInfiniteVoteListService from "services/useInfiniteVoteListService"; import styled from "styled-components"; import { media } from "styles/media"; +import { CategoryNameType } from "types/vote"; function VoteListPage() { const { voteList, subscribe } = useInfiniteVoteListService({ size: 3, sortBy: "ByTime", }); + const [selectedCategory, setSelectedCategory] = useState(); + const onChangeCategory = (e: React.ChangeEvent) => { + setSelectedCategory(e.target.value as CategoryNameType); + }; + console.log(voteList); return ( - - - {CATEGORY_LIST.map(({ id, name }) => ( - - ))} - - - - 필터 - - - + + + +
@@ -49,15 +47,9 @@ const PageInner = styled.div` } `; -const FilterContainer = styled.div` - display: flex; - justify-content: space-between; -`; - -const CategorySelect = styled.select``; -const Option = styled.option``; -const FilterBox = styled.div` +const FilterSection = styled.section` display: flex; + flex-direction: column; `; export default VoteListPage; diff --git a/apps/web/components/common/select/CategorySelect.tsx b/apps/web/components/common/select/CategorySelect.tsx new file mode 100644 index 00000000..d4da3f83 --- /dev/null +++ b/apps/web/components/common/select/CategorySelect.tsx @@ -0,0 +1,31 @@ +import useOutSideClick from "hooks/useOutsideClick"; +import { PropsWithChildren } from "react"; +import Option from "./Option"; +import { OptionList } from "./OptionList"; +import SelectButton from "./SelectButton"; +import useSelect from "hooks/useSelect"; +import { CATEGORY_LIST } from "lib/constants"; +import styled from "styled-components"; + +// @todo 추후 context api로 변경 +// @todo 재사용 가능한 컴포넌트로 만들기 +function CategorySelect({ children }: PropsWithChildren) { + const { isOpen, onChangeOpen, option, onChangeOption } = useSelect("전체"); + const { targetEl } = useOutSideClick(isOpen, onChangeOpen); + return ( + + {option} + {isOpen ? ( + + {CATEGORY_LIST.map( + ({ name }) => option !== name && + ) : null} + + ); +} + +const SelectBox = styled.div``; + +export default CategorySelect; diff --git a/apps/web/components/common/select/Option.tsx b/apps/web/components/common/select/Option.tsx new file mode 100644 index 00000000..d7c5ec5e --- /dev/null +++ b/apps/web/components/common/select/Option.tsx @@ -0,0 +1,23 @@ +import styled from "styled-components"; + +interface OptionProps { + name: string; + onChangeOption: (value: string) => void; +} + +function Option({ name, onChangeOption }: OptionProps) { + return ( +
  • onChangeOption(name)}> + {name} +
  • + ); +} + +const Li = styled.li` + display: flex; + flex-direction: row; + margin-bottom: 24px; + ${({ theme }) => theme.textStyle.Title_Small}; +`; + +export default Option; diff --git a/apps/web/components/common/select/OptionList.tsx b/apps/web/components/common/select/OptionList.tsx new file mode 100644 index 00000000..df890c58 --- /dev/null +++ b/apps/web/components/common/select/OptionList.tsx @@ -0,0 +1,27 @@ +import { Portal, transitions } from "@chooz/ui"; +import styled from "styled-components"; + +interface OptionListProps { + children: React.ReactNode; +} + +export function OptionList({ children }: OptionListProps) { + return ( +
      + {children} +
    + ); +} + +const Ul = styled.ul` + position: absolute; + width: 136px; + height: 246px; + margin-top: 8px; + padding: 20px 0 0 20px; + border-radius: 8px; + box-shadow: 0 0 40px 0 rgba(0, 0, 0, 0.1); + border: solid 1px var(--invalid-name); + z-index: 99; + background-color: ${({ theme }) => theme.palette.background.white}; +`; diff --git a/apps/web/components/common/select/SelectButton.tsx b/apps/web/components/common/select/SelectButton.tsx new file mode 100644 index 00000000..72d5f480 --- /dev/null +++ b/apps/web/components/common/select/SelectButton.tsx @@ -0,0 +1,37 @@ +import { SelectBoxIcon } from "public/icons"; +import styled from "styled-components"; + +interface SelectProps { + children: React.ReactNode; + onChangeOpen: () => void; +} + +function SelectButton({ children, onChangeOpen }: SelectProps) { + return ( + <> + + {children} + + + + ); +} + +const StyledButton = styled.button` + display: flex; + flex-direction: row; + align-items: center; + + > span { + margin-right: 18px; + } +`; + +export default SelectButton; diff --git a/apps/web/components/common/select/index.ts b/apps/web/components/common/select/index.ts new file mode 100644 index 00000000..0d709c3b --- /dev/null +++ b/apps/web/components/common/select/index.ts @@ -0,0 +1 @@ +export { default as CategorySelect } from "./CategorySelect"; diff --git a/apps/web/hooks/useSelect.ts b/apps/web/hooks/useSelect.ts new file mode 100644 index 00000000..43665230 --- /dev/null +++ b/apps/web/hooks/useSelect.ts @@ -0,0 +1,13 @@ +import { useState } from "react"; +import useToggle from "./useToggle"; + +export default function useSelect(defaultOption: string) { + const [isOpen, onChangeOpen] = useToggle(); + const [option, setOption] = useState(defaultOption); + const onChangeOption = (value: string) => { + setOption(value); + onChangeOpen(); + }; + + return { isOpen, onChangeOpen, option, onChangeOption }; +} diff --git a/apps/web/lib/constants.ts b/apps/web/lib/constants.ts index 90dcad03..87597499 100644 --- a/apps/web/lib/constants.ts +++ b/apps/web/lib/constants.ts @@ -16,12 +16,12 @@ export const NAVER_LOGIN_REDIRECT_URL = // export const CATEGORY_NAMES = ["음식", "직업", "연애", "패션", "재미", "기타"]; export const CATEGORY_LIST = [ + { id: "NULL", name: "전체" }, { id: "FOODS", name: "음식" }, { id: "CAREER", name: "직업" }, { id: "LOVE", name: "연애" }, { id: "FASHION", name: "패션" }, { id: "INTEREST", name: "재미" }, - { id: "NULL", name: "기타" }, ]; export const AGE_LIST = [ diff --git a/apps/web/public/icons/FilterIcon.svg b/apps/web/public/icons/FilterIcon.svg deleted file mode 100644 index 1460bb77..00000000 --- a/apps/web/public/icons/FilterIcon.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/web/public/icons/SelectBoxIcon.svg b/apps/web/public/icons/SelectBoxIcon.svg new file mode 100644 index 00000000..336d5154 --- /dev/null +++ b/apps/web/public/icons/SelectBoxIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/web/public/icons/index.ts b/apps/web/public/icons/index.ts index 541432f7..0556df84 100644 --- a/apps/web/public/icons/index.ts +++ b/apps/web/public/icons/index.ts @@ -1,10 +1,10 @@ export { default as WarningIcon } from "./WarningIcon.svg"; -export { default as SaveIcon } from "./saveIcon.png"; export { default as HambergerIcon } from "./hambergerIcon.png"; -export { default as AddIcon } from "./addIcon.png"; export { default as KakaoIcon } from "./KakaoIcon.svg"; export { default as NaverIcon } from "./NaverIcon.svg"; -export { default as FilterIcon } from "./FilterIcon.svg"; export { default as BookmarkIcon } from "./BookmarkIcon.svg"; +export { default as SelectBoxIcon } from "./SelectBoxIcon.svg"; export { default as AmplifyIcon } from "./amplifyIcon.png"; +export { default as AddIcon } from "./addIcon.png"; +export { default as SaveIcon } from "./saveIcon.png"; export { default as Reduction } from "./Reduction.png"; From c0516ffdd2bd14f75e57e38becad75b9aaeb1c44 Mon Sep 17 00:00:00 2001 From: Leejha <57664427+Leejha@users.noreply.github.com> Date: Tue, 14 Feb 2023 03:25:39 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[CZ-384]=20=EA=B3=B5=ED=86=B5=20hooks?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=9E=AC?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=84=B1=EC=9D=84=20=EB=86=92=EC=9D=B4?= =?UTF-8?q?=EA=B8=B0=20=EC=9C=84=ED=95=9C=20hooks=20=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EC=B6=94=EA=B0=80=20(#56)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: hooks package 추가 * feat: hooks 패키지로 useToggle 마이그레이션 * fix: hooks 의존성 추가 * fix: next.js에서 file을 로딩하기 전에 원하는 패키지를transpiling 하도록 코드 추가 --- .pnp.cjs | 19 +++++++++++++++++++ apps/web/app/register/page.tsx | 2 +- apps/web/app/select/[id]/detail/page.tsx | 2 +- apps/web/app/select/[id]/page.tsx | 2 +- apps/web/next.config.js | 2 +- apps/web/package.json | 1 + packages/hooks/README.md | 1 + packages/hooks/index.ts | 1 + packages/hooks/package.json | 16 ++++++++++++++++ packages/hooks/src/index.ts | 1 + .../hooks => packages/hooks/src}/useToggle.ts | 0 packages/hooks/tsconfig.json | 15 +++++++++++++++ packages/ui/package.json | 1 + yarn.lock | 12 ++++++++++++ 14 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 packages/hooks/README.md create mode 100644 packages/hooks/index.ts create mode 100644 packages/hooks/package.json create mode 100644 packages/hooks/src/index.ts rename {apps/web/hooks => packages/hooks/src}/useToggle.ts (100%) create mode 100644 packages/hooks/tsconfig.json diff --git a/.pnp.cjs b/.pnp.cjs index 92db0b30..c8656552 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -19,6 +19,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "name": "@chooz/web",\ "reference": "workspace:apps/web"\ },\ + {\ + "name": "@chooz/hooks",\ + "reference": "workspace:packages/hooks"\ + },\ {\ "name": "@chooz/ui",\ "reference": "workspace:packages/ui"\ @@ -27,6 +31,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "enableTopLevelFallback": true,\ "ignorePatternData": "(^(?:\\\\.yarn\\\\/sdks(?:\\\\/(?!\\\\.{1,2}(?:\\\\/|$))(?:(?:(?!(?:^|\\\\/)\\\\.{1,2}(?:\\\\/|$)).)*?)|$))$)",\ "fallbackExclusionList": [\ + ["@chooz/hooks", ["workspace:packages/hooks"]],\ ["@chooz/ui", ["workspace:packages/ui"]],\ ["@chooz/web", ["workspace:apps/web"]],\ ["chooz", ["workspace:."]]\ @@ -3899,11 +3904,24 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@chooz/hooks", [\ + ["workspace:packages/hooks", {\ + "packageLocation": "./packages/hooks/",\ + "packageDependencies": [\ + ["@chooz/hooks", "workspace:packages/hooks"],\ + ["@types/react", "npm:18.0.26"],\ + ["react", "npm:18.2.0"],\ + ["typescript", "patch:typescript@npm%3A4.9.4#~builtin::version=4.9.4&hash=d73830"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ ["@chooz/ui", [\ ["workspace:packages/ui", {\ "packageLocation": "./packages/ui/",\ "packageDependencies": [\ ["@chooz/ui", "workspace:packages/ui"],\ + ["@chooz/hooks", "workspace:packages/hooks"],\ ["@types/node", "npm:18.11.17"],\ ["@types/react", "npm:18.0.26"],\ ["@types/react-dom", "npm:18.0.10"],\ @@ -3922,6 +3940,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./apps/web/",\ "packageDependencies": [\ ["@chooz/web", "workspace:apps/web"],\ + ["@chooz/hooks", "workspace:packages/hooks"],\ ["@chooz/ui", "workspace:packages/ui"],\ ["@next/font", "npm:13.1.6"],\ ["@svgr/webpack", "npm:6.5.1"],\ diff --git a/apps/web/app/register/page.tsx b/apps/web/app/register/page.tsx index 26c6e02d..d06f86e5 100644 --- a/apps/web/app/register/page.tsx +++ b/apps/web/app/register/page.tsx @@ -2,10 +2,10 @@ import { AgeSelection, GenderSelection, MBTISelection, ProgressBar } from "components"; import WarningSmallModal from "components/register/WarningSmallModal"; -import useToggle from "hooks/useToggle"; import useRegisterService from "services/useRegisterService"; import styled from "styled-components"; import { media } from "styles/media"; +import { useToggle } from "@chooz/hooks"; function RegisterPage() { const { diff --git a/apps/web/app/select/[id]/detail/page.tsx b/apps/web/app/select/[id]/detail/page.tsx index b8ab472c..35dd3eff 100644 --- a/apps/web/app/select/[id]/detail/page.tsx +++ b/apps/web/app/select/[id]/detail/page.tsx @@ -1,5 +1,6 @@ "use client"; +import { useToggle } from "@chooz/hooks"; import { media } from "@chooz/ui/styles/media"; import CommentContainer from "components/detail/CommentContainer"; import DetailAB from "components/detail/DetailAB"; @@ -7,7 +8,6 @@ import FilterBar from "components/detail/FilterBar"; import VoteAnalyzeBar from "components/detail/VoteAnalyzeBar"; import VoteToolbar from "components/select/VoteToolbar"; import useOutSideClick from "hooks/useOutsideClick"; -import useToggle from "hooks/useToggle"; import { Eximg1, Eximg2 } from "public/images"; import React, { useState } from "react"; import styled from "styled-components"; diff --git a/apps/web/app/select/[id]/page.tsx b/apps/web/app/select/[id]/page.tsx index 1ea244ee..fde34247 100644 --- a/apps/web/app/select/[id]/page.tsx +++ b/apps/web/app/select/[id]/page.tsx @@ -1,5 +1,6 @@ "use client"; +import { useToggle } from "@chooz/hooks"; import { Button, FloatModalTemplate } from "@chooz/ui"; import { media } from "@chooz/ui/styles/media"; import AddDetailModal from "components/select/AddDetailModal"; @@ -7,7 +8,6 @@ import useFlipAnimation, { Drag } from "components/select/hooks/useFlipAnimation import SelectAB from "components/select/SelectAB"; import VoteToolbar from "components/select/VoteToolbar"; import useOutSideClick from "hooks/useOutsideClick"; -import useToggle from "hooks/useToggle"; import Image from "next/image"; import Link from "next/link"; import { AmplifyIcon } from "public/icons"; diff --git a/apps/web/next.config.js b/apps/web/next.config.js index a6dbbbdc..e52c7768 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -1,5 +1,5 @@ // eslint-disable-next-line @typescript-eslint/no-var-requires -const withTM = require("next-transpile-modules")(["@chooz/ui"]); +const withTM = require("next-transpile-modules")(["@chooz/ui", "@chooz/hooks"]); /** @type {import('next').NextConfig} */ const nextConfig = { diff --git a/apps/web/package.json b/apps/web/package.json index 2a491d76..f837207a 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -10,6 +10,7 @@ "lint": "next lint" }, "dependencies": { + "@chooz/hooks": "workspace:*", "@chooz/ui": "workspace:*", "@next/font": "^13.1.6", "@tanstack/react-query": "^4.20.4", diff --git a/packages/hooks/README.md b/packages/hooks/README.md new file mode 100644 index 00000000..749fd943 --- /dev/null +++ b/packages/hooks/README.md @@ -0,0 +1 @@ +# hooks diff --git a/packages/hooks/index.ts b/packages/hooks/index.ts new file mode 100644 index 00000000..3bd16e17 --- /dev/null +++ b/packages/hooks/index.ts @@ -0,0 +1 @@ +export * from "./src"; diff --git a/packages/hooks/package.json b/packages/hooks/package.json new file mode 100644 index 00000000..00d4a487 --- /dev/null +++ b/packages/hooks/package.json @@ -0,0 +1,16 @@ +{ + "name": "@chooz/hooks", + "packageManager": "yarn@3.3.0", + "description": "", + "author": "", + "license": "ISC", + "version": "0.1.0", + "main": "index.ts", + "dependencies": { + "react": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18", + "typescript": "^4.9.4" + } +} diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts new file mode 100644 index 00000000..1cdef6a7 --- /dev/null +++ b/packages/hooks/src/index.ts @@ -0,0 +1 @@ +export { default as useToggle } from "./useToggle"; diff --git a/apps/web/hooks/useToggle.ts b/packages/hooks/src/useToggle.ts similarity index 100% rename from apps/web/hooks/useToggle.ts rename to packages/hooks/src/useToggle.ts diff --git a/packages/hooks/tsconfig.json b/packages/hooks/tsconfig.json new file mode 100644 index 00000000..23ce8e85 --- /dev/null +++ b/packages/hooks/tsconfig.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "target": "esnext", + "lib": ["dom", "dom.iterable", "esnext"], + "module": "esnext", + "jsx": "react-jsx", + "noEmit": false, + "incremental": true, + "declaration": true, + "declarationMap": true + }, + "exclude": ["**/node_modules", "**/.*/", "dist", "build"] +} diff --git a/packages/ui/package.json b/packages/ui/package.json index 6b1607ac..d619e9f5 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -7,6 +7,7 @@ "author": "", "license": "ISC", "dependencies": { + "@chooz/hooks": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0", "react-is": "^18.2.0", diff --git a/yarn.lock b/yarn.lock index 501a34eb..49032733 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1566,10 +1566,21 @@ __metadata: languageName: node linkType: hard +"@chooz/hooks@workspace:*, @chooz/hooks@workspace:packages/hooks": + version: 0.0.0-use.local + resolution: "@chooz/hooks@workspace:packages/hooks" + dependencies: + "@types/react": ^18 + react: ^18.2.0 + typescript: ^4.9.4 + languageName: unknown + linkType: soft + "@chooz/ui@workspace:*, @chooz/ui@workspace:packages/ui": version: 0.0.0-use.local resolution: "@chooz/ui@workspace:packages/ui" dependencies: + "@chooz/hooks": "workspace:*" "@types/node": ^18.11.17 "@types/react": ^18 "@types/react-dom": ^18 @@ -1586,6 +1597,7 @@ __metadata: version: 0.0.0-use.local resolution: "@chooz/web@workspace:apps/web" dependencies: + "@chooz/hooks": "workspace:*" "@chooz/ui": "workspace:*" "@next/font": ^13.1.6 "@svgr/webpack": ^6.5.1 From edef65778f7078185db10dc750faeded6a8c480b Mon Sep 17 00:00:00 2001 From: Leejha <57664427+Leejha@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:01:24 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[CZ-381]=20=EC=A0=95=EB=A0=AC=20select=20bo?= =?UTF-8?q?x=20=EA=B5=AC=ED=98=84=20(#57)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: select 컴포넌트를 위한 훅 추가 * feat: select 컴포넌트 구현 * feat: category select box 추가 * feat: 투표 리스트 페이지에 category select box 추가 * refactor: theme에서 사용하지 않는 코드 제거 * feat: select box drop down 아이콘 추가 * feat: select box ui패키지로 마이그레이션 * feat: 정렬 select box 구현 * refactor: 코드 리뷰 반영 --- apps/web/app/voteList/page.tsx | 23 +++++++++--- apps/web/components/common/select/index.ts | 1 - .../CategorySelectBox.tsx} | 24 +++++++------ .../web/components/voteList/SortSelectBox.tsx | 36 +++++++++++++++++++ apps/web/components/voteList/index.ts | 2 ++ apps/web/lib/constants.ts | 5 +++ .../public/icons/SelectDropdownIndicator.svg | 3 ++ apps/web/public/icons/index.ts | 2 +- apps/web/tsconfig.json | 3 +- packages/ui/components/index.ts | 1 + .../ui/components/selectBox}/Option.tsx | 9 +++-- .../ui/components/selectBox}/OptionList.tsx | 17 ++++----- .../ui/components/selectBox}/SelectButton.tsx | 14 ++++---- .../ui/components/selectBox/hooks/index.ts | 1 + .../components/selectBox}/hooks/useSelect.ts | 2 +- packages/ui/components/selectBox/index.ts | 4 +++ packages/ui/styles/theme.ts | 2 +- 17 files changed, 112 insertions(+), 37 deletions(-) delete mode 100644 apps/web/components/common/select/index.ts rename apps/web/components/{common/select/CategorySelect.tsx => voteList/CategorySelectBox.tsx} (50%) create mode 100644 apps/web/components/voteList/SortSelectBox.tsx create mode 100644 apps/web/public/icons/SelectDropdownIndicator.svg rename {apps/web/components/common/select => packages/ui/components/selectBox}/Option.tsx (70%) rename {apps/web/components/common/select => packages/ui/components/selectBox}/OptionList.tsx (50%) rename {apps/web/components/common/select => packages/ui/components/selectBox}/SelectButton.tsx (77%) create mode 100644 packages/ui/components/selectBox/hooks/index.ts rename {apps/web => packages/ui/components/selectBox}/hooks/useSelect.ts (89%) create mode 100644 packages/ui/components/selectBox/index.ts diff --git a/apps/web/app/voteList/page.tsx b/apps/web/app/voteList/page.tsx index d0f0a113..7af07857 100644 --- a/apps/web/app/voteList/page.tsx +++ b/apps/web/app/voteList/page.tsx @@ -1,7 +1,6 @@ "use client"; -import { CategorySelect } from "components/common/select"; -import { VoteList } from "components/voteList"; +import { CategorySelectBox, SortSelectBox, VoteList } from "components/voteList"; import { useState } from "react"; import useInfiniteVoteListService from "services/useInfiniteVoteListService"; import styled from "styled-components"; @@ -23,7 +22,14 @@ function VoteListPage() { - + + + +
    + + 선택만 보기 +
    +
    @@ -47,9 +53,16 @@ const PageInner = styled.div` } `; -const FilterSection = styled.section` +const FilterSection = styled.div` display: flex; - flex-direction: column; + justify-content: space-between; +`; + +const RightFilterContainer = styled.div` + display: flex; + align-items: center; + width: 183px; + justify-content: space-between; `; export default VoteListPage; diff --git a/apps/web/components/common/select/index.ts b/apps/web/components/common/select/index.ts deleted file mode 100644 index 0d709c3b..00000000 --- a/apps/web/components/common/select/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as CategorySelect } from "./CategorySelect"; diff --git a/apps/web/components/common/select/CategorySelect.tsx b/apps/web/components/voteList/CategorySelectBox.tsx similarity index 50% rename from apps/web/components/common/select/CategorySelect.tsx rename to apps/web/components/voteList/CategorySelectBox.tsx index d4da3f83..2287422f 100644 --- a/apps/web/components/common/select/CategorySelect.tsx +++ b/apps/web/components/voteList/CategorySelectBox.tsx @@ -1,24 +1,28 @@ +import { Option, OptionList, SelectButton, useSelect } from "@chooz/ui"; import useOutSideClick from "hooks/useOutsideClick"; -import { PropsWithChildren } from "react"; -import Option from "./Option"; -import { OptionList } from "./OptionList"; -import SelectButton from "./SelectButton"; -import useSelect from "hooks/useSelect"; import { CATEGORY_LIST } from "lib/constants"; import styled from "styled-components"; // @todo 추후 context api로 변경 // @todo 재사용 가능한 컴포넌트로 만들기 -function CategorySelect({ children }: PropsWithChildren) { +function CategorySelectBox() { const { isOpen, onChangeOpen, option, onChangeOption } = useSelect("전체"); - const { targetEl } = useOutSideClick(isOpen, onChangeOpen); + const { targetEl } = useOutSideClick(isOpen, onChangeOpen); return ( - {option} + + <> + {option} + + + {isOpen ? ( {CATEGORY_LIST.map( - ({ name }) => option !== name && ) : null} @@ -28,4 +32,4 @@ function CategorySelect({ children }: PropsWithChildren) { const SelectBox = styled.div``; -export default CategorySelect; +export default CategorySelectBox; diff --git a/apps/web/components/voteList/SortSelectBox.tsx b/apps/web/components/voteList/SortSelectBox.tsx new file mode 100644 index 00000000..bcb1be5b --- /dev/null +++ b/apps/web/components/voteList/SortSelectBox.tsx @@ -0,0 +1,36 @@ +import { Option, OptionList, SelectButton, useSelect } from "@chooz/ui"; +import useOutSideClick from "hooks/useOutsideClick"; +import { SORT_LIST } from "lib/constants"; +import { SelectDropdownIndicator } from "public/icons"; +import styled from "styled-components"; + +function SortSelectBox() { + const { isOpen, onChangeOpen, option, onChangeOption } = useSelect("최신순"); + const { targetEl } = useOutSideClick(isOpen, onChangeOpen); + return ( + + + <> + {option} + + + + {isOpen ? ( + + {SORT_LIST.map( + ({ name }) => + option !== name && ( + + ) : null} + + ); +} + +const SelectBox = styled.div` + border: solid 1px ${({ theme }) => theme.palette.border.base}; ; +`; + +export default SortSelectBox; diff --git a/apps/web/components/voteList/index.ts b/apps/web/components/voteList/index.ts index 5b59da51..67fbda32 100644 --- a/apps/web/components/voteList/index.ts +++ b/apps/web/components/voteList/index.ts @@ -1,2 +1,4 @@ export { default as VoteItem } from "./VoteItem"; export { default as VoteList } from "./VoteList"; +export { default as CategorySelectBox } from "./CategorySelectBox"; +export { default as SortSelectBox } from "./SortSelectBox"; diff --git a/apps/web/lib/constants.ts b/apps/web/lib/constants.ts index 87597499..691c8b46 100644 --- a/apps/web/lib/constants.ts +++ b/apps/web/lib/constants.ts @@ -24,6 +24,11 @@ export const CATEGORY_LIST = [ { id: "INTEREST", name: "재미" }, ]; +export const SORT_LIST = [ + { id: "new", name: "최신순" }, + { id: "popular", name: "인기순" }, +]; + export const AGE_LIST = [ { id: "teenager", name: "10대" }, { id: "twenties", name: "20대" }, diff --git a/apps/web/public/icons/SelectDropdownIndicator.svg b/apps/web/public/icons/SelectDropdownIndicator.svg new file mode 100644 index 00000000..9f9d521e --- /dev/null +++ b/apps/web/public/icons/SelectDropdownIndicator.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/web/public/icons/index.ts b/apps/web/public/icons/index.ts index 0556df84..ae43e493 100644 --- a/apps/web/public/icons/index.ts +++ b/apps/web/public/icons/index.ts @@ -3,7 +3,7 @@ export { default as HambergerIcon } from "./hambergerIcon.png"; export { default as KakaoIcon } from "./KakaoIcon.svg"; export { default as NaverIcon } from "./NaverIcon.svg"; export { default as BookmarkIcon } from "./BookmarkIcon.svg"; -export { default as SelectBoxIcon } from "./SelectBoxIcon.svg"; +export { default as SelectDropdownIndicator } from "./SelectDropdownIndicator.svg"; export { default as AmplifyIcon } from "./amplifyIcon.png"; export { default as AddIcon } from "./addIcon.png"; export { default as SaveIcon } from "./saveIcon.png"; diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index dc764245..e0599414 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -30,6 +30,7 @@ "**/*.json", "../../package/ui/styles/theme.ts", "../../package/ui/styles/transitions.ts", - ".next/types/**/*.ts" + ".next/types/**/*.ts", + "../../packages/ui/components/selectBox/hooks/useSelect.ts" ] } diff --git a/packages/ui/components/index.ts b/packages/ui/components/index.ts index bdfd1f70..a0bc0b42 100644 --- a/packages/ui/components/index.ts +++ b/packages/ui/components/index.ts @@ -6,3 +6,4 @@ export { default as ModalTemplate } from "./modal/ModalTemplate"; export { default as Input } from "./input/Input"; export { default as FloatModalTemplate } from "./modal/FloatModalTemplate"; export { default as DivideLine } from "./divide/DivideLine"; +export * from "./selectBox"; diff --git a/apps/web/components/common/select/Option.tsx b/packages/ui/components/selectBox/Option.tsx similarity index 70% rename from apps/web/components/common/select/Option.tsx rename to packages/ui/components/selectBox/Option.tsx index d7c5ec5e..5e252081 100644 --- a/apps/web/components/common/select/Option.tsx +++ b/packages/ui/components/selectBox/Option.tsx @@ -15,9 +15,14 @@ function Option({ name, onChangeOption }: OptionProps) { const Li = styled.li` display: flex; - flex-direction: row; - margin-bottom: 24px; + justify-content: center; + align-items: center; + padding: 14px 34px; ${({ theme }) => theme.textStyle.Title_Small}; + + :hover { + background-color: ${({ theme }) => theme.palette.background.selectedSoft}; + } `; export default Option; diff --git a/apps/web/components/common/select/OptionList.tsx b/packages/ui/components/selectBox/OptionList.tsx similarity index 50% rename from apps/web/components/common/select/OptionList.tsx rename to packages/ui/components/selectBox/OptionList.tsx index df890c58..32de409f 100644 --- a/apps/web/components/common/select/OptionList.tsx +++ b/packages/ui/components/selectBox/OptionList.tsx @@ -1,11 +1,10 @@ -import { Portal, transitions } from "@chooz/ui"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; interface OptionListProps { children: React.ReactNode; } -export function OptionList({ children }: OptionListProps) { +function OptionList({ children }: OptionListProps) { return (
      {children} @@ -15,13 +14,15 @@ export function OptionList({ children }: OptionListProps) { const Ul = styled.ul` position: absolute; - width: 136px; - height: 246px; margin-top: 8px; - padding: 20px 0 0 20px; border-radius: 8px; box-shadow: 0 0 40px 0 rgba(0, 0, 0, 0.1); - border: solid 1px var(--invalid-name); z-index: 99; - background-color: ${({ theme }) => theme.palette.background.white}; + ${({ theme }) => + css` + border: solid 1px ${theme.palette.border.base}; + background-color: ${theme.palette.background.white}; + `} `; + +export default OptionList; diff --git a/apps/web/components/common/select/SelectButton.tsx b/packages/ui/components/selectBox/SelectButton.tsx similarity index 77% rename from apps/web/components/common/select/SelectButton.tsx rename to packages/ui/components/selectBox/SelectButton.tsx index 72d5f480..fa2118d8 100644 --- a/apps/web/components/common/select/SelectButton.tsx +++ b/packages/ui/components/selectBox/SelectButton.tsx @@ -1,4 +1,3 @@ -import { SelectBoxIcon } from "public/icons"; import styled from "styled-components"; interface SelectProps { @@ -18,19 +17,20 @@ function SelectButton({ children, onChangeOpen }: SelectProps) { onClick={onChangeOpen} > {children} - ); } const StyledButton = styled.button` - display: flex; - flex-direction: row; - align-items: center; - + width: 80px; + height: 40px; > span { - margin-right: 18px; + /* margin-right: 18px; */ + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-around; } `; diff --git a/packages/ui/components/selectBox/hooks/index.ts b/packages/ui/components/selectBox/hooks/index.ts new file mode 100644 index 00000000..252834ba --- /dev/null +++ b/packages/ui/components/selectBox/hooks/index.ts @@ -0,0 +1 @@ +export { default as useSelect } from "./useSelect"; diff --git a/apps/web/hooks/useSelect.ts b/packages/ui/components/selectBox/hooks/useSelect.ts similarity index 89% rename from apps/web/hooks/useSelect.ts rename to packages/ui/components/selectBox/hooks/useSelect.ts index 43665230..b0598ac2 100644 --- a/apps/web/hooks/useSelect.ts +++ b/packages/ui/components/selectBox/hooks/useSelect.ts @@ -1,5 +1,5 @@ import { useState } from "react"; -import useToggle from "./useToggle"; +import { useToggle } from "@chooz/hooks"; export default function useSelect(defaultOption: string) { const [isOpen, onChangeOpen] = useToggle(); diff --git a/packages/ui/components/selectBox/index.ts b/packages/ui/components/selectBox/index.ts new file mode 100644 index 00000000..8970d082 --- /dev/null +++ b/packages/ui/components/selectBox/index.ts @@ -0,0 +1,4 @@ +export { default as Option } from "./Option"; +export { default as OptionList } from "./OptionList"; +export { default as SelectButton } from "./SelectButton"; +export * from "./hooks"; diff --git a/packages/ui/styles/theme.ts b/packages/ui/styles/theme.ts index 45d53af1..09763bee 100644 --- a/packages/ui/styles/theme.ts +++ b/packages/ui/styles/theme.ts @@ -1,4 +1,4 @@ -import { css, DefaultTheme } from "styled-components"; +import { DefaultTheme } from "styled-components"; const palette = { ink: {