← Components/AI-Specific

ChatInterface

chatinterface-1779378413147.tsx
'use client'
import { useState, useRef, useEffect } from 'react'

interface Msg { id: number; role: 'user' | 'assistant'; content: string; streaming?: boolean }

const RESPONSES = [
  "Here's a React component for you:
```tsx
export default function Button() {
  return <button className="bg-gold-500 text-black px-4 py-2 rounded">Click me</button>
}
```",
  "I found 12 matching components in the Empire UI library. The most popular are: **GlowButton**, **HoverTiltCard**, and **CommandMenu**. Would you like the code for any of these?",
  "Great choice! The `RadialProgress` component uses SVG stroke animation with `stroke-dashoffset`. It supports 4 metrics simultaneously and animates on mount. Here's how to install it...",
  "I can generate a custom component for that. Give me a moment... ✨

Here's a `PricingToggle` with monthly/annual billing and animated transitions between prices.",
]

export default function ChatInterface() {
  const [msgs, setMsgs] = useState<Msg[]>([
    { id: 0, role: 'assistant', content: 'Hi! I\'m Empire UI Assistant. Ask me to find or generate any React component.' }
  ])
  const [input, setInput] = useState('')
  const [loading, setLoading] = useState(false)
  const bottomRef = useRef<HTMLDivElement>(null)

  useEffect(() => { bottomRef.current?.scrollIntoView({ behavior: 'smooth' }) }, [msgs])

  async function send() {
    if (!input.trim() || loading) return
    const userMsg: Msg = { id: Date.now(), role: 'user', content: input }
    setMsgs(m => [...m, userMsg])
    setInput('')
    setLoading(true)

    const responseText = RESPONSES[Math.floor(Math.random() * RESPONSES.length)]
    const aiMsg: Msg = { id: Date.now() + 1, role: 'assistant', content: '', streaming: true }
    setMsgs(m => [...m, aiMsg])

    for (let i = 0; i <= responseText.length; i++) {
      await new Promise(r => setTimeout(r, 15))
      setMsgs(m => m.map(msg => msg.id === aiMsg.id ? { ...msg, content: responseText.slice(0, i) } : msg))
    }
    setMsgs(m => m.map(msg => msg.id === aiMsg.id ? { ...msg, streaming: false } : msg))
    setLoading(false)
  }

  return (
    <div style={{ background: '#0A0A0A', height: 480, display: 'flex', flexDirection: 'column', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 16, overflow: 'hidden' }}>
      {/* Header */}
      <div style={{ padding: '14px 20px', borderBottom: '1px solid rgba(255,255,255,0.06)', display: 'flex', alignItems: 'center', gap: 10, background: '#111' }}>
        <div style={{ width: 32, height: 32, borderRadius: '50%', background: 'linear-gradient(135deg, #C9A84C, #6366f1)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 16 }}>⚡</div>
        <div>
          <div style={{ color: '#F5F5F0', fontSize: 14, fontWeight: 600 }}>Empire UI Assistant</div>
          <div style={{ color: '#22c55e', fontSize: 11 }}>● Online</div>
        </div>
      </div>

      {/* Messages */}
      <div style={{ flex: 1, overflowY: 'auto', padding: '16px 20px', display: 'flex', flexDirection: 'column', gap: 12 }}>
        {msgs.map(msg => (
          <div key={msg.id} style={{ display: 'flex', justifyContent: msg.role === 'user' ? 'flex-end' : 'flex-start', gap: 8 }}>
            {msg.role === 'assistant' && (
              <div style={{ width: 28, height: 28, borderRadius: '50%', background: 'linear-gradient(135deg, #C9A84C, #6366f1)', flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14 }}>⚡</div>
            )}
            <div style={{
              maxWidth: '75%', padding: '10px 14px', borderRadius: msg.role === 'user' ? '16px 16px 4px 16px' : '16px 16px 16px 4px',
              background: msg.role === 'user' ? '#C9A84C' : '#1a1a1a',
              color: msg.role === 'user' ? '#0A0A0A' : '#F5F5F0', fontSize: 14, lineHeight: 1.5,
              border: msg.role === 'assistant' ? '1px solid rgba(255,255,255,0.06)' : 'none',
            }}>
              {msg.content}
              {msg.streaming && <span style={{ display: 'inline-block', width: 2, height: 14, background: '#C9A84C', marginLeft: 2, animation: 'blink 0.7s step-end infinite', verticalAlign: 'text-bottom' }} />}
            </div>
          </div>
        ))}
        <div ref={bottomRef} />
      </div>

      {/* Input */}
      <div style={{ padding: '12px 16px', borderTop: '1px solid rgba(255,255,255,0.06)', display: 'flex', gap: 10 }}>
        <input
          value={input} onChange={e => setInput(e.target.value)}
          onKeyDown={e => e.key === 'Enter' && !e.shiftKey && send()}
          placeholder="Ask for a component..."
          style={{ flex: 1, background: '#1a1a1a', border: '1px solid rgba(255,255,255,0.08)', color: '#F5F5F0', padding: '10px 14px', borderRadius: 10, fontSize: 14, outline: 'none' }}
        />
        <button onClick={send} disabled={!input.trim() || loading} style={{
          background: input.trim() ? '#C9A84C' : 'rgba(255,255,255,0.06)',
          color: input.trim() ? '#0A0A0A' : '#555', border: 'none',
          padding: '10px 16px', borderRadius: 10, cursor: 'pointer', fontWeight: 700, fontSize: 14,
        }}>↑</button>
      </div>
      <style>{`@keyframes blink { 0%,100% { opacity: 1 } 50% { opacity: 0 } }`}</style>
    </div>
  )
}

Component info

CategoryAI-Specific
Frameworkreact
TierFREE
Views0
Copies0

About

Full AI chat interface with streaming simulation, message bubbles, and input area

More from AI-Specific

'use client'
import { useState } from 'react'

const TEMPLATES = [
  { id: 'role', label: 'System role', color: '#6366f1', content: 'You are a {role} expert who {expertise}.' },
  { id: 'task', label: 'Task', color: '#C9A84C', content: 'Your task is 
PromptBuilder
AI-Specific
import React, { useState, useEffect } from 'react';

interface ChatBubbleProps {
  message: string;
  isAI: boolean;
}

const ChatBubble: React.FC<ChatBubbleProps> = ({ message, isAI }) => {
  const [isTyping, setIsTyping] = useState(false);
  const 
ChatBubble
AI-Specific
import React, { useState, useEffect } from 'react';

interface Props {
  text: string;
  speed: number;
}

const StreamingText: React.FC<Props> = ({ text, speed }) => {
  const [displayedText, setDisplayedText] = useState('');
  const [tokens, setTok
StreamingText
AI-Specific