diff --git a/.changeset/shiny-dogs-hope.md b/.changeset/shiny-dogs-hope.md new file mode 100644 index 0000000..067fa90 --- /dev/null +++ b/.changeset/shiny-dogs-hope.md @@ -0,0 +1,5 @@ +--- +'@sopt-makers/ui': patch +--- + +[UI] Textarea maxLength 초과시 error 뜨도록 변경 diff --git a/packages/ui/Input/TextArea.tsx b/packages/ui/Input/TextArea.tsx index 2300e4c..10ae69d 100644 --- a/packages/ui/Input/TextArea.tsx +++ b/packages/ui/Input/TextArea.tsx @@ -5,8 +5,8 @@ import SendIcon from './icons/SendIcon'; interface TextAreaProps extends Omit, 'value'> { className?: string; - topAddon?: React.ReactNode | { labelText?: string; descriptionText?: string; }; - rightAddon?: React.ReactNode | { buttonContent?: React.ReactNode; onClick: () => void; }; // ReactNode로 버튼을 전달하면 disabled 및 onKeyDown 직접처리 필요 + topAddon?: React.ReactNode | { labelText?: string; descriptionText?: string }; + rightAddon?: React.ReactNode | { buttonContent?: React.ReactNode; onClick: () => void }; // ReactNode로 버튼을 전달하면 disabled 및 onKeyDown 직접처리 필요 isError?: boolean; validationFn?: (input: string) => boolean; // isError가 없을 때만 적용 @@ -63,7 +63,7 @@ function TextArea(props: TextAreaProps) { e.target.style.height = '1px'; e.target.style.height = `${e.target.scrollHeight}px`; } - } + }; const handleKeyPress = (event: React.KeyboardEvent) => { if (!disableEnterSubmit && event.key === 'Enter' && !event.shiftKey) { @@ -88,7 +88,13 @@ function TextArea(props: TextAreaProps) { const submitButton = useMemo(() => { if (rightAddon && typeof rightAddon === 'object' && 'onClick' in rightAddon) { return ( - @@ -96,19 +102,24 @@ function TextArea(props: TextAreaProps) { } }, [rightAddon, isSubmitDisabled]); - const handleFocus = () => { + const handleFocus = (e: React.FocusEvent) => { setIsFocused(true); - } + inputProps.onFocus && inputProps.onFocus(e); + }; - const handleBlur = () => { + const handleBlur = (e: React.FocusEvent) => { setIsFocused(false); - } + inputProps.onBlur && inputProps.onBlur(e); + }; const requiredEl = required ? * : null; const descriptionEl = descriptionText ?

{descriptionText}

: null; const labelEl = labelText ? ( ) : ( @@ -129,13 +140,17 @@ function TextArea(props: TextAreaProps) { onFocus={handleFocus} onKeyDown={inputProps.onKeyDown ?? handleKeyPress} rows={1} - style={{ ...inputProps.style, height: fixedHeight ? `${fixedHeight}px` : 'auto', maxHeight: `${maxHeight}px` }} + style={{ + ...inputProps.style, + height: fixedHeight ? `${fixedHeight}px` : 'auto', + maxHeight: `${maxHeight}px`, + }} value={value} /> {isValidElement(rightAddon) ? rightAddon : submitButton} - {(hasError || maxLength) ? ( + {hasError || maxLength ? (
{hasError ? (
@@ -147,7 +162,7 @@ function TextArea(props: TextAreaProps) { )} {maxLength ? ( -

+

maxLength ? S.maxCount : ''}`}> {value.length}/{maxLength}

) : null} @@ -157,4 +172,4 @@ function TextArea(props: TextAreaProps) { ); } -export default TextArea; \ No newline at end of file +export default TextArea;