Building Chat UI — AI Web

Membangun Chat UI Chat interface adalah pola UI paling umum untuk AI. Terlihat sederhana, tapi banyak detail UX yang perlu diperhatikan. Komponen Utama function

Membangun Chat UI

Chat interface adalah pola UI paling umum untuk AI. Terlihat sederhana, tapi banyak detail UX yang perlu diperhatikan.

Komponen Utama

function ChatUI() {
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState("");
  const [isLoading, setIsLoading] = useState(false);
  const messagesEndRef = useRef(null);

  // Auto-scroll ke bawah
  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  async function handleSubmit(e) {
    e.preventDefault();
    if (!input.trim() || isLoading) return;

    const userMessage = { role: "user", content: input };
    setMessages(prev => [...prev, userMessage]);
    setInput("");
    setIsLoading(true);

    // Stream response
    const assistantMessage = { role: "assistant", content: "" };
    setMessages(prev => [...prev, assistantMessage]);

    await streamChat([...messages, userMessage], (token) => {
      setMessages(prev => {
        const updated = [...prev];
        updated[updated.length - 1].content += token;
        return updated;
      });
    });

    setIsLoading(false);
  }

  return (
    <div className="flex flex-col h-screen">
      <div className="flex-1 overflow-y-auto p-4">
        {messages.map((m, i) => (
          <MessageBubble key={i} message={m} />
        ))}
        <div ref={messagesEndRef} />
      </div>
      <form onSubmit={handleSubmit} className="p-4 border-t">
        <input value={input} onChange={e => setInput(e.target.value)} />
        <button disabled={isLoading}>Kirim</button>
      </form>
    </div>
  );
}

UX Details

Stop Generation

const controller = new AbortController();

fetch("/api/chat", {
  signal: controller.signal,
  // ...
});

// User clicks "Stop"
controller.abort();

Yang akan kamu pelajari