AI Chat Inputs People Enjoy Typing Into: Designing the Prompt Composer in React

A floating frosted glass chat input bar with a glowing violet send button and translucent attachment chips on a dark violet background

The input is the product

In most AI products, the chat input is the one element people touch every single time. The model behind it may be brilliant, the answers may be beautifully formatted, but the first impression and the hundredth both start in the same box at the bottom of the screen. If that box feels cramped, jumpy or confusing, the whole product feels that way too.

The good news is that a prompt composer is a small, contained piece of interface. You can get it right in an afternoon if you know which details matter. This guide walks through those details, from how the text area grows to what the send button should do while a reply is streaming. The examples come from the Uncode catalog, so you can open each one, read the code and adapt it to your own app.

Let the text area grow, then stop

A single line input is fine for a search bar. It is wrong for a prompt. People paste error logs, write paragraphs of context and list requirements on separate lines. The composer should start as one comfortable line and grow with the content, so nobody has to scroll inside a tiny box to reread what they wrote.

Growth needs a ceiling, though. Past a certain height, usually somewhere between a third and half of the viewport, the text area should stop growing and scroll internally. Otherwise a long paste pushes the conversation out of view and the page jumps every time a line is added. The simplest reliable approach in React is to reset the height to auto on every change, read the scroll height, and clamp it between a minimum and a maximum. The AI Prompt Box follows this pattern and keeps its toolbar pinned underneath, so the controls never move while you type. If your product only ever needs short questions, a compact single line bar like the AI Prompt Textarea is a perfectly good choice, as long as it says so through its size.

One more detail: make the transition between heights quick or instant. A slow height animation looks lovely in a demo and feels sluggish when you are typing fast. Motion belongs on things that change rarely, not on something that changes with every keystroke.

Enter to send, Shift and Enter for a new line

This convention is now so widespread that breaking it feels like a bug. Enter sends the message. Shift and Enter inserts a line break. Say so once, quietly, in a hint or a tooltip, and then get out of the way.

There are two traps to watch for. The first is input method editors. People typing in Japanese, Chinese or Korean press Enter to confirm a character, not to send a message. Check the composition state of the keyboard event before treating Enter as submit, or you will send half finished sentences for a large group of users. The second trap is mobile. On a phone keyboard, the return key is the only way to add a line break, and the send button is right there on screen. Many apps sensibly let Enter insert a new line on touch devices and rely on the button to send.

Attachments should feel like part of the message

Files, images and screenshots are now a normal part of prompting. The worst way to handle them is a separate upload dialog that pulls people away from what they were writing. The better way is to let them drop a file on the composer, paste an image straight from the clipboard, or pick one from a paperclip button, and then show the result as a small chip or thumbnail right inside the input area.

Each attachment chip needs a clear way to remove it, a visible name or preview, and a state for files that are still uploading or have failed. A thin progress ring or a subtle shimmer is enough. The same AI Prompt Box shows a good balance here: previews sit above the text, the input stays focused, and opening an image in a larger view does not lose what you typed.

Be honest about limits. If you only accept certain file types or sizes, say so before the upload fails, not after. A short line under the composer or a tooltip on the attach button saves a frustrating round trip.

Uncode UI

Build with AI, not against it.

Over 1,400 React and Tailwind components that run live in the browser, with a prompt ready to paste into Claude, Cursor or v0. Plus a community of people building real sites with AI.

Send, stop and the moments in between

The send button has more states than most buttons in an interface. It should look disabled when there is nothing to send, active when there is, and it should turn into a stop button while the model is generating. That last state matters a lot. Long answers that go in the wrong direction are common, and people need a fast way to cut them off without hunting for a control.

Keep the button in the same place across all of these states. Swapping the icon inside a fixed circle reads as one control changing its job. Moving it, resizing it or hiding it reads as something breaking. While a reply streams, keep the text area editable so people can start drafting a follow up, but make it clear that sending will wait for the current answer or interrupt it.

A little personality helps here, in small doses. The AI Chat Input animates its placeholder through example prompts and expands smoothly on focus, which invites people to start typing without adding noise once they do. A character like the Live Orb, whose eyes follow the cursor, can sit above an empty conversation and make a blank screen feel less blank. Once a conversation is under way, step it back and let the content lead.

Model pickers, modes and the toolbar problem

Modern composers tend to collect buttons: model selection, web search, deep thinking, voice input, canvas mode. Each one is useful to someone. Together they can turn a calm input into a cockpit.

A good rule is to show what changes the next message and hide what changes the session. Toggles like web search affect the very next answer, so they belong on the toolbar with a clear on state. The model picker is usually set once and left alone, so a compact dropdown with the current model name is enough. Anything rarer can live behind a single more button. If a toggle is on, it should look on from across the room, with a filled background or an accent color, not a slightly darker icon that people miss.

Accessibility is not optional here

Because the composer is the primary control, accessibility gaps hurt more than usual. A few checks cover most of the ground:

  • Give the text area a real accessible name, not just a placeholder. Placeholders disappear as soon as typing starts.
  • Every icon button needs a label. A paperclip, a globe and a microphone mean nothing to a screen reader without one.
  • Announce state changes. When generation starts or stops, a polite live region lets people who cannot see the button know what happened.
  • Keep focus in the composer after sending, so keyboard users can carry on without tabbing back.
  • Check contrast on the placeholder and hint text. Light grey on dark grey often fails, and that is exactly the text that explains how the input works.

Performance and polish

Typing has to feel instant. Avoid running expensive work on every keystroke, such as token counting with a heavy library or syncing the draft to a server. Debounce those, or move them off the main thread. If your composer sits on top of an animated background or a WebGL scene, make sure that scene pauses when it is off screen and respects reduced motion settings, so it never steals frames from the input.

Save drafts locally. Few things are more annoying than losing a long prompt because a tab reloaded. A small piece of state in local storage, keyed by conversation, solves it.

Bring these components into your editor

Every component mentioned here lives in the Uncode catalog with a live preview and copyable code. If you work with an AI assistant in your editor, you can also connect Uncode to Claude Code, Cursor or Lovable and ask for a component by name, so the code lands straight in your project. Start with a composer that grows gracefully, handles attachments in place and never moves its send button, and the rest of your AI interface will have a solid place to stand.

Uncode UI

Build with AI, not against it.

Over 1,400 React and Tailwind components that run live in the browser, with a prompt ready to paste into Claude, Cursor or v0. Plus a community of people building real sites with AI.

Keep reading