From 37b6b9b0471acce896638d12394c0847408254db Mon Sep 17 00:00:00 2001 From: HyeongKyeom Kim <97586683+Brokyeom@users.noreply.github.com> Date: Sun, 3 Nov 2024 01:22:35 +0900 Subject: [PATCH] =?UTF-8?q?refactor(ui):=20TextField=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8,=20FieldBox=EB=A5=BC=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=9C=20=ED=98=95=ED=83=9C=EB=A1=9C=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81.=20(#195)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: FieldBox 기반의 컴포넌트로 리팩토링 * docs: TextField Storybook 문서 수정 * fix: FieldBox.Label Optional prop으로 수정 * cs * feat: add bottomAddon prop. --- .changeset/tiny-days-hammer.md | 5 ++ apps/docs/src/stories/TextField.stories.tsx | 18 ++++---- packages/ui/FieldBox/components/Label.tsx | 8 ++-- packages/ui/Input/TextField.tsx | 51 ++++++++++++++++----- 4 files changed, 57 insertions(+), 25 deletions(-) create mode 100644 .changeset/tiny-days-hammer.md diff --git a/.changeset/tiny-days-hammer.md b/.changeset/tiny-days-hammer.md new file mode 100644 index 0000000..39fc8d4 --- /dev/null +++ b/.changeset/tiny-days-hammer.md @@ -0,0 +1,5 @@ +--- +'@sopt-makers/ui': patch +--- + +TextField 컴포넌트를 FieldBox 기반으로 수정합니다. diff --git a/apps/docs/src/stories/TextField.stories.tsx b/apps/docs/src/stories/TextField.stories.tsx index 3be37ca..491fd47 100644 --- a/apps/docs/src/stories/TextField.stories.tsx +++ b/apps/docs/src/stories/TextField.stories.tsx @@ -15,22 +15,22 @@ const useTextField = (props: TextFieldProps) => { const handleTextChange = (e: ChangeEvent) => { setText(e.target.value); - } + }; - return {...props} value={text} onChange={handleTextChange} /> -} + return {...props} value={text} onChange={handleTextChange} />; +}; export default { title: 'Components/Input/TextField', component: useTextField, tags: ['autodocs'], args: { - style: { width: '335px' } + style: { width: '335px' }, }, argTypes: { - style: { control: false } - } -} + style: { control: false }, + }, +}; export const Default: StoryObj = { args: { @@ -52,7 +52,7 @@ export const NoLabel: StoryObj = { placeholder: 'Placeholder...', isError: false, errorMessage: 'error message', - required: true, + required: false, readOnly: false, disabled: false, }, @@ -136,4 +136,4 @@ export const Error: StoryObj = { readOnly: false, disabled: false, }, -}; \ No newline at end of file +}; diff --git a/packages/ui/FieldBox/components/Label.tsx b/packages/ui/FieldBox/components/Label.tsx index 587bc85..dbff8ce 100644 --- a/packages/ui/FieldBox/components/Label.tsx +++ b/packages/ui/FieldBox/components/Label.tsx @@ -3,13 +3,13 @@ import { forwardRef } from 'react'; import { requiredMarkStyle, TopAddonDescriptionStyle, TopAddonLabelStyle } from '../style.css'; export interface FieldBoxLabelProps extends HTMLAttributes { - label: string; - description: string; - required: boolean; + label?: string; + description?: string; + required?: boolean; } export const FieldBoxLabel = forwardRef((props, forwardedRef) => { - const { required, label, description } = props; + const { required = false, label, description } = props; return (
diff --git a/packages/ui/Input/TextField.tsx b/packages/ui/Input/TextField.tsx index e03ad8e..186e813 100644 --- a/packages/ui/Input/TextField.tsx +++ b/packages/ui/Input/TextField.tsx @@ -1,11 +1,14 @@ -import { type InputHTMLAttributes } from 'react'; +import type { ReactNode, InputHTMLAttributes } from 'react'; +import { FieldBox } from 'index'; import * as S from './style.css'; -import AlertCircleIcon from './icons/AlertCircleIcon'; interface TextFieldProps extends Omit, 'value'> { className?: string; + topAddon?: ReactNode; + bottomAddon?: ReactNode; labelText?: string; descriptionText?: string; + required?: boolean; errorMessage?: string; value: T; // isError -> validationFn 순서로 적용 @@ -14,23 +17,47 @@ interface TextFieldProps extends Omit, } function TextField(props: TextFieldProps) { - const { className, labelText, descriptionText, errorMessage, value, isError, validationFn, ...inputProps } = props; + const { + className, + topAddon, + bottomAddon, + labelText, + descriptionText, + required, + errorMessage, + value, + isError, + validationFn, + ...inputProps + } = props; const hasError = () => { if (inputProps.disabled || inputProps.readOnly) return false; if (isError !== undefined) return isError; if (validationFn && !validationFn(value)) return true; return false; - } + }; - const required = inputProps.required ? * : null; - const description = descriptionText ?

{descriptionText}

: null; - const input = ; - - return
- {labelText ? :
{description}{input}
} - {hasError() ?

{errorMessage ?? 'error'}

: null} -
+ return ( + : null} + rightAddon={bottomAddon} + /> + } + className={className} + topAddon={ + labelText || descriptionText ? ( + + ) : ( + topAddon + ) + } + > + + + ); } export default TextField;