- Replace all rgba(6,182,212,...) cyan focus borders and accents with rgba(249,115,22,...) ember orange across 21+ component files - Remove all var(--glass-border) references (undefined variable) with var(--color-border-default) across 24 files - Remove deprecated blur orbs and glass-morphism effects from SurveyPage, SurveyThankYouPage, and LoginPage - Migrate landing.css from hardcoded hex to CSS custom properties (~97 replacements for single-source theming) - Fix off-palette grays in FlowPilotAnalyticsPage chart styling (#8891a0 → #848b9b, #18191f → var(--color-bg-card)) - Update stale comments: "cyan brand" → "accent brand" in GlowEdge, "gradient cyan square" → "gradient orange square" in BrandLogo - Rename glow-cyan SVG filter ID to glow-accent - Fix category color comment: "cyan" → "deep orange" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
97 lines
3.5 KiB
TypeScript
97 lines
3.5 KiB
TypeScript
import { useRef, useEffect } from 'react'
|
|
import { Send, Sparkles, Loader2 } from 'lucide-react'
|
|
import { MarkdownContent } from '@/components/ui/MarkdownContent'
|
|
import type { EditorAIChatMessage } from '@/types'
|
|
|
|
interface ChatTabProps {
|
|
messages: EditorAIChatMessage[]
|
|
input: string
|
|
onInputChange: (value: string) => void
|
|
onSend: () => void
|
|
isLoading: boolean
|
|
}
|
|
|
|
export function ChatTab({ messages, input, onInputChange, onSend, isLoading }: ChatTabProps) {
|
|
const messagesEndRef = useRef<HTMLDivElement>(null)
|
|
const inputRef = useRef<HTMLTextAreaElement>(null)
|
|
|
|
useEffect(() => {
|
|
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
|
|
}, [messages])
|
|
|
|
// Focus input when panel mounts
|
|
useEffect(() => {
|
|
requestAnimationFrame(() => inputRef.current?.focus())
|
|
}, [])
|
|
|
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault()
|
|
if (input.trim() && !isLoading) onSend()
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="flex flex-1 flex-col overflow-hidden">
|
|
{/* Messages */}
|
|
<div className="flex-1 overflow-y-auto px-4 py-3 space-y-3">
|
|
{messages.length === 0 && (
|
|
<div className="flex flex-col items-center justify-center h-full text-muted-foreground text-sm">
|
|
<Sparkles className="h-8 w-8 mb-2 opacity-40" />
|
|
<p>Ask me to help build your flow</p>
|
|
</div>
|
|
)}
|
|
{messages.map((msg, i) => (
|
|
<div
|
|
key={i}
|
|
className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
|
|
>
|
|
<div
|
|
className={`max-w-[85%] rounded-xl px-3.5 py-2.5 text-[0.8125rem] leading-relaxed ${
|
|
msg.role === 'user'
|
|
? 'bg-primary/15 text-foreground'
|
|
: 'bg-input text-foreground border border-border'
|
|
}`}
|
|
>
|
|
<MarkdownContent content={msg.content} className="text-[0.8125rem] leading-relaxed" />
|
|
</div>
|
|
</div>
|
|
))}
|
|
{isLoading && (
|
|
<div className="flex justify-start">
|
|
<div className="bg-input border border-border rounded-xl px-3.5 py-2.5">
|
|
<Loader2 size={16} className="animate-spin text-primary" />
|
|
</div>
|
|
</div>
|
|
)}
|
|
<div ref={messagesEndRef} />
|
|
</div>
|
|
|
|
{/* Input */}
|
|
<div className="px-4 py-3 border-t shrink-0" style={{ borderColor: 'var(--color-border-default)' }}>
|
|
<div className="flex items-end gap-2">
|
|
<textarea
|
|
ref={inputRef}
|
|
value={input}
|
|
onChange={(e) => onInputChange(e.target.value)}
|
|
onKeyDown={handleKeyDown}
|
|
placeholder="Ask AI to help..."
|
|
rows={1}
|
|
className="flex-1 resize-none rounded-xl border bg-card text-foreground text-[0.8125rem] placeholder:text-muted-foreground px-3.5 py-2.5 focus:outline-hidden focus:border-primary/30"
|
|
style={{ borderColor: 'var(--color-border-default)' }}
|
|
disabled={isLoading}
|
|
/>
|
|
<button
|
|
onClick={onSend}
|
|
disabled={!input.trim() || isLoading}
|
|
className="bg-primary text-white p-2.5 rounded-xl hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-40"
|
|
>
|
|
<Send size={16} />
|
|
</button>
|
|
</div>
|
|
<p className="text-[0.625rem] text-muted-foreground mt-1.5 px-1">Shift + Enter for a new line</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|