---
title: "Designing for Conversation: UX Patterns for Chat Interfaces"
description: "Message bubbles are the easy part. The real design challenge is rich cards, embedded actions, error states, and streaming feedback inside chat."
canonical: https://nowah.xyz/blog/designing-for-conversation-ux-patterns
lastModified: "2026-08-07T07:55:12.125Z"
---

# Designing for Conversation: UX Patterns for Chat Interfaces

Message bubbles are the easy part. The real design challenge is rich cards, embedded actions, error states, and streaming feedback inside chat.

When people hear "[chat interface](/blog/adapting-chat-interface-mobile-desktop)," they think of message bubbles. Blue on the right, gray on the left, timestamps, maybe a typing indicator. That part is easy. Every messaging app in the world has solved it. The [design patterns](/blog/conversation-design-patterns-ai-agents) for text-based chat are well-established and boring in the best sense.

The hard part, the part nobody has fully figured out yet, is everything else that needs to live inside a chat when the chat is your primary product surface. Flight comparison cards. Hotel options with photos and prices. Payment flows. Booking confirmations. Error states. Loading indicators that tell you what the AI is actually doing. Interactive elements that let you make choices without leaving the conversation.

We have been designing these patterns for Nowah since the beginning, and I want to share what we have learned. Not because we think we have all the answers, but because the design community needs more public thinking about conversational UX for AI products. Most of what exists is either basic chatbot design (menus and buttons) or theoretical frameworks with no production experience behind them.

## Beyond message bubbles

![Illustration for this section](https://pics.nowah.xyz/website-media/product-021-img-1.webp)

The first misconception to correct: a chat interface for an AI agent is not a messaging app with a bot. The design requirements are fundamentally different.

In a messaging app, both parties produce the same type of content: text, images, links. The interface is symmetric. The design system needs to handle two text bubbles, media attachments, and maybe reactions.

In an AI agent interface, the content types are wildly asymmetric. The user sends text (or voice). The AI sends text, structured data cards, interactive buttons, status updates, loading states, error messages, and embedded transactional flows. The design system needs to handle all of this within the same scrolling conversation, and it needs to feel coherent rather than chaotic.

Think about a typical Nowah conversation. The user says: "I need a flight to Tokyo next month." The AI responds with text: "I found some great options for you. Here are three flights for mid-April." Below that text, three flight cards appear, each with departure time, arrival time, airline, price, duration, and number of stops. Below the cards, a row of action buttons: "Show me more options," "Change dates," "Tell me about these airlines." The user taps a flight card. A detail view expands with baggage info, seat selection, and cancellation policy. The user says "Book this one." A price summary card appears. A payment sheet slides up.

That single exchange involves six distinct UI components: text bubble, flight cards, action buttons, expanded detail view, summary card, and payment sheet. Each needs its own design, its own interaction model, and its own relationship to the conversation flow. And all of it needs to feel like a natural conversation, not like a webpage crammed into a chat window.

## Rich cards: structured data in conversational flow

Rich cards are the workhorse of conversational AI design. They are how you present structured information (flights, hotels, booking summaries) inside a chat without resorting to dense text paragraphs that nobody will read.

Our flight cards show six pieces of information at the summary level: departure and arrival times, total duration, number of stops, airline name, and price. That is it. We tested cards with more information (baggage allowance, aircraft type, seat availability) and found that users took longer to make decisions without making better ones. The additional information created noise, not clarity.

The hierarchy within each card matters enormously. Price and schedule are the two things travelers care about most. They get the largest type size and the most prominent position. Airline and stops are context that supports the decision. They get secondary positioning. Everything else is behind a tap.

Consistency between cards is non-negotiable. When a user is comparing three flight options, their eyes need to scan from the same position on card one to the same position on card two to the same position on card three. If the price is in the top-right of card one and the bottom-left of card two, the comparison fails. We use a rigid layout grid for all option cards so that comparison by scanning is instant.

Hotel cards present a different design challenge. Hotels are more subjective than flights. A flight is defined by numbers: times, price, duration. A hotel is defined by feel, location context, review sentiment, and photos. Our hotel cards lead with a photo (critical for the emotional decision), followed by price per night, rating, and a one-line AI-generated summary of why this hotel matches the user's preferences. The "why this hotel" line is the piece that makes AI curation visible. "Boutique hotel in Shinjuku, 10-minute walk to the metro, strong reviews for cleanliness" is more useful than a star rating.

One design principle we landed on early: cards should never break the scroll flow of the conversation. They sit inline with messages. They do not pop up in modals. They do not redirect to new screens. They are messages from the AI, just structured ones. This keeps the user in the conversation mentally, even when the content is structured data rather than text.

## Action buttons in context

![Supporting diagram](https://pics.nowah.xyz/website-media/product-021-img-2.webp)

Every rich card creates a decision point. The user sees three flights. Now what? Without action buttons, they would have to type "I want the second one" or "book the United flight." That works, but it is slow and introduces ambiguity. Which one is "the second one" if they have scrolled?

Action buttons solve this by embedding clear, tappable actions directly in the conversation at the moment they are relevant. Below the flight cards: "Book this" on each card. Below a set of options: "Show more," "Change dates," "Different airports."

The design rules for action buttons in conversational contexts are different from button design in traditional UIs.

First, buttons must be ephemeral. Unlike a persistent navigation bar, action buttons in a conversation are relevant only at that point in the conversation. If the user scrolls past and comes back later, the buttons might no longer make sense because the context has moved on. We handle this by making action buttons tappable but not prominent once the conversation has progressed past them. They fade visually but remain functional.

Second, buttons should advance the conversation, not branch it. A button that says "Book this flight" moves the conversation forward: selection, payment, confirmation. A button that says "Show flight details in new window" breaks the conversation by opening a modal or navigation. We avoid the second pattern whenever possible.

Third, the number of buttons matters. Offering two or three clear actions is helpful. Offering eight buttons turns the chat into a navigation menu, which defeats the purpose of a conversational interface. When there are many possible next steps, we let the AI offer the most likely two or three and let the user type if they want something different.

## Streaming and typing indicators

When you send a message to an AI agent and nothing happens for five seconds, you wonder if it is broken. When you see the AI thinking, searching flights, comparing options, those same five seconds feel productive. The difference is feedback.

Streaming is not just a technical choice. It is a design choice. We stream the AI's response character by character as it is generated, rather than waiting for the complete response and displaying it all at once. This has measurable effects on engagement. [Streaming responses](/blog/streaming-ai-responses-real-time-chat) increase user engagement by two to three times compared to batch responses that appear after a delay.

But naive streaming (just showing characters appear) is not enough for an AI agent that is doing complex work. When the agent is searching for flights, the user should not just see a cursor blinking. They should see "Searching flights to Tokyo..." with a progress indicator. When the agent is comparing options: "Analyzing 47 flights, ranking by your preferences..." When the agent is preparing cards: "Found three great options."

These status messages serve two purposes. They communicate progress, which reduces anxiety. And they build trust by showing the user what the agent is actually doing. "The AI is searching real flight data right now" is more credible than text that appears out of nowhere. The transparency is the trust mechanism.

We designed three levels of status communication:

Thinking indicators for when the AI is processing the request but has not started any visible work. A subtle animation that says "the agent received your message and is figuring out what to do."

Action indicators for when the agent is using tools. "Searching flights," "Checking hotel availability," "Converting currencies." These are specific and change in real time as the agent moves through its task list.

Streaming text for the conversational response itself. Characters appear as the AI generates them, giving the user something to read while the agent continues working.

The choreography of these three levels matters. You do not want the [thinking indicator](/blog/thinking-indicator-most-important-animation) to persist too long (it feels stuck). You do not want action indicators to flash so fast that the user cannot read them (it feels chaotic). You want the transition from action indicators to streaming text to feel like the agent finished its research and is now talking to you about what it found.

## Error states in conversation

[Error handling](/blog/error-handling-recovery) in conversational UI is fundamentally different from error handling in traditional UI, and most conversational products get it wrong.

In a traditional app, an error is a state. You see an error page, an error banner, a red outline on a form field. The error persists until you fix it. The UI communicates the problem and waits.

In a conversation, an error is a message. It appears in the thread, the conversation continues below it, and the user needs to understand both what went wrong and how to move forward without navigating to a different screen.

We handle errors in three categories.

Misunderstandings are the most common. The user says something the agent does not understand or misinterprets. "I want to fly to somewhere warm" is ambiguous. The agent should not guess and get it wrong. It should clarify: "I have some ideas, but can you narrow it down? Are you thinking beach resort, tropical city, or desert warmth?" This is not an error state in the traditional sense, but it is a point where the conversation could go wrong without good design. The clarification should feel like a natural follow-up question, not an error message.

System failures are less common but higher stakes. The flight search API returns no results. The payment processor is down. The booking could not be completed. These need to be communicated clearly without alarming the user. "I could not find any direct flights for those dates. Want me to check nearby dates or flights with one stop?" is better than "Error: No results found." The conversational format lets you present the failure as a natural part of the dialogue, with an alternative built in.

Recovery from errors is where conversational UI shines compared to traditional UI. On a traditional error page, the user has to figure out what to do. Go back? Refresh? Try again? In a conversation, the AI can guide recovery. "The payment did not go through. This sometimes happens with international cards. Want to try a different payment method, or should I hold the booking while you sort it out?" The error and the recovery are in the same thread, in the same context, delivered by the same agent that the user has been talking to.

## Anti-patterns that break conversational UX

Through a lot of iteration, we have identified patterns that reliably break the conversational experience. These are common in chatbot implementations and we avoid all of them.

Modal overuse is the biggest offender. You are in a chat, you tap a card, and a full-screen modal appears with flight details. The conversation disappears behind it. You are no longer in a conversation. You are in a modal. This pattern treats the chat as a trigger for traditional UI, which undermines the entire point of conversational design. We use inline expansion instead. Tap a card, it expands in place. The conversation is still visible above and below.

Page navigation mid-conversation is the same problem in a different form. You are chatting about hotels. You tap "See hotel details." The app navigates to a hotel detail page. The conversation is gone. To get back, you hit the back button and hope the conversation is still there. This breaks context continuity, which is the fundamental advantage of conversational commerce.

Form fallbacks are a subtler anti-pattern. The AI asks for your dates and presents a date-picker form instead of accepting natural language. "When do you want to fly?" should accept "next Thursday" or "sometime in late April" or "March 15 to the 22nd." Dropping a calendar widget into the chat is a concession that the AI cannot handle natural input, which is true for date pickers, but it breaks the conversational feel. We use date pickers only when the AI needs to disambiguate ("Did you mean March 15 or March 16?"), not as the primary input method.

Menu buttons that replace free text input turn a chat into a phone tree\. "What would you like to do? \[Search Flights\] \[Search Hotels\] \[My Trips\] \[Settings\]\." This is not a conversation\. It is a command menu in a chat bubble\. Menu buttons are appropriate for suggesting next steps\. They should never be the only way to interact\.

## The design system for chat

Building a design system for conversational AI is harder than building one for traditional apps, because the content is variable. You do not control what the AI says, how long its responses are, or what combination of text, cards, and actions it produces.

Our design system includes these core components, each designed to handle variability:

Text messages with dynamic length. Short responses (one line) need to not look lost in a huge bubble. Long responses (multiple paragraphs) need to remain readable without overwhelming the screen. We cap bubble width and use comfortable line spacing.

Card components with consistent layouts. Flight cards, hotel cards, booking summary cards, and trip cards all follow the same spacing and typography rules. A card should look like a card regardless of its content type.

Action containers that hold variable numbers of buttons. The container handles wrapping gracefully whether there is one button or four. More than four triggers a scrollable row rather than wrapping to multiple lines.

Status components that communicate agent activity. Thinking dots, action labels, progress indicators. These are transient, they appear and disappear as the agent works, and they need to animate smoothly to avoid jarring transitions.

System messages for non-conversational information. "Booking confirmed," "Trip updated," "Payment processed." These are not from the AI's conversational voice. They are system confirmations that should look visually distinct from chat messages.

The design system handles the combinatorial problem: any of these components can appear in any order, and the conversation needs to look coherent regardless of the sequence. This requires consistent spacing rules, a clear visual hierarchy that works across component types, and animation choreography that makes the appearance of new elements feel intentional rather than random.

We are still iterating on all of this. Conversational UX for AI agents is a new discipline. The patterns are not settled the way traditional app design patterns are. But we believe that getting this right is one of the [most important](/blog/why-speed-is-most-important-feature) design challenges in AI product development. The quality of the conversational UX determines whether users trust the agent, enjoy the interaction, and come back. Text generation quality is table stakes. The interface that delivers that text, and the structured data alongside it, is where the product experience is won or lost.

---

Nowah is an AI travel agent that searches and books real flights and hotels through conversation — no filters, no thirty open tabs. [Plan your next trip](https://app.nowah.xyz).
