feat: implement auto-resizing textarea in ChatInput component

This commit is contained in:
ecwu
2025-01-26 21:18:29 +00:00
parent 55e8186479
commit d51c283e55

View File

@@ -6,20 +6,55 @@ interface ChatInputProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {} extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
const ChatInput = React.forwardRef<HTMLTextAreaElement, ChatInputProps>( const ChatInput = React.forwardRef<HTMLTextAreaElement, ChatInputProps>(
({ className, ...props }, ref) => ( ({ className, onChange, ...props }, ref) => {
<Textarea const internalRef = React.useRef<HTMLTextAreaElement>(null);
mockOnChange={false}
autoComplete="off" // Combine the forwarded ref with the internal ref
ref={ref} React.useImperativeHandle(
name="message" ref,
className={cn( () => internalRef.current as HTMLTextAreaElement
"max-h-12 px-4 py-3 bg-background text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 w-full rounded-md flex items-center h-16 resize-none", );
className
)} // Function to adjust the height of the textarea
{...props} const adjustHeight = () => {
/> if (internalRef.current) {
) // Reset the height to auto to calculate the new height
internalRef.current.style.height = "auto";
// Set the height to the scrollHeight (content height)
internalRef.current.style.height = `${internalRef.current.scrollHeight}px`;
}
};
// Adjust height whenever the content changes
React.useEffect(() => {
adjustHeight();
}, [props.value]); // Run whenever the value changes
// Handle input changes
const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
adjustHeight();
if (onChange) {
onChange(e); // Call the passed onChange handler
}
};
return (
<Textarea
mockOnChange={false}
autoComplete="off"
ref={internalRef}
name="message"
className={cn(
"max-h-48 px-4 py-3 bg-background text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 w-full rounded-md flex items-center resize-none",
className
)}
onChange={handleInput}
{...props}
/>
);
}
); );
ChatInput.displayName = "ChatInput"; ChatInput.displayName = "ChatInput";
export { ChatInput }; export { ChatInput };