Spaces:
Sleeping
Sleeping
File size: 3,858 Bytes
8421ec4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import React, { useState, useRef, useEffect } from 'react';
interface ChatInputProps {
onSendMessage: (content: string) => void;
isSending: boolean;
disabled: boolean;
}
const ChatInput: React.FC<ChatInputProps> = ({ onSendMessage, isSending, disabled }) => {
const [message, setMessage] = useState('');
const textareaRef = useRef<HTMLTextAreaElement>(null);
// Auto-resize textarea
useEffect(() => {
if (textareaRef.current) {
textareaRef.current.style.height = 'auto';
textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 200)}px`;
}
}, [message]);
const handleSubmit = () => {
const trimmed = message.trim();
if (trimmed && !isSending && !disabled) {
onSendMessage(trimmed);
setMessage('');
if (textareaRef.current) {
textareaRef.current.style.height = 'auto';
}
}
};
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSubmit();
}
};
return (
<div className="border-t border-gray-200 bg-white p-4">
<div className="max-w-4xl mx-auto">
<div className="relative flex items-end gap-3 bg-gray-50 border border-gray-200 rounded-2xl p-2 focus-within:border-indigo-300 focus-within:ring-2 focus-within:ring-indigo-100 transition-all">
<textarea
ref={textareaRef}
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyDown={handleKeyDown}
placeholder={disabled ? "Select or create a chat to start..." : "Ask a question..."}
disabled={disabled || isSending}
rows={1}
className="flex-1 resize-none bg-transparent px-3 py-2 text-gray-800 placeholder-gray-400 focus:outline-none text-sm leading-relaxed max-h-[200px] disabled:cursor-not-allowed"
/>
<button
onClick={onsubmit}
disabled={!message.trim() || isSending || disabled}
className={`flex-shrink-0 p-3 rounded-xl transition-all duration-200 ${message.trim() && !isSending && !disabled
? 'bg-gradient-to-r from-indigo-600 to-purple-600 text-white shadow-lg hover:shadow-indigo-500/30 hover:scale-105 active:scale-95'
: 'bg-gray-200 text-gray-400 cursor-not-allowed'
}`}
>
{isSending ? (
<svg className="w-5 h-5 animate-spin" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
) : (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
</svg>
)}
</button>
</div>
<p className="text-xs text-gray-400 text-center mt-2">
Press Enter to send, Shift+Enter for new line
</p>
</div>
</div>
);
};
export default ChatInput;
|