diff --git a/frontend/src/components/tasks/TaskFollowUpSection.tsx b/frontend/src/components/tasks/TaskFollowUpSection.tsx
index 0624f614..5620f44e 100644
--- a/frontend/src/components/tasks/TaskFollowUpSection.tsx
+++ b/frontend/src/components/tasks/TaskFollowUpSection.tsx
@@ -102,6 +102,7 @@ export function TaskFollowUpSection() {
disabled={!canSendFollowUp}
projectId={projectId}
rows={1}
+ maxRows={6}
/>
diff --git a/frontend/src/components/ui/auto-expanding-textarea.tsx b/frontend/src/components/ui/auto-expanding-textarea.tsx
new file mode 100644
index 00000000..20d5d8c9
--- /dev/null
+++ b/frontend/src/components/ui/auto-expanding-textarea.tsx
@@ -0,0 +1,70 @@
+import * as React from 'react';
+import { cn } from '@/lib/utils';
+
+interface AutoExpandingTextareaProps extends React.ComponentProps<'textarea'> {
+ maxRows?: number;
+}
+
+const AutoExpandingTextarea = React.forwardRef<
+ HTMLTextAreaElement,
+ AutoExpandingTextareaProps
+>(({ className, maxRows = 10, ...props }, ref) => {
+ const internalRef = React.useRef(null);
+
+ // Get the actual ref to use
+ const textareaRef = ref || internalRef;
+
+ const adjustHeight = React.useCallback(() => {
+ const textarea = (textareaRef as React.RefObject)
+ .current;
+ if (!textarea) return;
+
+ // Reset height to auto to get the natural height
+ textarea.style.height = 'auto';
+
+ // Calculate line height
+ const style = window.getComputedStyle(textarea);
+ const lineHeight = parseInt(style.lineHeight) || 20;
+ const paddingTop = parseInt(style.paddingTop) || 0;
+ const paddingBottom = parseInt(style.paddingBottom) || 0;
+
+ // Calculate max height based on maxRows
+ const maxHeight = lineHeight * maxRows + paddingTop + paddingBottom;
+
+ // Set the height to scrollHeight, but cap at maxHeight
+ const newHeight = Math.min(textarea.scrollHeight, maxHeight);
+ textarea.style.height = `${newHeight}px`;
+ }, [maxRows]);
+
+ // Adjust height on mount and when content changes
+ React.useEffect(() => {
+ adjustHeight();
+ }, [adjustHeight, props.value]);
+
+ // Adjust height on input
+ const handleInput = React.useCallback(
+ (e: React.FormEvent) => {
+ adjustHeight();
+ if (props.onInput) {
+ props.onInput(e);
+ }
+ },
+ [adjustHeight, props.onInput]
+ );
+
+ return (
+
+ );
+});
+
+AutoExpandingTextarea.displayName = 'AutoExpandingTextarea';
+
+export { AutoExpandingTextarea };
diff --git a/frontend/src/components/ui/file-search-textarea.tsx b/frontend/src/components/ui/file-search-textarea.tsx
index 185058c4..35965298 100644
--- a/frontend/src/components/ui/file-search-textarea.tsx
+++ b/frontend/src/components/ui/file-search-textarea.tsx
@@ -1,6 +1,6 @@
import { KeyboardEvent, useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
-import { Textarea } from '@/components/ui/textarea';
+import { AutoExpandingTextarea } from '@/components/ui/auto-expanding-textarea';
import { projectsApi } from '@/lib/api';
interface FileSearchResult {
@@ -17,6 +17,7 @@ interface FileSearchTextareaProps {
className?: string;
projectId?: string;
onKeyDown?: (e: React.KeyboardEvent) => void;
+ maxRows?: number;
}
export function FileSearchTextarea({
@@ -28,6 +29,7 @@ export function FileSearchTextarea({
className,
projectId,
onKeyDown,
+ maxRows = 10,
}: FileSearchTextareaProps) {
const [searchQuery, setSearchQuery] = useState('');
const [searchResults, setSearchResults] = useState([]);
@@ -230,7 +232,7 @@ export function FileSearchTextarea({
-
{showDropdown &&