diff --git a/joi/src/core/TextArea/TextArea.test.tsx b/joi/src/core/TextArea/TextArea.test.tsx
index 8bc64010f..e29eed5d0 100644
--- a/joi/src/core/TextArea/TextArea.test.tsx
+++ b/joi/src/core/TextArea/TextArea.test.tsx
@@ -1,9 +1,8 @@
import React from 'react'
-import { render, screen } from '@testing-library/react'
+import { render, screen, act } from '@testing-library/react'
import '@testing-library/jest-dom'
import { TextArea } from './index'
-// Mock the styles import
jest.mock('./styles.scss', () => ({}))
describe('@joi/core/TextArea', () => {
@@ -31,4 +30,40 @@ describe('@joi/core/TextArea', () => {
const textareaElement = screen.getByTestId('custom-textarea')
expect(textareaElement).toHaveAttribute('rows', '5')
})
+
+ it('should auto resize the textarea based on minResize', () => {
+ render()
+
+ const textarea = screen.getByRole('textbox') as HTMLTextAreaElement
+
+ Object.defineProperty(textarea, 'scrollHeight', {
+ value: 20,
+ writable: true,
+ })
+
+ act(() => {
+ textarea.value = 'Short text'
+ textarea.dispatchEvent(new Event('input', { bubbles: true }))
+ })
+
+ expect(textarea.style.height).toBe('10px')
+ })
+
+ it('should auto resize the textarea based on maxResize', () => {
+ render()
+
+ const textarea = screen.getByRole('textbox') as HTMLTextAreaElement
+
+ Object.defineProperty(textarea, 'scrollHeight', {
+ value: 100,
+ writable: true,
+ })
+
+ act(() => {
+ textarea.value = 'A very long text that should exceed max height'
+ textarea.dispatchEvent(new Event('input', { bubbles: true }))
+ })
+
+ expect(textarea.style.height).toBe('40px')
+ })
})
diff --git a/joi/src/core/TextArea/index.tsx b/joi/src/core/TextArea/index.tsx
index 33d6744ad..6807178ff 100644
--- a/joi/src/core/TextArea/index.tsx
+++ b/joi/src/core/TextArea/index.tsx
@@ -1,19 +1,41 @@
-import React, { ReactNode, forwardRef } from 'react'
+import React, { forwardRef, useRef, useEffect } from 'react'
import { twMerge } from 'tailwind-merge'
import './styles.scss'
-import { ScrollArea } from '../ScrollArea'
+
+type ResizeProps = {
+ autoResize?: boolean
+ minResize?: number
+ maxResize?: number
+}
export interface TextAreaProps
- extends React.TextareaHTMLAttributes {}
+ extends ResizeProps,
+ React.TextareaHTMLAttributes {}
const TextArea = forwardRef(
- ({ className, ...props }, ref) => {
+ (
+ { autoResize, minResize = 80, maxResize = 250, className, ...props },
+ ref
+ ) => {
+ const textareaRef = useRef(null)
+
+ useEffect(() => {
+ if (autoResize && textareaRef.current) {
+ const textarea = textareaRef.current
+ textarea.style.height = 'auto'
+ const scrollHeight = textarea.scrollHeight
+ const newHeight = Math.min(maxResize, Math.max(minResize, scrollHeight))
+ textarea.style.height = `${newHeight}px`
+ textarea.style.overflow = newHeight >= maxResize ? 'auto' : 'hidden'
+ }
+ }, [props.value, autoResize, minResize, maxResize])
+
return (
diff --git a/web/containers/ModelConfigInput/index.tsx b/web/containers/ModelConfigInput/index.tsx
index 840e2378e..f0e6ea1f2 100644
--- a/web/containers/ModelConfigInput/index.tsx
+++ b/web/containers/ModelConfigInput/index.tsx
@@ -36,7 +36,7 @@ const ModelConfigInput = ({