// MuteToggleButton.tsx
// @framerSupportedLayoutWidth any-prefer-fixed
// @framerSupportedLayoutHeight fixed
import * as React from "react"
import { useRef, useState } from "react"
import { addPropertyControls, ControlType } from "framer"
import { SpeakerSimpleSlash, SpeakerSimpleLow } from "phosphor-react"
const IconMap = {
SpeakerSimpleSlash,
SpeakerSimpleLow,
} as const
type IconName = keyof typeof IconMap
interface MuteToggleButtonProps {
audioFile: string
background: string
iconColor: string
borderRadius: number
size: number
muteIcon: IconName
unmuteIcon: IconName
style?: React.CSSProperties
}
export default function MuteToggleButton({
audioFile = "https://framerusercontent.com/assets/8w3IUatLX9a5JVJ6XPCVuHi94.mp3",
background = "#FFFFFF",
iconColor = "#0099FF",
borderRadius = 30,
size = 60,
muteIcon = "SpeakerSimpleSlash",
unmuteIcon = "SpeakerSimpleLow",
style,
}: MuteToggleButtonProps) {
const audioRef = useRef(null)
const [muted, setMuted] = useState(true)
// Toggle mute/unmute **et** play si nécessaire
const handleClick = () => {
const audio = audioRef.current!
if (audio.paused) {
audio.muted = true
audio.play().catch(() => {})
}
audio.muted = !audio.muted
setMuted(audio.muted)
}
const IconComponent = IconMap[muted ? unmuteIcon : muteIcon]
return (
<div
style={{
...style,
width: size,
height: size,
background,
borderRadius,
display: "flex",
alignItems: "center",
justifyContent: "center",
cursor: "pointer",
position: "relative",
}}
>
<audio ref={audioRef} src={audioFile} preload="auto" />
<button
type="button"
onClick={handleClick}
aria-label={muted ? "Unmute" : "Mute"}
style={{
width: size,
height: size,
borderRadius: "50%",
border: "none",
background: "transparent",
display: "flex",
alignItems: "center",
justifyContent: "center",
padding: 0,
cursor: "pointer",
outline: "none",
}}
>
<IconComponent
size={size * 0.5}
color={iconColor}
weight="fill"
/>
</button>
<style>{`
/* Suppression de l’encadré bleu au focus */
button:focus {
outline: none !important;
box-shadow: none !important;
}
`}</style>
</div>
)
}
addPropertyControls(MuteToggleButton, {
audioFile: {
type: ControlType.File,
allowedFileTypes: ["mp3", "wav", "ogg"],
title: "Audio File",
defaultValue:
"https://framerusercontent.com/assets/8w3IUatLX9a5JVJ6XPCVuHi94.mp3",
},
background: {
type: ControlType.Color,
title: "Background",
defaultValue: "#FFFFFF",
},
iconColor: {
type: ControlType.Color,
title: "Icon Color",
defaultValue: "#0099FF",
},
muteIcon: {
type: ControlType.Enum,
title: "Mute Icon",
options: ["SpeakerSimpleSlash", "SpeakerSimpleLow"],
defaultValue: "SpeakerSimpleSlash",
},
unmuteIcon: {
type: ControlType.Enum,
title: "Unmute Icon",
options: ["SpeakerSimpleLow", "SpeakerSimpleSlash"],
defaultValue: "SpeakerSimpleLow",
},
borderRadius: {
type: ControlType.Number,
title: "Radius",
defaultValue: 30,
min: 0,
max: 60,
},
size: {
type: ControlType.Number,
title: "Size",
defaultValue: 60,
min: 32,
max: 120,
unit: "px",
},
})