<script setup lang="ts">
import { VoiceButton } from '@/components/elevenlabs-ui/voice-button'
import { onMounted, onUnmounted, ref } from 'vue'
type VoiceButtonState = 'idle' | 'recording' | 'processing' | 'success' | 'error'
const state = ref<VoiceButtonState>('idle')
function handlePress() {
if (state.value === 'idle') {
state.value = 'recording'
}
else if (state.value === 'recording') {
state.value = 'processing'
// Simulate an API call / transcription
setTimeout(() => {
state.value = 'success'
// Revert to idle after the feedback duration
setTimeout(() => {
state.value = 'idle'
}, 1500)
}, 1000)
}
}
function handleKeyDown(e: KeyboardEvent) {
// ⌥ (Alt) + Space
if (e.altKey && e.code === 'Space') {
e.preventDefault()
handlePress()
}
}
onMounted(() => {
window.addEventListener('keydown', handleKeyDown)
})
onUnmounted(() => {
window.removeEventListener('keydown', handleKeyDown)
})
</script>
<template>
<div class="flex min-h-[200px] w-full items-center justify-center p-4">
<VoiceButton
label="Voice"
trailing="⌥Space"
:state="state"
class="min-w-[180px]"
@press="handlePress"
/>
</div>
</template>Installation
pnpm dlx elevenlabs-ui-vue@latest add voice-button
Usage
import { VoiceButton } from "@/components/elevenlabs-ui/voice-button"Basic Usage
<script setup lang="ts">
const state = ref<'idle' | 'recording' | 'processing'>('idle')
const handlePress = () => {
if (state.value === 'idle') {
state.value = 'recording'
} else {
state.value = 'processing'
}
}
</script>
<template>
<VoiceButton
:state="state"
@press="handlePress"
/>
</template>With Label and Keyboard Shortcut
<template>
<VoiceButton
state="idle"
label="Press to speak"
trailing="⌥Space"
@press="console.log("Button pressed")"
/>
</template>Different States
<script setup lang="ts">
import { VoiceButton } from '@/components/elevenlabs-ui/voice-button'
</script>
<template>
<div>
<!-- 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" />
</div>
</template>Icon Button
<script setup lang="ts">
import { MicIcon } from 'lucide-vue-next'
import { VoiceButton } from '@/components/elevenlabs-ui/voice-button'
</script>
<template>
<VoiceButton state="idle" size="icon">
<template #icon>
<MicIcon />
</template>
</VoiceButton>
</template>Custom Styling
<template>
<VoiceButton
state="recording"
variant="default"
size="lg"
class="w-full"
waveformClass="bg-primary/10"
/>
</template>Auto-transitioning States
<script setup lang="ts">
import { ref } from 'vue'
import {
VoiceButton,
type VoiceButtonState,
} from '@/components/elevenlabs-ui/voice-button'
const state = ref<VoiceButtonState>('idle')
const handlePress = () => {
if (state.value === 'idle') {
state.value = 'recording'
} else if (state.value === 'recording') {
state.value = 'processing'
// Simulate API call
setTimeout(() => {
state.value = 'success'
// Auto-return to idle after feedback
}, 2000)
}
}
</script>
<template>
<VoiceButton :state="state" @press="handlePress" />
</template>API Reference
VoiceButton
A button component with multiple states for voice recording workflows, including live waveform visualization.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| state | "idle" | "recording" | "processing" | "success" | "error" | "idle" | Current state of the voice button |
| label | any | - | Content to display on the left side |
| trailing | any | - | Content to display on the right (e.g., shortcuts) |
| icon | any | - | Icon to display when idle (for icon size buttons) |
| variant | "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | "outline" | Button variant |
| size | "default" | "sm" | "lg" | "icon" | "default" | Button size |
| class | string | - | Optional CSS classes for the button |
| waveformClass | string | - | Optional CSS classes for the waveform container |
| feedbackDuration | number | 1500 | Duration in ms to show success/error states |
| ...props | HTMLAttributes | - | All standard button element props |
Emits
| Event | Type | Description |
|---|---|---|
| press | () => void | Callback when when button is clicked |
VoiceButtonState Type
type VoiceButtonState =
| "idle"
| "recording"
| "processing"
| "success"
| "error"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
Notes
- Integrates with the LiveWaveform component for audio visualization
- Success state shows a checkmark icon with automatic timeout
- Error state shows an X icon with automatic timeout
- Processing state displays a subtle pulsing animation
- Recording state activates the live waveform visualization
- Uses the Button component as base with all its variants
- Waveform only appears in recording state
- Feedback states (success/error) automatically return to idle after
feedbackDuration - Compatible with all button sizes and variants