Learn how to add click sounds to buttons with customizable volume, playback rates, and variants.
Basic Button Click
The simplest way to add a click sound to a button:
import { useSound } from "@/hooks/use-sound"
import { clickSoft } from "@/sounds/click-soft"
import { Button } from "@/components/ui/button"
export function BasicClickButton () {
const [ playClick ] = useSound ( clickSoft )
return (
< Button onClick = { playClick } >
Click Me
</ Button >
)
}
Volume Control
Adjust the volume for different button styles:
Subtle Click
Normal Click
Loud Click
import { useSound } from "@/hooks/use-sound"
import { clickSoft } from "@/sounds/click-soft"
import { Button } from "@/components/ui/button"
export function SubtleButton () {
const [ playClick ] = useSound ( clickSoft , { volume: 0.3 })
return (
< Button variant = "ghost" onClick = { playClick } >
Subtle Click
</ Button >
)
}
Dynamic Playback Rates
Create playful effects by varying the playback rate:
import { useSound } from "@/hooks/use-sound"
import { click8bit } from "@/sounds/click-8bit"
import { Button } from "@/components/ui/button"
export function PlaybackRateButtons () {
const [ playClick ] = useSound ( click8bit )
return (
< div className = "flex gap-2" >
< Button onClick = { () => playClick ({ playbackRate: 0.5 }) } >
Slow (0.5x)
</ Button >
< Button onClick = { () => playClick ({ playbackRate: 1.0 }) } >
Normal (1x)
</ Button >
< Button onClick = { () => playClick ({ playbackRate: 1.5 }) } >
Fast (1.5x)
</ Button >
< Button onClick = { () => playClick ({ playbackRate: 2.0 }) } >
Very Fast (2x)
</ Button >
</ div >
)
}
Different Click Styles
Soft Click
8-bit Click
Switch Toggle
Perfect for secondary actions and ghost buttons: import { useSound } from "@/hooks/use-sound"
import { clickSoft } from "@/sounds/click-soft"
import { Button } from "@/components/ui/button"
export function SoftClickButton () {
const [ playClick ] = useSound ( clickSoft , { volume: 0.5 })
return (
< Button variant = "ghost" onClick = { playClick } >
Cancel
</ Button >
)
}
Great for playful, retro-style interfaces: import { useSound } from "@/hooks/use-sound"
import { click8bit } from "@/sounds/click-8bit"
import { Button } from "@/components/ui/button"
export function RetroClickButton () {
const [ playClick ] = useSound ( click8bit )
return (
< Button onClick = { playClick } >
Start Game
</ Button >
)
}
Use switch sounds for toggle actions: import { useState } from "react"
import { useSound } from "@/hooks/use-sound"
import { switchOn } from "@/sounds/switch-on"
import { switchOff } from "@/sounds/switch-off"
import { Button } from "@/components/ui/button"
export function ToggleButton () {
const [ isOn , setIsOn ] = useState ( false )
const [ playSwitchOn ] = useSound ( switchOn )
const [ playSwitchOff ] = useSound ( switchOff )
const handleToggle = () => {
if ( isOn ) {
playSwitchOff ()
} else {
playSwitchOn ()
}
setIsOn ( ! isOn )
}
return (
< Button
variant = { isOn ? "default" : "outline" }
onClick = { handleToggle }
>
{ isOn ? "ON" : "OFF" }
</ Button >
)
}
Advanced: Hover + Click
Combine hover and click sounds for rich feedback:
import { useSound } from "@/hooks/use-sound"
import { hoverTick } from "@/sounds/hover-tick"
import { clickSoft } from "@/sounds/click-soft"
import { Button } from "@/components/ui/button"
export function InteractiveButton () {
const [ playHover ] = useSound ( hoverTick , { volume: 0.3 })
const [ playClick ] = useSound ( clickSoft , { volume: 0.6 })
return (
< Button
onMouseEnter = { playHover }
onClick = { playClick }
>
Interactive Button
</ Button >
)
}
Keep hover sounds subtle (volume 0.2-0.4) to avoid overwhelming users when navigating the interface.
Preventing Sound Overlap
Use the interrupt option to stop the previous sound when clicking rapidly:
import { useSound } from "@/hooks/use-sound"
import { clickSoft } from "@/sounds/click-soft"
import { Button } from "@/components/ui/button"
export function RapidClickButton () {
const [ playClick ] = useSound ( clickSoft , {
interrupt: true ,
volume: 0.7
})
return (
< Button onClick = { playClick } >
Click Me Rapidly
</ Button >
)
}
User Preference Toggle
Respect user preferences by making sounds optional:
import { useState } from "react"
import { useSound } from "@/hooks/use-sound"
import { clickSoft } from "@/sounds/click-soft"
import { Button } from "@/components/ui/button"
export function ButtonWithPreference () {
const [ soundEnabled , setSoundEnabled ] = useState ( true )
const [ playClick ] = useSound ( clickSoft , { soundEnabled })
return (
< div className = "flex gap-2 items-center" >
< Button onClick = { playClick } >
Click Me
</ Button >
< label className = "flex items-center gap-2" >
< input
type = "checkbox"
checked = { soundEnabled }
onChange = { ( e ) => setSoundEnabled ( e . target . checked ) }
/>
Enable sounds
</ label >
</ div >
)
}
Troubleshooting
No sound on mobile Safari
Mobile Safari requires a user interaction before playing audio. Make sure the sound is triggered by a click event, not on page load. // ❌ Won't work on mobile Safari
useEffect (() => {
playSound () // Called automatically
}, [])
// ✅ Works on all platforms
< Button onClick = { playSound } >
Click Me
</ Button >
Sound plays multiple times when clicking fast
Use the interrupt option to stop the previous sound: const [ playClick ] = useSound ( clickSoft , { interrupt: true })
Volume too loud or too soft
Adjust the volume option (0.0 to 1.0): const [ playClick ] = useSound ( clickSoft , { volume: 0.5 })
Or override it per click: const [ playClick ] = useSound ( clickSoft )
< Button onClick = { () => playClick ({ volume: 0.3 }) } >
Quiet Click
</ Button >
Available Click Sounds
click-soft - Very subtle and gentle (7ms)
click-8bit - Retro-style digital click (91ms)
switch-on - Upward-moving activation sound (364ms)
switch-off - Downward-moving deactivation sound (213ms)
hover-tick - Subtle hover feedback (224ms)
Install sounds individually:
npx soundcn@latest add click-soft
npx soundcn@latest add click-8bit
npx soundcn@latest add switch-on switch-off