Most chatbot interfaces share the same parts: an input area, a message thread, and controls on each message. The difference between a good and a frustrating chatbot is mostly in the details of those parts and their states.
Start with the empty state. A blank screen with a text box gives no idea what the bot can do. Add a short description and three or four example prompts people can tap.
Make the thread easy to read. Keep message width comfortable for reading, separate user and AI messages clearly, render formatting such as lists and code properly, and keep the latest message in view while new text streams in, without jumping if the person has scrolled up.
Design every state. Sending, thinking, streaming, finished, stopped and failed should each look different. A thinking indicator, often an animated dot pattern or orb, tells people the request was received. A stop button while streaming gives control back. Errors should say what happened and offer a retry.
Add controls to answers: copy, regenerate, edit the previous prompt and give feedback. For a voice assistant, use a clear visual for listening, thinking and speaking so people know when to talk. ExodeUI, which we make, has free animated orbs for these states that run in React, Vue, SwiftUI, Flutter and other frameworks.