---
title: Quick Replies
description: Suggested replies under a message — a named group of chips, each dispatching the answer the reader picked.
visibility: guest
draft: false
---

# Quick Replies

A row of suggested answers under the last message, so the reader can reply with one
press instead of typing. Each chip dispatches what was picked; what happens next —
sending it, filling the composer, calling a tool — stays with your application.

## Basic Usage

Pass the suggestions as strings. The words on a chip are also the value you get back.

:::preview{title="Suggestions under an assistant message"}
<div style="width: 26rem; max-width: 100%; margin-inline: auto;">
    <x-wirekit::stack gap="sm">
        <x-wirekit::message :author="['name' => 'Assistant']">Your order is on its way. Anything else?</x-wirekit::message>
        <x-wirekit::quick-replies :replies="['Track it', 'Change the address', 'No, thanks']" />
    </x-wirekit::stack>
</div>
:::

:::source{language="blade"}
<x-wirekit::stack gap="sm">
    <x-wirekit::message :author="['name' => 'Assistant']">Your order is on its way. Anything else?</x-wirekit::message>
    <x-wirekit::quick-replies :replies="['Track it', 'Change the address', 'No, thanks']" />
</x-wirekit::stack>
:::

## Values, and a suggestion that is not available

An entry may be an array instead of a string: `label` is what the reader sees, `value`
is what your listener receives, and `disabled` offers a suggestion that cannot be taken
right now without removing it from the row.

:::preview{title="Labels, values and a disabled suggestion"}
<x-wirekit::quick-replies
    label="Reply to the delivery update"
    :replies="[
        ['label' => 'Track it', 'value' => 'track'],
        ['label' => 'Change the address', 'value' => 'address'],
        ['label' => 'Talk to a human', 'value' => 'handoff', 'disabled' => true],
    ]"
/>
:::

## Listening

A press dispatches `wirekit:quick-replies-select`, and the event bubbles. Its `detail`
carries `value`, `label` and the zero-based `index` of the chip.

:::preview{title="A suggestion that fills the composer"}
<div x-data="{ draft: '' }" style="width: 26rem; max-width: 100%; margin-inline: auto;">
    <x-wirekit::stack gap="sm">
        <x-wirekit::quick-replies
            :replies="['Sounds good', 'Send me the details', 'Not right now']"
            x-on:wirekit:quick-replies-select="draft = $event.detail.value"
        />
        <x-wirekit::textarea label="Your reply" rows="2" x-model="draft" />
    </x-wirekit::stack>
</div>
:::

:::source{language="blade"}
<div x-data="{ draft: '' }">
    <x-wirekit::quick-replies
        :replies="['Sounds good', 'Send me the details', 'Not right now']"
        x-on:wirekit:quick-replies-select="draft = $event.detail.value"
    />
    <x-wirekit::textarea label="Your reply" rows="2" x-model="draft" />
</div>
:::

In Livewire, hand the value straight to a method:

```blade
{{-- 1. The chips dispatch the picked answer; the listener passes it to the component. --}}
<x-wirekit::quick-replies
    :replies="$suggestions"
    x-on:wirekit:quick-replies-select="$wire.reply($event.detail.value)"
/>
```

## Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `replies` | array | `[]` | The suggestions, in order. A string is its own label and value; an array takes `label`, an optional `value` and an optional `disabled`. An entry with no label is skipped. |
| `label` | string\|null | `null` | Names the group for assistive technology. Defaults to a translated "Suggested replies". |
| `scope` | string\|null | `null` | Scoped personalization name. |

The chips resolve their look through the `base` and `chip` keys, so a theme can restyle
the row and the pills separately.

## Accessibility

- The row is a **named group of buttons** — `role="group"` with a name, so a screen
  reader announces what the suggestions belong to before reading them.
- It is deliberately **not** a toolbar. That role promises an arrow-key model, and this
  row has none: a reader who tried the arrows would find the promise broken.
- Every chip carries the same target floor the rest of the library uses, so a suggestion
  stays pressable on a phone, and the row wraps rather than scrolling sideways — a chip
  behind a screen edge is one nothing announces.
- With no suggestions the component renders nothing at all, rather than an empty group
  that announces a set and then offers none.

## Keyboard Interaction

| Key | Action |
|-----|--------|
| `Tab` | Move focus to the next suggestion |
| `Enter` / `Space` | Pick the focused suggestion |

The chips are ordinary buttons, one tab stop each. There is deliberately no arrow-key
model: offering one means taking the whole row out of the tab sequence, and a row that
merely looks like it has arrow keys leaves a reader pressing them at nothing.

## Pitfalls

- **Don't offer more than a handful.** Every chip is a tab stop, so ten suggestions put
  ten stops between the reader and the composer below them.
- **Don't drop the composer.** Suggestions are shortcuts for the common answers, never a
  replacement for typing one — keep the field they sit above.
- **Don't treat the event as "sent".** It says what was picked. Whether that sends a
  message, fills the field or calls a tool is your application's decision, and the same
  row serves all three.

## See Also

- [Message](/components/message) — the bubble these sit under
- [Conversation](/components/conversation) — the transcript scroller that holds the thread
- [Message Typing](/components/message-typing) — the indicator while the other side writes
