1
+ import { useCallback , useEffect } from "react" ;
1
2
import useMessages , { type IMessage } from "../../../hooks/useMessages" ;
2
3
3
4
interface Props {
4
5
setMessages : React . Dispatch < React . SetStateAction < IMessage [ ] > > ;
5
6
isLoading : boolean ;
6
7
setIsLoading : React . Dispatch < React . SetStateAction < boolean > > ;
7
8
value : string ;
8
- inputRef : React . RefObject < HTMLInputElement | null > ;
9
- onChange : ( e : React . ChangeEvent < HTMLInputElement > ) => void ;
9
+ inputRef : React . RefObject < HTMLTextAreaElement | null > ;
10
+ onChange : ( e : React . ChangeEvent < HTMLTextAreaElement > ) => void ;
10
11
}
11
12
12
13
export default function InputField ( {
@@ -26,7 +27,9 @@ export default function InputField({
26
27
const userMessageId = Date . now ( ) . toString ( ) ;
27
28
const botMessageId = ( Date . now ( ) + 1 ) . toString ( ) ;
28
29
29
- onChange ( { target : { value : "" } } as React . ChangeEvent < HTMLInputElement > ) ;
30
+ onChange ( {
31
+ target : { value : "" } ,
32
+ } as React . ChangeEvent < HTMLTextAreaElement > ) ;
30
33
setIsLoading ( true ) ;
31
34
32
35
// Add user message
@@ -60,10 +63,8 @@ export default function InputField({
60
63
// Update only the bot's message
61
64
setMessages ( ( prev ) =>
62
65
prev . map ( ( msg ) =>
63
- msg . messageId === botMessageId
64
- ? { ...msg , content : fullText }
65
- : msg ,
66
- ) ,
66
+ msg . messageId === botMessageId ? { ...msg , content : fullText } : msg
67
+ )
67
68
) ;
68
69
}
69
70
} catch ( error ) {
@@ -75,33 +76,46 @@ export default function InputField({
75
76
...msg ,
76
77
content : "Sorry, I encountered an error. Please try again." ,
77
78
}
78
- : msg ,
79
- ) ,
79
+ : msg
80
+ )
80
81
) ;
81
82
} finally {
82
83
setIsLoading ( false ) ;
83
84
}
84
85
} ;
85
86
87
+ const resizeTextArea = useCallback ( ( ) => {
88
+ const inputElement = inputRef . current ;
89
+ if ( inputElement !== null ) {
90
+ inputElement . style . height = "auto" ;
91
+ inputElement . style . height = `${ inputElement . scrollHeight } px` ;
92
+ }
93
+ } , [ inputRef ] ) ;
94
+
95
+ useEffect ( ( ) => {
96
+ resizeTextArea ( ) ;
97
+ } , [ value , resizeTextArea ] ) ;
98
+
86
99
return (
87
- < div className = "flex gap-2 mt-4 h-11 items-stretch mx-auto max-w-[700px]" >
88
- < input
89
- type = "text"
100
+ < div className = "flex gap-2 mt-4 justify-center items-center mx-auto max-w-[700px]" >
101
+ < textarea
90
102
value = { value }
91
103
onChange = { onChange }
104
+ onInput = { resizeTextArea }
92
105
onKeyDown = { ( e ) => {
93
106
if ( e . key === "Enter" ) {
94
107
e . preventDefault ( ) ;
95
108
handleSend ( ) ;
96
109
}
97
110
} }
98
- className = "w-full p-3 border-1 border-[#ddd] rounded-md box-border transition-colors duration-300 focus:outline-0 focus:border-[#4a90e2] focus:shadow-[0_0_0_2px_rgba(74,144,226,0.2)]"
111
+ rows = { 1 }
112
+ className = "overflow-auto resize-none max-h-22 w-full px-3 py-2 border-1 border-[#ddd] rounded-md box-border transition-colors duration-300 focus:outline-0 focus:border-[#4a90e2] focus:shadow-[0_0_0_2px_rgba(74,144,226,0.2)]"
99
113
placeholder = "Type your message here..."
100
114
disabled = { isLoading }
101
115
ref = { inputRef }
102
116
/>
103
117
< button
104
- className = "px-6 bg-[#1F584F] hover:bg-[#4F8B82] text-white rounded-md cursor-pointer transition-color duration-300"
118
+ className = "px-6 h-10 bg-[#1F584F] hover:bg-[#4F8B82] text-white rounded-md cursor-pointer transition-color duration-300"
105
119
onClick = { handleSend }
106
120
disabled = { isLoading || ! value . trim ( ) }
107
121
>
0 commit comments