Voice Button

Installation

No MCP yet? Connect your agent.

Features

  • State Management: Five distinct states (idle, recording, processing, success, error)
  • Live Waveform: Displays real-time audio visualization during recording
  • Automatic Transitions: Success/error states auto-transition back to idle
  • Keyboard Shortcuts: Display keyboard shortcuts in the trailing slot
  • Flexible Layouts: Supports label/trailing content or icon-only mode
  • Customizable Feedback: Configurable duration for success/error states
  • Accessibility: Proper ARIA labels and button semantics

Usage

import { VoiceButton } from "@/components/ui/voice-button";

Basic Usage

const [state, setState] = useState<"idle" | "recording" | "processing">("idle")

<VoiceButton
  state={state}
  onPress={() => {
    if (state === "idle") {
      setState("recording")
    } else {
      setState("processing")
    }
  }}
/>

With Label and Keyboard Shortcut

<VoiceButton
  state="idle"
  label="Press to speak"
  trailing="⌥Space"
  onPress={() => console.log("Button pressed")}
/>

Different States

import { VoiceButton } from "@/components/ui/voice-button";

export default () => (
  <>
    {/* Idle state */}
    <VoiceButton state="idle" />

    {/* Recording with waveform */}
    <VoiceButton state="recording" />

    {/* Processing */}
    <VoiceButton state="processing" />

    {/* Success feedback */}
    <VoiceButton state="success" />

    {/* Error feedback */}
    <VoiceButton state="error" />
  </>
);

Icon Button

import { MicIcon } from "lucide-react";

import { VoiceButton } from "@/components/ui/voice-button";

export default () => <VoiceButton state="idle" size="icon" icon={<MicIcon />} />;

Custom Styling

<VoiceButton
  state="recording"
  variant="default"
  size="lg"
  className="w-full"
  waveformClassName="bg-primary/10"
/>

Auto-transitioning States

import { useState } from "react";

import { VoiceButton, type VoiceButtonState } from "@/components/ui/voice-button";

export default () => {
  const [state, setState] = useState<VoiceButtonState>("idle");

  const handlePress = () => {
    if (state === "idle") {
      setState("recording");
    } else if (state === "recording") {
      setState("processing");
      // Simulate API call
      setTimeout(() => {
        setState("success");
        // Auto-return to idle after feedback
      }, 2000);
    }
  };

  return <VoiceButton state={state} onPress={handlePress} />;
};

Related items

Requires

  • Real-time canvas-based audio waveform visualizer with microphone input and customizable rendering modes.

    ReactTailwind