Hold to Record, animated React component
A press-and-hold voice button that grows into a live waveform with a timer, cancels when you slide away, and settles into a playable voice note.
- Free
- Inputs & Controls
- Spring
Play with it
Move the controls and watch it change. Copy code gives you a snippet with only the props you changed.
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
| onRecorded | (result: { durationMs: number; levels: number[] }) => void | — | Called when a recording is kept. levels holds loudness samples from 0 to 1. |
| onCancel | () => void | — | Called when a recording is cancelled by sliding left or pressing Escape. |
| onDelete | () => void | — | Called when the kept voice note is deleted. |
| maxDuration | number | 60000 | Recording stops by itself after this many milliseconds. |
| minDuration | number | 400 | Holds shorter than this are ignored. |
| useMicrophone | boolean | false | Drive the waveform from the real microphone (asks for permission). Simulated otherwise. |
| cancelDistance | number | 90 | How far to slide left, in pixels, before releasing cancels. |
| label | string | "Hold to record" | Button label. |
| accent | string | "#ef4444" | Colour of the recording dot and the live waveform. |
| className | string | — | Extra classes on the wrapper. |
Add it to your project
- 1
Prepare your project
You need Tailwind CSS and the
@/import alias. If shadcn isn't set up yet, initialise it once:npx shadcn@latest init
Then add the Nexus registry to your
components.json(theregistrieskey is the part that matters):{ "$schema": "https://ui.shadcn.com/schema.json", "style": "default", "rsc": true, "tsx": true, "tailwind": { "css": "src/app/globals.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" }, "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" }, "registries": { "@nexus-labs": "https://www.nexus-ui.com/api/registry/{name}" } } - 2
Add the component
Run this from your project root. It adds the component, the utilities it uses and its packages.
npx shadcn@latest add @nexus-labs/hold-to-record
- 3
Check what was added
With the standard aliases, these files land in your project:
components/hold-to-record/hold-to-record.tsxindex.ts - 4
Copying by hand? Install the packages
Skip this if you used the command above.
npm install framer-motion lucide-react
- 5
Use it in a page
Import it and render it. The Code tab above has the full example.
// app/page.tsx import { HoldToRecord } from "@/components/hold-to-record"; export default function Page() { return ( <main> <HoldToRecord /> </main> ); }