Skip to main content

Import

import { InputChat } from '@adoptaunabuelo/react-components';

Usage

<InputChat
  placeholder="Type a message..."
  options={[
    { id: "photo", label: "Photo", icon: <Camera /> },
    { id: "file", label: "File", icon: <Paperclip /> }
  ]}
  onOptionClick={(id) => handleAttachment(id)}
  onSend={(data) => {
    if (data.text) sendTextMessage(data.text);
    if (data.media) sendAudioMessage(data.media.base64);
  }}
/>

Props

onSend
(data: { text?: string; media?: { base64: string; contentType: string } }) => void
Callback when message is sent (Enter key or Send button). For text messages, data.text contains the message. For voice recordings, data.media contains the audio as base64-encoded WAV format.
options
Array<{ id: string; label: string; icon?: ReactElement }>
Attachment menu options. When provided, displays a Plus icon button that opens a Menu component with these options.
onOptionClick
(id: string) => void
Callback when an attachment menu item is clicked. Receives the option id.
loading
boolean
Shows loading animation (Lottie), disables input, and changes background to soft gray.
placeholder
string
Input placeholder text.
disabled
boolean
Disables the input and send button.
style
CSSProperties
Custom CSS properties for the container.
Accepts all standard HTML input attributes via ComponentPropsWithoutRef<"input"> (except value and onChange which are managed internally).

Voice Recording Features

  • Microphone button: Appears when input is empty, click to start recording
  • Waveform visualization: Real-time audio visualization using Canvas API during recording
  • Recording controls:
    • Trash icon: Cancel and discard recording
    • Send icon: Complete and send recording
  • Audio format: Automatically converted to base64-encoded WAV format
  • MediaRecorder API: Uses browser’s MediaRecorder for audio capture

UI Behavior

  • Dynamic button: Shows Send icon when text is present or recording, Mic icon when empty
  • Focus styling: Blue border appears on focus (2px neutral medium color)
  • Rounded design: 100px border radius for pill-shaped appearance
  • 48px height: Fixed height for consistent layout

Examples

Text Messaging Only

<InputChat
  placeholder="Type your message..."
  onSend={(data) => {
    if (data.text) {
      sendMessage({ content: data.text, type: 'text' });
    }
  }}
/>

With Attachment Menu

import { Camera, Paperclip, Image } from 'lucide-react';

<InputChat
  placeholder="Message..."
  options={[
    { id: "camera", label: "Camera", icon: <Camera /> },
    { id: "gallery", label: "Gallery", icon: <Image /> },
    { id: "file", label: "File", icon: <Paperclip /> }
  ]}
  onOptionClick={(id) => {
    if (id === 'camera') openCamera();
    if (id === 'gallery') openGallery();
    if (id === 'file') openFilePicker();
  }}
  onSend={(data) => {
    if (data.text) sendTextMessage(data.text);
    if (data.media) sendVoiceMessage(data.media);
  }}
/>

With Voice Recording Handler

<InputChat
  placeholder="Send a message or voice note..."
  onSend={(data) => {
    if (data.text) {
      // Send text message
      sendMessage({ type: 'text', content: data.text });
    }
    if (data.media) {
      // Send voice recording
      sendMessage({
        type: 'audio',
        audioData: data.media.base64,
        contentType: data.media.contentType
      });
    }
  }}
/>

With Loading State

const [isSending, setIsSending] = useState(false);

<InputChat
  loading={isSending}
  disabled={isSending}
  onSend={async (data) => {
    setIsSending(true);
    try {
      await sendMessage(data);
    } finally {
      setIsSending(false);
    }
  }}
/>

Browser Permissions

Voice recording requires microphone access. The component handles permission requests automatically via navigator.mediaDevices.getUserMedia(). If the user denies permission, recording will fail silently.

Build docs developers (and LLMs) love