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;