anvilsign in

collin/mahjong

master / src / ui / SoundToggle.tsx
1import type { Prefs } from '../game/prefs';
2import { useT } from './lang';
3import { play, setSoundEnabled } from '../game/sound';
4
5interface Props {
6 prefs: Prefs;
7 onPrefs: (p: Prefs) => void;
8 /** Icon only, for the cramped row of controls in the middle of the table. */
9 compact?: boolean;
10}
11
12/**
13 * Mute. Turning sound *on* plays the chime straight away — partly so the room
14 * hears how loud it is before a hand starts, partly because the browser will
15 * only start the audio hardware from inside a click like this one.
16 */
17export function SoundToggle({ prefs, onPrefs, compact }: Props) {
18 const t = useT();
19 const on = prefs.sound;
20 return (
21 <button
22 className={`btn ghost pill sound-toggle ${compact ? 'compact' : ''} ${on ? 'on' : ''}`}
23 aria-pressed={on}
24 onClick={() => {
25 // Unlock the audio hardware here, inside the click, rather than
26 // waiting for the effect that persists the preference.
27 setSoundEnabled(!on);
28 onPrefs({ ...prefs, sound: !on });
29 if (!on) play('claimWindow');
30 }}
31 >
32 <span className="spk" aria-hidden>
33 {on ? '🔊' : '🔇'}
34 </span>
35 {!compact && <span>{on ? t('音效開', 'Sound on') : t('靜音', 'Muted')}</span>}
36 </button>
37 );
38}