diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 905b380c5..9a18cd5ff 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.0", + "version": "0.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.0", + "version": "0.1.3", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index c7dbfca71..42f857a3e 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.0", + "version": "0.1.3", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts index f45b02ea2..be05abb5b 100644 --- a/HDesign/src/components/Input/Input.style.ts +++ b/HDesign/src/components/Input/Input.style.ts @@ -19,8 +19,8 @@ const inputBoxBackgroundColorByInputType = (theme: Theme, inputType: InputType = export const inputBoxStyle = (theme: Theme, inputType: InputType = 'input') => css({ display: 'flex', - width: '100%', justifyContent: 'space-between', + marginInline: '1rem', padding: '0.75rem 1rem', borderRadius: '1rem', backgroundColor: inputBoxBackgroundColorByInputType(theme, inputType), diff --git a/HDesign/src/components/Search/Search.stories.tsx b/HDesign/src/components/Search/Search.stories.tsx new file mode 100644 index 000000000..40f7df4b1 --- /dev/null +++ b/HDesign/src/components/Search/Search.stories.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import type {Meta, StoryObj} from '@storybook/react'; + +import Search from '@components/Search/Search'; + +const meta = { + title: 'Components/Search', + component: Search, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + value: { + description: '', + control: {type: 'text'}, + }, + inputType: { + control: {type: 'radio'}, + }, + }, + args: { + disabled: false, + placeholder: 'placeholder', + searchTerms: ['todari', 'cookie'], + setKeyword: keyword => console.log(keyword), + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Search/Search.style.ts b/HDesign/src/components/Search/Search.style.ts new file mode 100644 index 000000000..413655bd5 --- /dev/null +++ b/HDesign/src/components/Search/Search.style.ts @@ -0,0 +1,39 @@ +import {Theme} from '@/theme/theme.type'; +import {css} from '@emotion/react'; + +export const searchStyle = css({ + position: 'relative', + + width: '100%', +}); + +export const searchTermsStyle = (theme: Theme) => + css({ + position: 'absolute', + top: '3.5rem', + + width: 'calc(100% - 2rem)', + margin: '0 1rem', + padding: '0.5rem 0', + + borderRadius: '1rem', + + backgroundColor: theme.colors.white, + }); + +export const searchTermStyle = (theme: Theme) => + css( + { + width: '100%', + padding: '0.5rem 1rem', + + color: theme.colors.onTertiary, + + '&:hover': { + borderRadius: '0.5rem', + + backgroundColor: theme.colors.lightGrayContainer, + }, + }, + theme.typography.body, + ); diff --git a/HDesign/src/components/Search/Search.tsx b/HDesign/src/components/Search/Search.tsx new file mode 100644 index 000000000..68fc02209 --- /dev/null +++ b/HDesign/src/components/Search/Search.tsx @@ -0,0 +1,42 @@ +/** @jsxImportSource @emotion/react */ +import Input from '../Input/Input'; +import {InputProps} from '../Input/Input.type'; +import {searchStyle, searchTermsStyle} from './Search.style'; +import useSearch from './useSearch'; +import {searchTermStyle} from './Search.style'; +import {useTheme} from '@theme/HDesignProvider'; +import Flex from '@components/Flex/Flex'; + +export interface SearchProps extends InputProps { + searchTerms: string[]; + setState: React.Dispatch>; +} + +const Search: React.FC = ({searchTerms, setState, ...inputProps}: SearchProps) => { + const {theme} = useTheme(); + const {value, showSearchTerms, handleOnChange, handleOnClick, filterSearchTerms} = useSearch({ + searchTerms, + setState, + }); + + return ( +
+ + {showSearchTerms && ( +
    + + {filterSearchTerms(value).map((searchTerm, index) => ( +
  • + +
  • + ))} +
    +
+ )} +
+ ); +}; + +export default Search; diff --git a/HDesign/src/components/Search/useSearch.ts b/HDesign/src/components/Search/useSearch.ts new file mode 100644 index 000000000..fbb9cf4c3 --- /dev/null +++ b/HDesign/src/components/Search/useSearch.ts @@ -0,0 +1,39 @@ +import {useState} from 'react'; + +interface UseSearchProps { + searchTerms: string[]; + setState: React.Dispatch>; +} + +const useSearch = ({searchTerms, setState}: UseSearchProps) => { + const [value, setValue] = useState(''); + const [showSearchTerms, setShowSearchTerms] = useState(false); + + const handleOnClick = (searchTerm: string) => { + setValue(searchTerm); + setState(searchTerm); + setShowSearchTerms(false); + }; + + const handleOnChange = (event: React.ChangeEvent) => { + const {value} = event.target; + setValue(value); + setShowSearchTerms(value.trim() !== '' && filterSearchTerms(value).length !== 0); + }; + + const filterSearchTerms = (keyword: string) => { + if (keyword.trim() === '') return []; + + return searchTerms.filter(terms => terms.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1); + }; + + return { + value, + showSearchTerms, + handleOnClick, + handleOnChange, + filterSearchTerms, + }; +}; + +export default useSearch; diff --git a/HDesign/src/components/Title/Title.style.ts b/HDesign/src/components/Title/Title.style.ts index ca0a02fc3..700128c02 100644 --- a/HDesign/src/components/Title/Title.style.ts +++ b/HDesign/src/components/Title/Title.style.ts @@ -6,6 +6,7 @@ export const titleContainerStyle = (theme: Theme) => css({ display: 'flex', flexDirection: 'column', + width: '100%', gap: '0.5rem', backgroundColor: theme.colors.white, padding: '1rem', diff --git a/HDesign/src/components/TopNav/TopNav.style.ts b/HDesign/src/components/TopNav/TopNav.style.ts index cd4244eb3..88910da47 100644 --- a/HDesign/src/components/TopNav/TopNav.style.ts +++ b/HDesign/src/components/TopNav/TopNav.style.ts @@ -3,4 +3,5 @@ import {css} from '@emotion/react'; export const topNavStyle = css({ display: 'flex', padding: '0 1rem', + width: '100%', }); diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx index 8c010bca0..7f941ad5f 100644 --- a/HDesign/src/index.tsx +++ b/HDesign/src/index.tsx @@ -1,13 +1,23 @@ import BillItem from '@components/BillItem/BillItem'; import BottomSheet from '@components/BottomSheet/BottomSheet'; import Button from '@components/Button/Button'; +import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; +import ExpenseList from '@components/ExpenseList/ExpenseList'; import FixedButton from '@components/FixedButton/FixedButton'; +import Flex from '@components/Flex/Flex'; import IconButton from '@components/IconButton/IconButton'; import InOutItem from '@components/InOutItem/InOutItem'; import Input from '@components/Input/Input'; +import Search from '@components/Search/Search'; import StepItem from '@components/StepItem/StepItem'; +import Switch from '@components/Switch/Switch'; +import Tab from '@components/Tab/Tab'; import Text from '@components/Text/Text'; +import TextButton from '@components/TextButton/TextButton'; import Title from '@components/Title/Title'; +import TopNav from '@components/TopNav/TopNav'; + +import {MainLayout} from '@layouts/MainLayout'; import {HDesignProvider} from '@theme/HDesignProvider'; @@ -15,12 +25,21 @@ export { BillItem, BottomSheet, Button, + DragHandleItem, + ExpenseList, FixedButton, + Flex, IconButton, InOutItem, Input, + Search, StepItem, + Switch, + Tab, Text, + TextButton, Title, + TopNav, + MainLayout, HDesignProvider, }; diff --git a/HDesign/src/layouts/MainLayout.tsx b/HDesign/src/layouts/MainLayout.tsx new file mode 100644 index 000000000..825aca175 --- /dev/null +++ b/HDesign/src/layouts/MainLayout.tsx @@ -0,0 +1,12 @@ +import {PropsWithChildren} from 'react'; +import {Flex} from '..'; + +interface MainLayoutInterface extends PropsWithChildren {} + +export const MainLayout = ({children}: MainLayoutInterface) => { + return ( + + {children} + + ); +}; diff --git a/HDesign/tsconfig.json b/HDesign/tsconfig.json index 6cbcf91bd..371b40efe 100644 --- a/HDesign/tsconfig.json +++ b/HDesign/tsconfig.json @@ -18,6 +18,7 @@ "paths": { "@/*": ["src/*"], "@components/*": ["src/components/*"], + "@layouts/*": ["src/layouts/*"], "@token/*": ["src/token/*"], "@theme/*": ["src/theme/*"], "@assets/*": ["src/assets/*"]