Voice recorderPro
Record with a live waveform, review and scrub, then send the take into the thread.
Live · keyboard ready
Megan Brooks
Porch renovation
Tap the mic to record a voice note
- Voice notes in chats, comments, or field notes where speaking beats typing.
- A thread of voice bubbles with playback and scrubbing.
- Use now-playing for music or long-form audio.
- Use hold-to-confirm for press-and-hold actions that do not record.
- Use stopwatch to time something without audio.
Installation
Pro source and install commands unlock with a Pro plan.
example.tsx
import { VoiceRecorder, voicePeaks } from "@/registry/components/voice-recorder/voice-recorder"; const history = [ { id: "m1", duration: 7, peaks: voicePeaks(1, 7), from: "Sam", avatar: "/people/sam.jpg", meta: "9:41 AM" },]; export function Thread() { return <VoiceRecorder defaultMessages={history} maxDuration={30} onSend={message => console.log("sent", message.id)} />;}VoiceRecorder
A voice note composer and thread. Tap the mic to record into a live bar with a scrolling waveform and timer, stop into a review you can play and scrub, then send the take into the thread as a voice bubble.
PropTypeDefaultDescription
defaultMessages{ id: string; duration: number; peaks: number[]; from?: string; avatar?: string; meta?: string }[][]Messages already in the thread, oldest first. peaks are bar heights from 0 to 1 (the exported voicePeaks makes deterministic data); from and avatar mark incoming messages.onSend(message: VoiceMessage) => void–Called with each sent take. Recording is simulated, so wire this to real audio capture.onCancel() => void–Called when a take is discarded with the trash button or Escape.maxDurationnumber60Seconds before recording stops on its own and moves to review.sentMetastring"Just now"Meta line under messages you send.labelstring"Voice messages"Accessible name of the whole recorder.classNamestring–Class on the root section.- EnterorSpace
- Activate the focused control: record, stop, send, play, or discard. Focus follows from mic to stop to send and back.
- Escape
- Discard the take while recording or reviewing.
- The recorder is a labelled section with a labelled message list; every control is a native button with an aria-label, such as "Stop recording at 0:04" or "Play voice message from Sam, 0:07".
- Recording, review, send, and discard are announced in a polite live region that also describes the mic.
- Waveforms, the live canvas, and timers are aria-hidden; the button labels carry the durations.
- Mic, recording bar, review, and sent bubble share one layout id, so a take morphs from the mic into the thread on a spring.
- The live waveform scrolls on a canvas and playback fills the bars left to right; side buttons pop in and content crossfades with a slight blur.
- Motion follows the user's reduced motion setting: layout morphs are skipped, the waveform steps instead of growing, and the thread scrolls without smoothing.
- The recorder fills its container width, and the review waveform flexes its bars between 1.5px and 3px to fit.
- Waveforms keep touch-action pan-y, so scrubbing by tap works without blocking scroll.
- Recording is simulated; the live waveform is painted to a canvas each frame only while recording.
- Each message runs its own frame callback that returns early unless playing; long threads are not virtualized.
Notes for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Use for voice notes in chats, comments, or field notes where speaking beats typing. Audio is simulated; add MediaRecorder capture and upload in onSend before shipping.
- Seed history with voicePeaks for deterministic bars. Messages live in internal state, so persist them from onSend and pass them back as defaultMessages.
The full library index for assistants is at /llms.txt.