React AI chat UI components

The interface layer for an LLM product: the prompt box, the thinking state, the model picker and the attachments. Bring your own provider.

Built with the stack you already ship

React
Next.js
TypeScript
Tailwind CSS
Framer Motion
Vite
Astro
React
Next.js
TypeScript
Tailwind CSS
Framer Motion
Vite
Astro

Prompt input and controls

The parts a user actually touches: where they type, what they attach, and which model they are talking to.

Thinking, streaming and voice states

An LLM response takes seconds, not milliseconds. These are the states that fill that gap without making the wait feel broken.

What makes a chat interface feel good

The hard part of a chat interface is not the message bubbles. It is the several seconds between the user pressing enter and the first token arriving, which is far longer than any normal interface delay and completely outside your control. Everything that makes an AI product feel fast or slow happens in that window, and a plain spinner is the weakest thing you can put there because it says only that something is happening.

A better waiting state suggests the shape of what is coming. That is what a skeleton does in a normal app, and it works here too: Generative Skeleton Mesh fills the response area with something that reads as text taking form rather than as a loading indicator sitting on an empty box. The user's eye settles where the answer will appear, so when tokens do start arriving there is no jump and no re-reading.

Once tokens start streaming, resist the urge to animate them. Text that fades or slides in per word is much harder to read than text that simply appears, because the eye keeps re-fixating on moving targets. Stream the characters in plainly and spend the motion budget on the container instead, letting it grow smoothly as content fills it so the page below does not jump on every chunk.

The prompt input carries more weight than its size suggests, because it is the one thing on screen at every moment. It needs to grow with the content rather than scroll internally, accept a paste of five hundred words without breaking the layout, submit on Enter while keeping Shift and Enter for a newline, and make attachment state obvious before submission rather than after. Liquid Multimodal Input handles all four, which is roughly the minimum bar.

Voice interfaces need one honest signal above all: whether the microphone is currently listening. That is a privacy question before it is a design question, and an ambiguous indicator is worse than none. Voice Aurora Wave ties its amplitude to real input level, so the visual is driven by what the microphone actually hears rather than a decorative loop that would keep moving if the stream had already dropped.

Frequently asked questions

No, and that is deliberate. They are the interface layer only, with no provider SDK, no API key handling and no opinion about where your tokens come from. Wire them to the AI SDK, a direct fetch to any provider, or your own endpoint. That keeps them useful when you switch models, which most teams do at least once.
Append incoming chunks to a piece of state and render it as plain text. Avoid animating each token as it arrives, because moving text is measurably harder to read than static text. Animate the container height instead so the layout settles smoothly, and keep the scroll pinned to the bottom only while the user has not scrolled up themselves.
Something that indicates the shape of the answer rather than a generic spinner. A skeleton in the response area works because it puts the user's attention where the text will appear, which removes the jump when streaming starts. Generative Skeleton Mesh is built for that, and Shimmering Skeleton Wrapper does the same job around any layout you already have.
Voice Aurora Wave reacts to an audio amplitude value that you pass in, so the component itself requests nothing. You capture the stream through the Web Audio API in your own code and feed it the level. That keeps the permission prompt under your control and means the component works just as well for playback visualisation as for recording.
ChatGPT Orb uses low power fractal noise inside a circular mask rather than a full scene, and Siri Orb renders a single sphere. Both are far lighter than a general 3D scene, but both still compile shaders before the first frame. If one is the first thing on screen in your app, give it a static fallback for the initial paint.

Where to go next