From ec7df50064593ac6e1080db03df71b3f5a40da9f Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sat, 21 Mar 2026 16:49:46 -0400 Subject: [PATCH] feat(flowpilot): add always-visible message bar, remove hidden free text escape hatch Co-Authored-By: Claude Opus 4.6 (1M context) --- .../flowpilot/FlowPilotMessageBar.tsx | 75 +++++++++++++++++++ .../components/flowpilot/FlowPilotSession.tsx | 10 +++ .../flowpilot/FlowPilotStepCard.tsx | 52 ------------- 3 files changed, 85 insertions(+), 52 deletions(-) create mode 100644 frontend/src/components/flowpilot/FlowPilotMessageBar.tsx diff --git a/frontend/src/components/flowpilot/FlowPilotMessageBar.tsx b/frontend/src/components/flowpilot/FlowPilotMessageBar.tsx new file mode 100644 index 00000000..efe2e480 --- /dev/null +++ b/frontend/src/components/flowpilot/FlowPilotMessageBar.tsx @@ -0,0 +1,75 @@ +import { useState, useRef, useCallback } from 'react' +import { Send } from 'lucide-react' +import { cn } from '@/lib/utils' +import type { StepResponseRequest } from '@/types/ai-session' + +interface FlowPilotMessageBarProps { + onRespond: (response: StepResponseRequest) => void + disabled?: boolean + isProcessing?: boolean +} + +export function FlowPilotMessageBar({ onRespond, disabled = false, isProcessing = false }: FlowPilotMessageBarProps) { + const [message, setMessage] = useState('') + const textareaRef = useRef(null) + + const isDisabled = disabled || isProcessing + + const handleSubmit = useCallback(() => { + const trimmed = message.trim() + if (!trimmed || isDisabled) return + onRespond({ free_text_input: trimmed }) + setMessage('') + if (textareaRef.current) { + textareaRef.current.style.height = 'auto' + } + }, [message, isDisabled, onRespond]) + + const handleKeyDown = useCallback((e: React.KeyboardEvent) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault() + handleSubmit() + } + }, [handleSubmit]) + + const handleInput = useCallback((e: React.ChangeEvent) => { + setMessage(e.target.value) + const textarea = e.target + textarea.style.height = 'auto' + textarea.style.height = `${Math.min(textarea.scrollHeight, 120)}px` + }, []) + + return ( +
+
+