Waveform Bars
refinery/waveform-barsFreeComponent
Mic toggle with animated waveform bars and pulse state.
Live preview
live · rendered by the registry
Rendered by refinery on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://refinery.abhii.me/r/waveform-bars.jsonSource
1"use client";23import { useState } from "react";4import { motion } from "motion/react";5import { cn } from "@/lib/utils";67const EASE: [number, number, number, number] = [0.22, 1, 0.36, 1];8const BAR_HEIGHTS = ["8px", "20px", "12px", "24px", "14px", "8px"];9const BAR_WIDTH = 6; // px - matches w-1.510const BAR_GAP = 6;1112interface WaveformBarsProps {13 color?: string;14 iconSize?: string;15 barCount?: number;16 defaultOpen?: boolean;17 open?: boolean;18 onOpenChange?: (open: boolean) => void;19}2021function isTailwindClass(value: string) {22 return /^bg-/.test(value);23}2425export default function WaveformBars({26 color = "#34d399", // Tailwind's emerald-40027 iconSize = "size-5",28 barCount = 7,29 defaultOpen = false,30 open,31 onOpenChange,32}: WaveformBarsProps) {33 const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);3435 const isControlled = open !== undefined;36 const toggled = isControlled ? open : uncontrolledOpen;37 const isTailwind = isTailwindClass(color);3839 const handleOpenChange = (newOpen: boolean) => {40 if (!isControlled) {41 setUncontrolledOpen(newOpen);42 }43 onOpenChange?.(newOpen);44 };4546 return (47 <div className="relative isolate flex items-center justify-center gap-3">48 <motion.div49 className="relative"50 animate={{ x: toggled ? -20 : 0 }}51 transition={{ duration: 0.42, ease: EASE }}52 >53 <motion.button54 onClick={() => handleOpenChange(!toggled)}55 whileHover={{ scale: toggled ? 1.02 : 1.05 }}56 whileTap={{ scale: 0.95 }}57 transition={{ duration: 0.2, ease: "easeOut" }}58 className={cn(59 "relative z-10 rounded-full p-2 text-white transition-colors duration-300",60 !toggled && "bg-neutral-800 dark:bg-neutral-100 dark:text-black",61 toggled && isTailwind && color62 )}63 style={64 toggled && !isTailwind ? { backgroundColor: color } : undefined65 }66 >67 <MicrophoneIcon className={cn("relative z-10", iconSize)} />6869 {toggled && (70 <motion.div71 className={cn(72 "pointer-events-none absolute inset-0 rounded-full opacity-20",73 isTailwind && color74 )}75 style={!isTailwind ? { backgroundColor: color } : undefined}76 initial={{ scale: 0.84 }}77 animate={{ scale: [1, 1.2, 1] }}78 transition={{ duration: 2, repeat: Infinity, ease: "easeInOut" }}79// … truncated
What it pulls in
npm packages
Files it writes
More from refinery
All 16 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Analog Clock Screensaveranalog-clock-screensaver | refinery | Components | Free | 1 dep | |
| Avatar Circleavatar-circle | refinery | Components | Free | 1 dep | |
| DVD Screensaverdvd-screensaver | refinery | Components | Free | 1 dep | |
| Floating Cardfloating-card | refinery | Components | Free | 1 dep | |
| Floating Navfloating-nav | refinery | Components | Free | 1 dep | |
| Glowy Buttonglowy-button | refinery | Components | Free | 1 dep | |
| Move To Topmove-to-top-button | refinery | Components | Free | 1 dep | |
| Notification Badgenotification-badge | refinery | Components | Free | 1 dep |
