fix: add state to pause existing audio for demo menus, add support fo… (#10428)

This commit is contained in:
Joseph Campuzano
2026-01-24 12:16:53 -06:00
committed by GitHub
parent 32e6bcae3b
commit 15801a01ba
3 changed files with 35 additions and 7 deletions

View File

@@ -7,6 +7,26 @@ import { useSettings, monoFontFamily } from "@/context/settings"
import { playSound, SOUND_OPTIONS } from "@/utils/sound"
import { Link } from "./link"
let demoSoundState = {
cleanup: undefined as (() => void) | undefined,
timeout: undefined as NodeJS.Timeout | undefined,
}
// To prevent audio from overlapping/playing very quickly when navigating the settings menus,
// delay the playback by 100ms during quick selection changes and pause existing sounds.
const playDemoSound = (src: string) => {
if (demoSoundState.cleanup) {
demoSoundState.cleanup();
}
clearTimeout(demoSoundState.timeout)
demoSoundState.timeout = setTimeout(() => {
demoSoundState.cleanup = playSound(src)
}, 100)
}
export const SettingsGeneral: Component = () => {
const theme = useTheme()
const language = useLanguage()
@@ -211,12 +231,12 @@ export const SettingsGeneral: Component = () => {
label={(o) => language.t(o.label)}
onHighlight={(option) => {
if (!option) return
playSound(option.src)
playDemoSound(option.src)
}}
onSelect={(option) => {
if (!option) return
settings.sounds.setAgent(option.id)
playSound(option.src)
playDemoSound(option.src)
}}
variant="secondary"
size="small"
@@ -235,12 +255,12 @@ export const SettingsGeneral: Component = () => {
label={(o) => language.t(o.label)}
onHighlight={(option) => {
if (!option) return
playSound(option.src)
playDemoSound(option.src)
}}
onSelect={(option) => {
if (!option) return
settings.sounds.setPermissions(option.id)
playSound(option.src)
playDemoSound(option.src)
}}
variant="secondary"
size="small"
@@ -259,12 +279,12 @@ export const SettingsGeneral: Component = () => {
label={(o) => language.t(o.label)}
onHighlight={(option) => {
if (!option) return
playSound(option.src)
playDemoSound(option.src)
}}
onSelect={(option) => {
if (!option) return
settings.sounds.setErrors(option.id)
playSound(option.src)
playDemoSound(option.src)
}}
variant="secondary"
size="small"

View File

@@ -106,5 +106,12 @@ export function soundSrc(id: string | undefined) {
export function playSound(src: string | undefined) {
if (typeof Audio === "undefined") return
if (!src) return
void new Audio(src).play().catch(() => undefined)
const audio = new Audio(src)
audio.play().catch(() => undefined)
// Return a cleanup function to pause the sound.
return () => {
audio.pause()
audio.currentTime = 0
}
}

View File

@@ -105,6 +105,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">)
}}
onPointerEnter={() => move(itemProps.item.rawValue)}
onPointerMove={() => move(itemProps.item.rawValue)}
onFocus={() => move(itemProps.item.rawValue)}
>
<Kobalte.ItemLabel data-slot="select-select-item-label">
{local.children