Files
resolutionflow/frontend/src/components/editor-ai/ChatTab.tsx
chihlasm 34b0f2ade9 fix: eliminate deprecated cyan, glass-border, and off-palette colors site-wide
- 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>
2026-03-27 05:42:08 +00:00

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>
)
}