Back to library
buttons
Visualizer Button
An outline button that doubles as an audio player — five randomized bars animate while an <audio> element plays.
Inspired by ruixen.ui · View source
Preview
Copy for AI
Copy for Lovable is the fastest way to move this component into another Lovable project — it copies the full prompt with dependencies, files, and a usage example. Copy all files gives you the raw source if you want to paste it manually.
Installation
npx shadcn@latest add https://21st.dev/r/ruixen.ui/visualizer-buttonPaste into a terminal — or paste into a Lovable chat and I'll run it for you.
Source files
components/ui/visualizer-button.tsx
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"
interface VisualizerButtonProps {
audioSrc: string
width?: number
height?: number
className?: string
}
export default function VisualizerButton({
audioSrc,
width = 60,
height = 30,
className,
}: VisualizerButtonProps) {
const audioRef = React.useRef<HTMLAudioElement | null>(null)
React.useEffect(() => {
audioRef.current = new Audio(audioSrc)
return () => {
audioRef.current?.pause()
audioRef.current = null
}
}, [audioSrc])
const [isPlaying, setIsPlaying] = React.useState(false)
const [levels, setLevels] = React.useState<number[]>(Array(5).fill(0))
React.useEffect(() => {
let interval: ReturnType<typeof setInterval> | undefined
if (isPlaying) {
interval = setInterval(() => {
setLevels(levels.map(() => Math.random() * height))
}, 150)
} else {
setLevels(Array(5).fill(0))
}
return () => clearInterval(interval)
}, [isPlaying, height])
const togglePlay = () => {
const audio = audioRef.current
if (!audio) return
if (isPlaying) audio.pause()
else void audio.play()
setIsPlaying(!isPlaying)
}
return (
<Button
className={cn(
"relative flex items-end justify-between px-2 py-1",
className
)}
onClick={togglePlay}
variant="outline"
style={{ width, height }}
>
{levels.map((lvl, idx) => (
<div
key={idx}
className="bg-blue-500 dark:bg-white rounded-sm transition-all duration-150"
style={{ width: 4, height: `${lvl}px` }}
/>
))}
</Button>
)
}
Dependencies
@/components/ui/button