diff --git a/src/ui/search-field/index.ts b/src/ui/search-field/index.ts new file mode 100644 index 000000000..b2151f474 --- /dev/null +++ b/src/ui/search-field/index.ts @@ -0,0 +1 @@ +export { SearchField, type SearchFieldProps } from './search-field.tsx'; diff --git a/src/ui/search-field/search-field.stories.tsx b/src/ui/search-field/search-field.stories.tsx new file mode 100644 index 000000000..1c951ac83 --- /dev/null +++ b/src/ui/search-field/search-field.stories.tsx @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { SearchField } from './search-field.tsx'; + +const meta: Meta = { + title: 'ui/SearchField', + component: SearchField, + parameters: { + layout: 'centered', + }, + argTypes: { + hasResetButton: { + control: { + type: 'boolean', + }, + }, + variant: { + options: ['default', 'home'], + control: { + type: 'radio', + }, + }, + }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: { + label: 'Default', + hasResetButton: true, + }, +}; + +export const Secondary: Story = { + args: { + label: 'With Placeholder', + placeholder: '건강 불편 증상을 검색해 보세요', + }, +}; + +export const Home: Story = { + args: { + label: 'Home', + value: 'Home에서 검색 창', + variant: 'home', + }, +}; diff --git a/src/ui/search-field/search-field.styles.css.ts b/src/ui/search-field/search-field.styles.css.ts new file mode 100644 index 000000000..d49409987 --- /dev/null +++ b/src/ui/search-field/search-field.styles.css.ts @@ -0,0 +1,67 @@ +import { style } from '@vanilla-extract/css'; +import { type RecipeVariants, recipe } from '@vanilla-extract/recipes'; +import { typography } from '../typography.css.ts'; +import { globalVars } from './../theme.css.ts'; + +const base = style([ + typography('head_3_16_r'), + { + color: globalVars.color.black, + outline: 'none', + borderRadius: 20, + border: 'none', + width: '100%', + '::placeholder': { + color: globalVars.color.grey500, + }, + }, +]); + +export const searchFieldVariants = recipe({ + base, + variants: { + variant: { + default: { + padding: '8px 32px 8px 40px', + backgroundColor: globalVars.color.grey200, + }, + home: { + padding: '14px 27px 14px 52px', + backgroundColor: globalVars.color.white, + border: '1px solid', + borderColor: globalVars.color.mainblue500, + borderRadius: 25, + }, + }, + }, + defaultVariants: { + variant: 'default', + }, +}); + +export type SearchFieldVariants = Exclude< + RecipeVariants, + undefined +>; + +export const searchFieldContainer = style({ + position: 'relative', + display: 'flex', + alignItems: 'center', +}); + +export const SearchFieldLeftElement = style({ + position: 'absolute', + left: 12, + height: '100%', +}); + +export const SearchFieldRightElement = style({ + all: 'unset', + position: 'absolute', + right: 4, + cursor: 'pointer', + height: '100%', + display: 'flex', + alignItems: 'center', +}); diff --git a/src/ui/search-field/search-field.tsx b/src/ui/search-field/search-field.tsx new file mode 100644 index 000000000..bb0e33746 --- /dev/null +++ b/src/ui/search-field/search-field.tsx @@ -0,0 +1,35 @@ +import { ComponentProps } from 'react'; +import { DeleteCir, Search } from '../../assets/index.ts'; +import { cx } from '../util.ts'; +import * as styles from './search-field.styles.css.ts'; + +export type SearchFieldProps = ComponentProps<'input'> & + styles.SearchFieldVariants & + Partial<{ + hasResetButton: boolean; + onClickResetButton: VoidFunction; + }>; + +export const SearchField = (props: SearchFieldProps) => { + const { className, variant, hasResetButton, ...restProps } = props; + + return ( +
+ + + {hasResetButton && ( + + )} +
+ ); +};