From 00d7fcc012adb9de9b16dcc058155f3a6cf9890b Mon Sep 17 00:00:00 2001 From: Nahyun Date: Sun, 15 Dec 2024 14:43:24 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20=EA=B2=80=EC=83=89=EB=B0=94=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(home)/_components/Header.css.ts | 2 +- src/app/(home)/_components/Header.tsx | 4 +- .../(home)/_components/SearchBarArea.css.ts | 35 ++++++++ src/app/(home)/_components/SearchBarArea.tsx | 21 +++++ src/app/search/_components/SearchBar.css.ts | 2 +- src/components/SearchBar/KeywordArea.css.ts | 86 +++++++++++++++++++ src/components/SearchBar/KeywordArea.tsx | 44 ++++++++++ src/components/SearchBar/index.tsx | 70 +++++++++++---- src/lib/constants/placeholder.ts | 2 +- 9 files changed, 246 insertions(+), 20 deletions(-) create mode 100644 src/app/(home)/_components/SearchBarArea.css.ts create mode 100644 src/app/(home)/_components/SearchBarArea.tsx create mode 100644 src/components/SearchBar/KeywordArea.css.ts create mode 100644 src/components/SearchBar/KeywordArea.tsx diff --git a/src/app/(home)/_components/Header.css.ts b/src/app/(home)/_components/Header.css.ts index 9dc1a701..a843e35b 100644 --- a/src/app/(home)/_components/Header.css.ts +++ b/src/app/(home)/_components/Header.css.ts @@ -5,7 +5,7 @@ export const headerWrapper = style({ width: '100%', height: '40px', padding: '10px 16px', - margin: '0 0 12px', + margin: '0 0 16px', }); export const entireWrapper = style({ diff --git a/src/app/(home)/_components/Header.tsx b/src/app/(home)/_components/Header.tsx index f20c3f88..34f97937 100644 --- a/src/app/(home)/_components/Header.tsx +++ b/src/app/(home)/_components/Header.tsx @@ -7,7 +7,7 @@ import Link from 'next/link'; import Image from 'next/image'; import { useQuery } from '@tanstack/react-query'; -import SearchBarComponent from '@/components/SearchBar'; +import SearchBarArea from './SearchBarArea'; import Modal from '@/components/Modal/Modal'; import LoginModal from '@/components/login/LoginModal'; @@ -59,7 +59,7 @@ function Header() { return (
- {isSearchBarOpened && } + {isSearchBarOpened && } {!isSearchBarOpened && (
diff --git a/src/app/(home)/_components/SearchBarArea.css.ts b/src/app/(home)/_components/SearchBarArea.css.ts new file mode 100644 index 00000000..847ea156 --- /dev/null +++ b/src/app/(home)/_components/SearchBarArea.css.ts @@ -0,0 +1,35 @@ +import { style } from '@vanilla-extract/css'; + +export const wrapper = style({ + width: '100%', + + display: 'flex', + alignItems: 'center', +}); + +export const inputWrapper = style({ + width: '100%', + + display: 'flex', + alignItems: 'center', +}); + +export const input = style({ + width: '100%', + + fontSize: '1.6rem', + overflow: 'hidden', + '::placeholder': { + color: '#637587', + fontWeight: '400', + fontSize: '1.6rem', + }, +}); + +export const cancelButton = style({ + flexShrink: 0, + fontWeight: '400', + fontSize: '1.6rem', + letterSpacing: '-3%', + color: '#213752', +}); diff --git a/src/app/(home)/_components/SearchBarArea.tsx b/src/app/(home)/_components/SearchBarArea.tsx new file mode 100644 index 00000000..1609334e --- /dev/null +++ b/src/app/(home)/_components/SearchBarArea.tsx @@ -0,0 +1,21 @@ +import * as styles from './SearchBarArea.css'; +import SearchBar from '@/components/SearchBar'; + +interface SearchBarProps { + handleCancel?: () => void; +} + +function SearchBarArea({ handleCancel }: SearchBarProps) { + return ( +
+
+ +
+ +
+ ); +} + +export default SearchBarArea; diff --git a/src/app/search/_components/SearchBar.css.ts b/src/app/search/_components/SearchBar.css.ts index 7dbf91f7..61cb8b8b 100644 --- a/src/app/search/_components/SearchBar.css.ts +++ b/src/app/search/_components/SearchBar.css.ts @@ -2,7 +2,7 @@ import { style } from '@vanilla-extract/css'; export const searchWrapper = style({ width: '100%', - padding: '0 16px', + padding: '0 16px 0 0', display: 'flex', flexDirection: 'column', diff --git a/src/components/SearchBar/KeywordArea.css.ts b/src/components/SearchBar/KeywordArea.css.ts new file mode 100644 index 00000000..e8e0aa10 --- /dev/null +++ b/src/components/SearchBar/KeywordArea.css.ts @@ -0,0 +1,86 @@ +import { style, keyframes } from '@vanilla-extract/css'; +import { vars } from '@/styles/__theme.css'; + +export const keywordWrapper = style({ + width: '100%', + + position: 'relative', + + display: 'flex', + flexDirection: 'column', + gap: '1.6rem', + + backgroundColor: vars.color.white, + borderRadius: '50px', +}); + +const moveInputRight = keyframes({ + '0%': { transform: 'translateX(1%)' }, + '100%': { transform: 'translateX(0)' }, +}); + +const moveInputLeft = keyframes({ + '0%': { transform: 'translateX(-1%)' }, + '100%': { transform: 'translateX(0)' }, +}); + +const moveIconRight = keyframes({ + '0%': { transform: 'translateX(-100%)' }, + '100%': { transform: 'translateX(0)' }, +}); + +const moveIconLeft = keyframes({ + '0%': { transform: 'translateX(100%)' }, + '100%': { transform: 'translateX(0)' }, +}); + +export const keywordInput = style({ + padding: '0.5rem 1.5rem 0.5rem 4rem', + + backgroundColor: 'transparent', + + fontSize: '1.5rem', + + zIndex: 2, +}); + +export const basicKeywordInput = style([ + keywordInput, + { + padding: '1.1rem 4rem 1.1rem 4rem', + animation: `${moveInputLeft} 0.5s ease`, + }, +]); + +export const typedKeywordInput = style([ + keywordInput, + { + padding: '1.1rem 4rem 1.1rem 1.5rem', + animation: `${moveInputRight} 0.5s ease`, + }, +]); + +export const searchIcon = style({ + position: 'absolute', + top: '1.2rem', + zIndex: 2, +}); + +export const basicSearchIcon = style([ + searchIcon, + { + left: '1.5rem', + + animation: `${moveIconLeft} 0.2s ease-in-out`, + }, +]); + +export const typedSearchIcon = style([ + searchIcon, + { + right: '1.5rem', + + animation: `${moveIconRight} 0.2s ease-in-out`, + cursor: 'pointer', + }, +]); diff --git a/src/components/SearchBar/KeywordArea.tsx b/src/components/SearchBar/KeywordArea.tsx new file mode 100644 index 00000000..a3720c4a --- /dev/null +++ b/src/components/SearchBar/KeywordArea.tsx @@ -0,0 +1,44 @@ +import { ChangeEventHandler, KeyboardEventHandler, MouseEventHandler, useEffect, useRef, useState } from 'react'; +import { useSearchParams } from 'next/navigation'; + +import * as styles from './KeywordArea.css'; + +import SearchIcon from '/public/icons/search.svg'; +import { useLanguage } from '@/store/useLanguage'; +import { searchPlaceholer } from '@/lib/constants/placeholder'; + +interface searchKeywordAreaProps { + onKeyDown?: KeyboardEventHandler; + onInput: ChangeEventHandler; + onClick?: MouseEventHandler; +} + +function KeywordArea({ onKeyDown, onInput, onClick }: searchKeywordAreaProps) { + const { language } = useLanguage(); + const searchParams = useSearchParams(); + const defaultKeyword: string = searchParams?.get('keyword') ?? ''; + + const inputRef = useRef(null); + const [inputHasValue, setInputHasValue] = useState(false); + + useEffect(() => { + setInputHasValue(!!inputRef.current?.value); + }, [inputRef.current?.value]); + + return ( +
+ + +
+ ); +} + +export default KeywordArea; diff --git a/src/components/SearchBar/index.tsx b/src/components/SearchBar/index.tsx index a402172e..ef9f0347 100644 --- a/src/components/SearchBar/index.tsx +++ b/src/components/SearchBar/index.tsx @@ -1,22 +1,62 @@ -import * as styles from './SearchBar.css'; -import SearchIcon from '/public/icons/ver3/search.svg'; +'use client'; -interface SearchBarProps { - handleCancel?: () => void; -} +import { ChangeEvent, useState, KeyboardEvent, MouseEvent } from 'react'; +import { useRouter } from 'next/navigation'; +import KeywordArea from './KeywordArea'; + +import * as styles from '@/app/search/_components/SearchBar.css'; + +function SearchBar() { + const router = useRouter(); + const [keyword, setKeyword] = useState(''); + + const handleSearchClick = (e: MouseEvent) => { + router.push(`/search?keyword=${keyword}`); + }; + + const handleEnterKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Enter') { + // keyword가 없는 경우, 초기 category값을 '전체' 로 설정 + router.push(`/search?keyword=${keyword}&category=entire`); + } + }; + + const handleInputChange = (e: ChangeEvent) => { + setKeyword(e.target.value); + }; + + const handelCategoryClick = (e: MouseEvent) => { + router.push(`/search?category=${e.currentTarget?.dataset?.value}`); + }; -function SearchBarComponent({ handleCancel }: SearchBarProps) { return ( -
-
- - -
- +
+
); } -export default SearchBarComponent; +export default SearchBar; + +// import * as styles from './SearchBar.css'; +// import SearchIcon from '/public/icons/ver3/search.svg'; + +// interface SearchBarProps { +// handleCancel?: () => void; +// } + +// function SearchBarComponent({ handleCancel }: SearchBarProps) { +// return ( +//
+//
+// +// +//
+// +//
+// ); +// } + +// export default SearchBarComponent; diff --git a/src/lib/constants/placeholder.ts b/src/lib/constants/placeholder.ts index 12815952..6b711a4d 100644 --- a/src/lib/constants/placeholder.ts +++ b/src/lib/constants/placeholder.ts @@ -41,7 +41,7 @@ export const profilePlaceholder = { export const searchPlaceholer = { ko: { - keyword: '검색어를 입력해주세요.', + keyword: '리스트 혹은 리스터를 검색해 보세요', }, en: { keyword: 'Please enter a search term.',