From 63357159f0af3828ec7faa3b391e81d91fdfebdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A5=AC=EB=A8=90?= Date: Sat, 18 Jan 2025 02:48:11 +0900 Subject: [PATCH] =?UTF-8?q?[Feat/#37]=20Input=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84=20(#38)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: input 컴포넌트 구현 * feat: input 컴포넌트 스토리북 구현 * chore: git merge develop 후 후순위 이슈로 잠정적 중단 * chore: pr fail 해결 * feat: input 컴포넌트 80% 완성 * input 컴포넌트 완성 * App.tsx 파일 최신화 * chore: 코드리뷰 반영 * feat: input 완성 * chore: base 폰트 추가 * chore: 트렌지션 수정 --- public/svg/ic_arrow_right_24.svg | 6 --- public/svg/ic_form_dot.svg | 3 ++ public/svg/ic_form_dotdot.svg | 4 ++ src/App.tsx | 14 +++++++ src/assets/svgs/IcFormDot.tsx | 12 ++++++ src/assets/svgs/IcFormDotdot.tsx | 13 +++++++ src/assets/svgs/index.ts | 8 ++-- src/components/common/Input/Input.css.ts | 49 ++++++++++++++++++++++++ src/components/common/Input/Input.tsx | 31 +++++++++++++++ src/components/common/index.ts | 2 + src/stories/Input.stories.tsx | 30 +++++++++++++++ 11 files changed, 163 insertions(+), 9 deletions(-) create mode 100644 public/svg/ic_form_dot.svg create mode 100644 public/svg/ic_form_dotdot.svg create mode 100644 src/assets/svgs/IcFormDot.tsx create mode 100644 src/assets/svgs/IcFormDotdot.tsx create mode 100644 src/components/common/Input/Input.css.ts create mode 100644 src/components/common/Input/Input.tsx create mode 100644 src/stories/Input.stories.tsx diff --git a/public/svg/ic_arrow_right_24.svg b/public/svg/ic_arrow_right_24.svg index 817f47b6..49833b04 100644 --- a/public/svg/ic_arrow_right_24.svg +++ b/public/svg/ic_arrow_right_24.svg @@ -1,9 +1,3 @@ -<<<<<<< HEAD - - - -======= ->>>>>>> develop diff --git a/public/svg/ic_form_dot.svg b/public/svg/ic_form_dot.svg new file mode 100644 index 00000000..ddfc5c38 --- /dev/null +++ b/public/svg/ic_form_dot.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/svg/ic_form_dotdot.svg b/public/svg/ic_form_dotdot.svg new file mode 100644 index 00000000..8d0114e4 --- /dev/null +++ b/public/svg/ic_form_dotdot.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/App.tsx b/src/App.tsx index e0339528..5f895836 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,9 @@ import { QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; +import { useState } from 'react'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import { Input } from '@components'; import { ToastProvider } from '@contexts'; import { pageRoutes } from '@routes'; @@ -12,10 +14,22 @@ import '@styles/global.css'; const router = createBrowserRouter(pageRoutes); const App = () => { + const [inputValue, setInputValue] = useState(''); + + const handleInputChange = (e: React.ChangeEvent) => { + setInputValue(e.target.value); + }; + return ( +
diff --git a/src/assets/svgs/IcFormDot.tsx b/src/assets/svgs/IcFormDot.tsx new file mode 100644 index 00000000..57a6a332 --- /dev/null +++ b/src/assets/svgs/IcFormDot.tsx @@ -0,0 +1,12 @@ +import type { SVGProps } from 'react'; +const SvgIcFormDot = (props: SVGProps) => ( + + + +); +export default SvgIcFormDot; diff --git a/src/assets/svgs/IcFormDotdot.tsx b/src/assets/svgs/IcFormDotdot.tsx new file mode 100644 index 00000000..b33f568f --- /dev/null +++ b/src/assets/svgs/IcFormDotdot.tsx @@ -0,0 +1,13 @@ +import type { SVGProps } from 'react'; +const SvgIcFormDotdot = (props: SVGProps) => ( + + + + +); +export default SvgIcFormDotdot; diff --git a/src/assets/svgs/index.ts b/src/assets/svgs/index.ts index e18427c3..aeba3d19 100644 --- a/src/assets/svgs/index.ts +++ b/src/assets/svgs/index.ts @@ -5,12 +5,16 @@ export { default as IcArrowUp20 } from './IcArrowUp20'; export { default as IcCheck } from './IcCheck'; export { default as IcFillLikeOff36 } from './IcFillLikeOff36'; export { default as IcFillLikeOn36 } from './IcFillLikeOn36'; +export { default as IcFormDot } from './IcFormDot'; +export { default as IcFormDotdot } from './IcFormDotdot'; export { default as IcGpsmarkerOff } from './IcGpsmarkerOff'; export { default as IcGpsmarkerOn } from './IcGpsmarkerOn'; export { default as IcKakao } from './IcKakao'; export { default as IcLineLikeOff20 } from './IcLineLikeOff20'; export { default as IcLineLikeOn20 } from './IcLineLikeOn20'; +export { default as IcLocation } from './IcLocation'; export { default as IcMy } from './IcMy'; +export { default as IcMypageArrowRight24 } from './IcMypageArrowRight24'; export { default as IcSavedOff24 } from './IcSavedOff24'; export { default as IcSavedOn24 } from './IcSavedOn24'; export { default as IcSearchCategoryAnivUnactivate } from './IcSearchCategoryAnivUnactivate'; @@ -19,12 +23,10 @@ export { default as IcSearchCategoryCheerUnactivate } from './IcSearchCategoryCh export { default as IcSearchCategorySeasonUnactivate } from './IcSearchCategorySeasonUnactivate'; export { default as IcToastCheck } from './IcToastCheck'; export { default as IcToastError } from './IcToastError'; -export { default as IcLocation } from './IcLocation'; export { default as ImgLogo } from './ImgLogo'; +export { default as ImgMypageProfileLogin } from './ImgMypageProfileLogin'; export { default as ImgStore11Cm } from './ImgStore11Cm'; export { default as ImgStore13Cm } from './ImgStore13Cm'; export { default as ImgStore16Cm } from './ImgStore16Cm'; export { default as ImgStore19Cm } from './ImgStore19Cm'; export { default as ImgStore22Cm } from './ImgStore22Cm'; -export { default as ImgMypageProfileLogin } from './ImgMypageProfileLogin'; -export { default as IcMypageArrowRight24 } from './IcMypageArrowRight24'; diff --git a/src/components/common/Input/Input.css.ts b/src/components/common/Input/Input.css.ts new file mode 100644 index 00000000..cbbbc36b --- /dev/null +++ b/src/components/common/Input/Input.css.ts @@ -0,0 +1,49 @@ +import { style } from '@vanilla-extract/css'; +import { recipe } from '@vanilla-extract/recipes'; + +import { flexGenerator } from '@styles/generator.css'; +import { vars } from '@styles/theme.css'; + +export const inputContainer = style([ + flexGenerator('column', 'center', 'flex-start'), + { + gap: '0.4rem', + }, +]); + +export const inputTitle = style([ + flexGenerator(), + vars.fonts.body05_m_14, + { + color: vars.colors.gray700, + }, +]); + +export const inputStyle = recipe({ + base: [ + vars.fonts.body07_r_14, + { + width: '100%', + backgroundColor: vars.colors.white, + border: `1px solid ${vars.colors.gray300}`, + borderRadius: '8px', + padding: '1.4rem 2rem', + selectors: { + '&:focus': { + border: `1px solid ${vars.colors.gray500}`, + }, + }, + }, + ], + variants: { + state: { + default: { color: vars.colors.gray400 }, + active: { + color: vars.colors.gray900, + }, + }, + }, + defaultVariants: { + state: 'default', + }, +}); diff --git a/src/components/common/Input/Input.tsx b/src/components/common/Input/Input.tsx new file mode 100644 index 00000000..5d0b878f --- /dev/null +++ b/src/components/common/Input/Input.tsx @@ -0,0 +1,31 @@ +import { IcFormDot, IcFormDotdot } from '@svgs'; + +import { inputTitle, inputContainer, inputStyle } from './Input.css'; + +type InputProps = { + inputLabel?: string; + value: string; + onChange: (e: React.ChangeEvent) => void; + placeholder?: string; +}; + +const Input = ({ inputLabel, value, onChange, placeholder }: InputProps) => { + return ( +
+ + +
+ ); +}; + +export default Input; diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 3d75dd6b..6db94377 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -6,6 +6,7 @@ import FilteringButton from './FilteringButton/FilteringButton'; import Header from './Header/Header'; import IconButton from './IconButton/IconButton'; import Image from './Image/Image'; +import Input from './Input/Input'; import Label from './Label/Label'; import Modal from './Modal/Modal'; import SocialLoginButton from './SocialLoginButton/SocialLoginButton'; @@ -30,4 +31,5 @@ export { BottomSheet, DesignCard, Toast, + Input, }; diff --git a/src/stories/Input.stories.tsx b/src/stories/Input.stories.tsx new file mode 100644 index 00000000..a9a4e7b5 --- /dev/null +++ b/src/stories/Input.stories.tsx @@ -0,0 +1,30 @@ +import { Input } from '@components'; + +import type { Meta, StoryObj } from '@storybook/react'; + +const meta: Meta = { + title: 'Components/Input', + component: Input, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], + argTypes: { + inputLabel: { control: 'text' }, + value: { control: 'text' }, + onChange: { action: 'changed' }, + placeholder: { control: 'text' }, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + inputLabel: '픽업 날짜/요일/시간(30분 단위로)', + value: '', + onChange: () => {}, + placeholder: '예: 01.03/금/16:30', + }, +};