QuickReplyButton

Updated: Sep 24, 2026
QuickReplyButton is a compact action for a ready-to-send response or reaction in a messaging surface. It is shorter than Button and carries a single line of text, an optional icon, or both. When it has both, the icon stays hidden until the control is focused or pressed, and the width animates as it reveals.
Use it for conversational replies that send immediately. General application commands, destinations, and multi-step flows belong on a Button.
Place quick replies inside a ButtonRail — or a ButtonGroup when the set always fits.
QuickReplyButton is built on Container, which is built on InteractableBase. Read those pages for the full interaction, material, and tooltip contract.

Usage

import { ButtonRail, QuickReplyButton } from '@wearables-ui-toolkit/mrbd';

<ButtonRail>
  <QuickReplyButton title="Thanks!" icon={thumbsUpIcon} onClick={() => send('Thanks!')} />
  <QuickReplyButton title="On my way" onClick={() => send('On my way')} />
  <QuickReplyButton
    icon={heartIcon}
    aria-label="React with a heart"
    onClick={() => react('heart')}
  />
</ButtonRail>;
A reply set driven by data still belongs in a single lane, so focus travel and overflow stay correct:
import { ButtonGroup, QuickReplyButton } from '@wearables-ui-toolkit/mrbd';

<ButtonGroup>
  {suggestions.map(suggestion => (
    <QuickReplyButton
      key={suggestion.id}
      title={suggestion.text}
      icon={sendIcon}
      disabled={isSending}
      onClick={() => send(suggestion.text)}
    />
  ))}
</ButtonGroup>;

Props

The full prop type is QuickReplyButtonProps. It extends the Container prop type, minus the props the control owns itself.

Own props

PropTypeDefaultDescription
title
string
—
The reply text. Also supplies the accessible name.
icon
IconSource
—
Optional icon. Revealed on focus and press when there is also text; always visible when there is no text.

Notable inherited props

PropTypeDefaultDescription
onClick
(event: MouseEvent) => void
—
Activation handler. Receives a real DOM click event for pointer and keyboard activation.
onActivate
(event: InteractableActivationEvent) => void
—
Called once per activation; keyboard activation receives the originating keyboard event.
onLongPress
(event) => void
—
Called when the press is held past the long-press threshold.
onStateChange
(prev: InteractionState, next: InteractionState) => void
—
Called on every default / focused / pressed / disabled transition.
disabled
boolean
false
Dim the control and suppress activation. It stays focusable.
interactive
boolean
true
Master switch for focusable, pressable, and clickable.
focusable
boolean
inherits interactive
Whether the control takes focus.
initialFocusEligible
boolean
true
Whether the control may receive initial focus when a route mounts.
aria-label
string
—
Accessible name. Required when there is no title.
tooltipText
string
—
Tooltip copy.
tooltipMode
TooltipMode
TooltipMode.NONE
When the tooltip appears.
tooltipPosition
TooltipPosition
TooltipPosition.ANCHORED
Where the tooltip is placed relative to the control.
material
ContainerMaterial
the button material
Material used for the background and stroke layers.
shapeProvider
ShapeProvider
full-radius rounded rectangle
Geometry used for clipping and every material path.
clipContent
boolean
true
Clip the content to the pill shape.
className
string
''
Extra class on the root element.
style
CSSProperties
—
Extra inline styles on the root element. They merge over the component’s own transform and opacity, so use them for placement, not for restyling.
QuickReplyButton does not accept children, width, or height: content comes from title and icon, and the size is component-owned. The state-and-motion hooks the reveal depends on are removed as well — materialTransition, visualStateOverride, visualStateForInteractionStateFn, contentScaleForStateFn, and stateChangeAnimations are not part of the type, because the component drives the width, scale, and icon fade itself. The role is component-owned as well, and so is the ariaLabel convenience prop — it is always set from title, so name an icon-only reply with the standard aria-label instead. The component forwards its ref to the root HTMLDivElement.

Behavior

Content modes. Text only, icon only, or text plus a revealing icon. With both, the icon is hidden in the default state and fades in slightly behind the width change when the control is focused or pressed; the delay is skipped on press transitions so a press feels immediate. With no text, the icon is always visible and centered, and the control keeps a square footprint.
Color. In the default state the label and icon use the secondary text and icon roles with a lighten blend so they sit back against the material; on focus and press they move to the primary roles.
Sizing. The control measures its own text and animates its width between the collapsed and revealed states — the revealed width adds room for the icon and the gap before it — with a component-owned minimum so an icon-only reply stays square. There is no maximum width and no truncation: the label never wraps or ellipsizes, so the control keeps growing with the text. Keep the copy short instead of expecting the component to cap it. It is shorter than a Button, and a group sizes its row to the tallest child, so a quick-reply-only lane is not padded out to full button height. The control publishes a layout compensation that keeps spacing even in a group or rail while its width animates.
Material and state. The default material is the button material on a full-radius shape. The resting state is inset slightly, focus goes to full size, and press insets again, with the material cross-fading between its idle, focused, and pressed layers.
Reduced motion, fast traversal, and page entry. When the display prefers reduced motion, when focus is moving quickly through a lane, or while a route is entering, the width and icon reveal snap to their end state instead of animating.
Disabled. A disabled quick reply dims, keeps its focus stop, exposes aria-disabled, and suppresses activation. It still reports focus and blur through onStateChange.

Accessibility

  • The control renders with role="button", takes a focus stop, and activates on Enter, Space, and pointer click.
  • The accessible name is taken from title. For an icon-only quick reply, pass the standard aria-label prop; with no title and no aria-label the control has no accessible name at all.
  • The icon is decorative and hidden from assistive technology, so a reaction it represents must also be in the label.
  • Because the icon is hidden while unfocused, never let it carry meaning the label does not already convey.
  • Keep the copy conversational, short, and immediately sendable.
  • Give icon-only replies an accessible label with aria-label.
  • Put quick replies in a rail or group alongside their peers.
  • Disable the whole set while a send is in flight rather than unmounting it and losing focus.

Avoid

  • Avoid using full sentences or multi-line copy.
  • Avoid using a quick reply for general commands, navigation, or multi-step flows.
  • Let the component own its width, internal margins, and icon size so the reveal motion and lane spacing stay synchronized.
  • Avoid relying on ariaLabel to name the control; it is component-owned.
  • Avoid mixing quick replies and standard buttons in a way that makes the reply set read as ordinary page actions.