diff --git a/.storybook/preview-body.html b/.storybook/preview-body.html new file mode 100644 index 0000000..6322ef7 --- /dev/null +++ b/.storybook/preview-body.html @@ -0,0 +1,2 @@ +
+
diff --git a/README.md b/README.md index a456d1e..542296b 100644 --- a/README.md +++ b/README.md @@ -36,24 +36,27 @@ import FunEatProvider from '@fun-eat/design-system'; ### Props -| props | value | description | -| --------- | ----------------------------------------------------- | -------------------------------------------- | -| element | p, span (default: span) | Badge 컴포넌트의 element 타입입니다. | -| color | CSSProperties['color'] | Badge 컴포넌트 내부 색상입니다. | -| textColor | CSSProperties['color'] | Badge 컴포넌트에 들어갈 텍스트의 색상입니다. | -| size? | `xs` , `sm`, `md` , `lg` , `xl`
(default: `sm`) | Badge 컴포넌트에 들어갈 텍스트의 크기입니다. | -| css? | CSSProp | Badge 컴포넌트에 적용할 CSS 스타일입니다. | +| props | value | description | +| --------- | -------------------------------------- | -------------------------------------------- | +| element | p, span
(default: span) | Badge 컴포넌트의 element 타입입니다. | +| color | CSSProperties['color'] | Badge 컴포넌트 내부 색상입니다. | +| textColor | CSSProperties['color'] | Badge 컴포넌트에 들어갈 텍스트의 색상입니다. | +| size? | xs, sm, md, lg, xl
(default: sm) | Badge 컴포넌트에 들어갈 텍스트의 크기입니다. | +| css? | CSSProp | Badge 컴포넌트에 적용할 CSS 스타일입니다. | ### Example -```jsx +```tsx 뱃지 뱃지 ``` +
+ ## BottomSheet 아래에서 위로 올라오는 바텀시트 컴포넌트입니다. + @fun-eat/design-system에서 제공하는 useBottomSheet와 사용해야 합니다. ### Props @@ -85,22 +88,24 @@ const Parent = () => { }; ``` +
+ ## Button 버튼 컴포넌트입니다. ### Props -| props | value | description | -| ------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -| customWidth? | string
(default: 120px) | Button 컴포넌트의 넓이입니다. | -| customHeight? | string
(default: 40px) | Button 컴포넌트의 높이입니다. | -| color? | color
(default: `primary`) | Button 컴포넌트의 색상입니다. | -| textColor? | color
(default: `default`) | Button 컴포넌트의 텍스트 색상입니다. | -| size? | `xs`, `sm`, `md`, `lg`, `xl`
(default: `md`) | Button 컴포넌트의 폰트 크기입니다. | -| weight? | `light`, `regular`, `bold`
(default: `bold`) | Button 컴포넌트의 폰트 가중치입니다. | -| variant? | `outlined`, `filled`, `transparent`
(default: `filled`) | Button 컴포넌트의 스타일로 배경색 없이 아웃라인이 있는지, 배경색이 있고 아웃라인이 없는지, 투명 배경인지 설정할 수 있습니다. | -| css? | CSSProp | Button 컴포넌트에 적용할 CSS 스타일입니다. | +| props | value | description | +| ------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | +| customWidth? | string
(default: 120px) | Button 컴포넌트의 넓이입니다. | +| customHeight? | string
(default: 40px) | Button 컴포넌트의 높이입니다. | +| color? | color
(default: primary) | Button 컴포넌트의 색상입니다. | +| textColor? | color
(default: default) | Button 컴포넌트의 텍스트 색상입니다. | +| size? | xs, sm, md, lg, xl
(default: md) | Button 컴포넌트의 폰트 크기입니다. | +| weight? | light, regular, bold
(default: bold) | Button 컴포넌트의 폰트 가중치입니다. | +| variant? | outlined, filled, transparent
(default: filled) | Button 컴포넌트의 스타일로 배경색 없이 아웃라인이 있는지, 배경색이 있고 아웃라인이 없는지, 투명 배경인지 설정할 수 있습니다. | +| css? | CSSProp | Button 컴포넌트에 적용할 CSS 스타일입니다. | ### Example @@ -109,18 +114,20 @@ const Parent = () => { ``` -## Checkbox +
+ +## **Checkbox** 체크박스 컴포넌트입니다. ### Props -| props | value | description | -| --------- | --------------------------------------------------- | ---------------------------------------- | -| size? | `xs`, `sm`, `md`, `lg`, `xl`
(default: `md`) | Checkbox 컴포넌트의 체크박스 크기입니다. | -| fontSize? | `xs`, `sm`, `md`, `lg`, `xl`
(default: `md`) | Checkbox 컴포넌트의 폰트 크기입니다. | -| weight? | `light`, `regular`, `bold`
(default: `bold`) | Checkbox 컴포넌트의 폰트 가중치입니다. | -| tabIndex? | `-1`, `0`, `1`
| Checkbox 컴포넌트의 tabIndex입니다. | +| props | value | description | +| --------- | ------------------------------------------ | ---------------------------------------- | +| size? | xs, sm, md, lg, xl
(default: md) | Checkbox 컴포넌트의 체크박스 크기입니다. | +| fontSize? | xs, sm, md, lg, xl
(default: md) | Checkbox 컴포넌트의 폰트 크기입니다. | +| weight? | light, regular, bold
(default: bold) | Checkbox 컴포넌트의 폰트 가중치입니다. | +| tabIndex? | -1, 0, 1 | Checkbox 컴포넌트의 tabIndex입니다. | ### Example @@ -130,40 +137,43 @@ const Parent = () => { 재구매 의사가 있으신가요? ``` +
+ ## Divider 화면 구역을 나누는 선 컴포넌트입니다. ### Props -| props | value | description | -| ------------- | ----------------------------------------------------- | ----------------------------------------------------------- | -| variant? | default , strong , disabled
(default: default) | Divider 컴포넌트의 종류입니다. 강조의 정도 차이가 있습니다. | -| customWidth? | string
(default: 100%) | Divider 컴포넌트의 길이입니다. | -| customHeight? | string
(default: 1px) | Divider 컴포넌트의 두께입니다. | -| css? | CSSProp | Divider 컴포넌트에 적용할 CSS 스타일입니다. | +| props | value | description | +| ------------- | ---------------------------------------------------- | ----------------------------------------------------------- | +| variant? | default , strong , disabled
(default: default) | Divider 컴포넌트의 종류입니다. 강조의 정도 차이가 있습니다. | +| customWidth? | string
(default: 100%) | Divider 컴포넌트의 길이입니다. | +| customHeight? | string
(default: 1px) | Divider 컴포넌트의 두께입니다. | +| css? | CSSProp | Divider 컴포넌트에 적용할 CSS 스타일입니다. | ### Example ```jsx - + ``` +
+ ## Heading HTML heading 태그를 사용하는 컴포넌트입니다. ### Props -| props | value | description | -| --------- | ------------------------------------- | ------------------------------------------- | -| children? | ReactNode | Heading 컴포넌트의 자식 컴포넌트입니다. | -| size? | `xs`, `sm`, `md`, `lg`, `xl` | Heading 컴포넌트의 폰트 크기입니다. | -| weight? | `light`, `regular`, `bold` | Heading 컴포넌트의 폰트 가중치입니다. | -| css? | CSSProp | Heading 컴포넌트에 적용할 CSS 스타일입니다. | -| as? | `h1` ,`h2`, `h3`
(default: `h1`) | Heading 컴포넌트의 HTML 태그입니다. | -| css? | CSSProp | Heading 컴포넌트에 적용할 CSS 스타일입니다. | +| props | value | description | +| --------- | ----------------------------- | ------------------------------------------- | +| children? | ReactNode | Heading 컴포넌트의 자식 컴포넌트입니다. | +| as? | h1 ,h2, h3
(default: h1) | Heading 컴포넌트의 HTML 태그입니다. | +| size? | xs, sm, md, lg, xl | Heading 컴포넌트의 폰트 크기입니다. | +| weight? | light, regular, bold | Heading 컴포넌트의 폰트 가중치입니다. | +| css? | CSSProp | Heading 컴포넌트에 적용할 CSS 스타일입니다. | ### Example @@ -174,20 +184,53 @@ HTML heading 태그를 사용하는 컴포넌트입니다. 로망오우타해황 ``` +
+ +## Input + +인풋 컴포넌트입니다. + +### Props + +| props | value | description | +| ------------- | --------- | --------------------------------------------- | +| customWidth? | string | Input 컴포넌트의 너비값입니다. | +| minWidth? | string | Input 컴포넌트의 최소 너비값입니다. | +| isError? | boolean | Input value에 에러가 있는지 여부입니다. | +| rightIcon? | ReactNode | Input 컴포넌트 오른쪽에 위치할 아이콘입니다. | +| errorMessage? | string | isError가 true일 때 보여줄 에러 메시지입니다. | + +### Example + +```jsx + + + + + } +/> +``` + +
+ ## Link -다른 URL로 연결하는 컴포넌트입니다. -`react-router-dom`과 함께 사용할 수 있습니다. +다른 URL로 연결하는 컴포넌트입니다. `react-router-dom`과 함께 사용할 수 있습니다. ### Props -| props | value | description | -| ----------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | -| isExternal? | boolean
(default: false) | Link 컴포넌트의 링크 클릭 시 새로운 탭으로 열도록 선택할 수 있습니다. | -| block | boolean
(default: false) | Link 컴포넌트의 디스플레이 속성이 block인지 선택할 수 있습니다. | -| css? | CSSProp | Link 컴포넌트에 적용할 CSS 스타일입니다. | -| as? | `a` ,`Link(react-router-dom의 Link)`, `NavLink(react-router-dom의 NavLink)`
(default: `a`) | Link 컴포넌트로 사용할 HTML 태그 또는 외부 링크 컴포넌트입니다. | -| css? | CSSProp | Link 컴포넌트에 적용할 CSS 스타일입니다. | +| props | value | description | +| ----------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | +| as? | a, Link(react-router-dom의 Link), NavLink(react-router-dom의 NavLink)
(default: a) | Link 컴포넌트로 사용할 HTML 태그 또는 외부 링크 컴포넌트입니다. | +| isExternal? | boolean
(default: false) | Link 컴포넌트의 링크 클릭 시 새로운 탭으로 열도록 선택할 수 있습니다. | +| block | boolean
(default: false) | Link 컴포넌트의 디스플레이 속성이 block인지 선택할 수 있습니다. | +| css? | CSSProp | Link 컴포넌트에 적용할 CSS 스타일입니다. | ### Example @@ -203,16 +246,18 @@ import {Link as RouterLink, NavLink} from 'react-router-dom' 링크로 이동합니다. ``` +
+ ## Spacing 화면 구역을 나누는 여백 컴포넌트입니다. ### Props -| props | value | description | -| ---------- | ---------------------------------------------------- | ------------------------------ | -| direction? | `vertical`, `horizontal`
(default: `vertical`) | Spacing 컴포넌트의 방향입니다. | -| size | number | Spacing 컴포넌트의 크기입니다. | +| props | value | description | +| ---------- | ---------------------------------------------- | ------------------------------ | +| direction? | vertical, horizontal
(default: vertical) | Spacing 컴포넌트의 방향입니다. | +| size | number | Spacing 컴포넌트의 크기입니다. | ### Example @@ -221,22 +266,24 @@ import {Link as RouterLink, NavLink} from 'react-router-dom' ``` +
+ ## Text 텍스트 컴포넌트입니다. ### Props -| props | value | description | -| ----------- | -------------------------------------------------- | ---------------------------------------- | -| children? | ReactNode | Text 컴포넌트의 자식 컴포넌트입니다. | -| size? | `xs`, `sm`, `md`, `lg`, `xl`
(default: `md`) | Text 컴포넌트의 폰트 크기입니다. | -| weight? | `light`, `regular`, `bold`
(default: regular) | Text 컴포넌트의 폰트 가중치입니다. | -| lineHeight? | `xs`,`sm`, `md`, `xl`
(default: `md`) | Text 컴포넌트의 텍스트 높이입니다. | -| color? | CSSProperties['color']
(default: ‘#232527’) | Text 컴포넌트의 텍스트 색상입니다. | -| align? | `left`, `center`, `right`
(default: `left`) | Text 컴포넌트의 텍스트 정렬입니다. | -| css? | CSSProp | Text 컴포넌트에 적용할 CSS 스타일입니다. | -| as? | `p` ,`span`
(default: `p`) | Text 컴포넌트의 HTML 태그입니다. | +| props | value | description | +| ----------- | ------------------------------------------------- | ---------------------------------------- | +| children? | ReactNode | Text 컴포넌트의 자식 컴포넌트입니다. | +| as? | p, span
(default: p) | Text 컴포넌트의 HTML 태그입니다. | +| size? | xs, sm, md, lg, xl
(default: md) | Text 컴포넌트의 폰트 크기입니다. | +| weight? | light, regular, bold
(default: regular) | Text 컴포넌트의 폰트 가중치입니다. | +| lineHeight? | xs, sm, md, lg, xl
(default: md) | Text 컴포넌트의 텍스트 높이입니다. | +| color? | CSSProperties['color']
(default: ‘#232527’) | Text 컴포넌트의 텍스트 색상입니다. | +| align? | left, center, right
(default: left) | Text 컴포넌트의 텍스트 정렬입니다. | +| css? | CSSProp | Text 컴포넌트에 적용할 CSS 스타일입니다. | ### Example @@ -247,15 +294,17 @@ import {Link as RouterLink, NavLink} from 'react-router-dom' 로망오우타해황 ``` +
+ ## Textarea 멀티라인 텍스트 입력 컴포넌트입니다. ### Props -| props | value | description | -| ------- | ----------------------------------------------------------------- | ------------------------------------------------ | -| resize? | `both`, `horizontal`, `vertical`, `none`
(default: `both`) | Textarea 컴포넌트의 크기 재조정 방향 설정입니다. | +| props | value | description | +| ------- | ------------------------------------------------------ | ------------------------------------------------ | +| resize? | both, horizontal, vertical, none
(default: both) | Textarea 컴포넌트의 크기 재조정 방향 설정입니다. | ### Example diff --git a/src/Input/Input.stories.tsx b/src/Input/Input.stories.tsx new file mode 100644 index 0000000..eca0da5 --- /dev/null +++ b/src/Input/Input.stories.tsx @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import Input from './Input'; + +const meta: Meta = { + title: 'Input', + component: Input, + argTypes: { + rightIcon: { + control: { type: 'boolean' }, + mapping: { false: '', true: '🔎' }, + }, + }, + args: { + customWidth: '300px', + isError: false, + rightIcon: false, + errorMessage: '', + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const WithPlaceholder: Story = { + args: { + placeholder: '상품 이름을 검색하세요.', + }, +}; + +export const WithIcon: Story = { + args: { + placeholder: '상품 이름을 검색하세요.', + rightIcon: true, + }, +}; + +export const Error: Story = { + args: { + isError: true, + errorMessage: '10글자 이내로 입력해주세요.', + }, +}; + +export const Disabled: Story = { + render: () => , +}; diff --git a/src/Input/Input.tsx b/src/Input/Input.tsx new file mode 100644 index 0000000..0d361a2 --- /dev/null +++ b/src/Input/Input.tsx @@ -0,0 +1,98 @@ +import type { ComponentPropsWithRef, ForwardedRef, ReactNode } from 'react'; +import { forwardRef } from 'react'; +import styled from 'styled-components'; + +import Text from '../Text'; + +export interface InputProps extends ComponentPropsWithRef<'input'> { + /** + * Input 컴포넌트의 너비값입니다. + */ + customWidth?: string; + /** + * Input 컴포넌트의 최소 너비값입니다. + */ + minWidth?: string; + /** + * Input value에 에러가 있는지 여부입니다. + */ + isError?: boolean; + /** + * Input 컴포넌트 오른쪽에 위치할 아이콘입니다. + */ + rightIcon?: ReactNode; + /** + * isError가 true일 때 보여줄 에러 메시지입니다. + */ + errorMessage?: string; +} + +const Input = forwardRef( + ( + { customWidth = '300px', minWidth, isError = false, rightIcon, errorMessage, ...props }: InputProps, + ref: ForwardedRef + ) => { + return ( + <> + + + {rightIcon && {rightIcon}} + + {isError && {errorMessage}} + + ); + } +); + +Input.displayName = 'Input'; + +export default Input; + +type InputContainerStyleProps = Pick; +type CustomInputStyleProps = Pick; + +const InputContainer = styled.div` + position: relative; + min-width: ${({ minWidth }) => minWidth ?? 0}; + max-width: ${({ customWidth }) => customWidth}; + text-align: center; +`; + +const CustomInput = styled.input` + width: 100%; + height: 40px; + padding: 10px 0 10px 12px; + color: ${({ isError, theme }) => (isError ? theme.colors.error : theme.textColors.default)}; + border: 1px solid ${({ isError, theme }) => (isError ? theme.colors.error : theme.borderColors.default)}; + border-radius: 5px; + + &:focus { + border: 2px solid ${({ isError, theme }) => (isError ? theme.colors.error : theme.borderColors.strong)}; + outline: none; + } + + &:disabled { + border: 1px solid ${({ theme }) => theme.borderColors.disabled}; + background: ${({ theme }) => theme.colors.gray1}; + } + + &::placeholder { + color: ${({ theme }) => theme.textColors.disabled}; + font-size: ${({ theme }) => theme.fontSizes.sm}; + } +`; + +const IconWrapper = styled.div` + position: absolute; + top: 0; + right: 0; + display: flex; + align-items: center; + height: 100%; + margin-right: 8px; +`; + +const ErrorMessage = styled(Text)` + color: ${({ theme }) => theme.colors.error}; + font-size: ${({ theme }) => theme.fontSizes.xs}; +`; diff --git a/src/Input/index.ts b/src/Input/index.ts new file mode 100644 index 0000000..c90e5ad --- /dev/null +++ b/src/Input/index.ts @@ -0,0 +1,5 @@ +import Input from './Input'; + +export type { InputProps } from './Input'; + +export default Input; diff --git a/src/index.ts b/src/index.ts index c847503..cac763d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,3 +14,4 @@ export { default as Link } from './Link'; export { default as Spacing } from './Spacing'; export { default as Text } from './Text'; export { default as Textarea } from './Textarea'; +export { default as Input } from './Input';