Sound hooks
useClickSfx, useHoverSfx and useSfx give your own components the same UI sounds as the
library components. They read the nearest SfxProvider, which JarvisProvider sets up.
import { useClickSfx, useHoverSfx, useSfx } from 'jarvis-react-ui';
Usage
import { useClickSfx, useHoverSfx, useSfx } from 'jarvis-react-ui';
export default function CustomControl() {
const onMouseEnter = useHoverSfx('button');
const onClick = useClickSfx(() => undefined);
const { playOneShot } = useSfx();
return (
<>
<button
type="button"
data-sfx-hover="button"
onMouseEnter={onMouseEnter}
onClick={onClick}
className="border border-accent px-4 py-2 text-[11px] uppercase tracking-[1px] text-accent"
>
Custom control
</button>
<button
type="button"
onClick={() => playOneShot('confirm')}
className="border border-success px-4 py-2 text-[11px] uppercase tracking-[1px] text-success"
>
Play confirm
</button>
</>
);
}
useClickSfx
function useClickSfx<E>(handler?: (event: E) => void): (event: E) => void;
Wraps a click handler: plays click, then calls yours. Pass the result to onClick. The returned
function is memoized on handler.
useHoverSfx
function useHoverSfx(
target: 'button' | 'panel',
options?: { throttleMs?: number },
): (e: MouseEvent) => void;
Returns an onMouseEnter handler that plays hover_button or hover_panel, throttled to one sound
per 150ms by default. With 'panel' it stays silent while the pointer enters a child marked
data-sfx-hover="button", so a button inside a panel does not play both sounds. Mark your own
buttons with that attribute.
useSfx
function useSfx(): {
playOneShot: (event: SfxEvent) => void;
play: (event: SfxEvent) => void; // looping sounds
stop: (event: SfxEvent) => void;
};
Plays any sound event directly, e.g. confirm, error, transition or scan. The full list is the
SfxEvent type and SFX_CONFIG.
Without a provider
All three hooks work outside a provider; they simply play nothing. Components therefore never break in tests or in apps that do not want sound.
SfxProvider
SfxProvider takes playOneShot, play and stop and passes them down. Use it directly to plug in
your own audio implementation, or let JarvisProvider wire it to the
built-in audio engine.