UI widgets

Sound layer

Seven interface sounds — hover, click, open, close, success, error, type — mapped to the events you already fire. Every one is built at runtime from oscillators, a generated noise buffer, filters and envelopes. There are no audio files to host, no licences to clear, and the whole layer weighs a few kilobytes.

Sound is off until you ask for it. The toggle in the corner is the switch, the choice is remembered, and no audio context exists until you touch the page — browsers block it otherwise, and so does this. Press H to hide the control panel.

01

The sounds

Each row is one recipe: a stack of voices, each with its own wave or noise burst, envelope, filter sweep and start offset. Change the preset in the panel to hear the same seven events rebuilt with a different palette.

EventVoicesLevel

audio context none · voices ringing 0 · sound off

02

Wired to a real interface

Nothing below calls play(). The layer listens once at the document and reads the markup: buttons and links get hover and click, anything with data-sound="open" gets the drawer sound, and typing in a field ticks.

Buttons and links

A link with hover

Result states

data-sound-click="…"

Disclosure

Typing

modifier chords stay silent

Opt out

data-sound-mute on any ancestor
03

The gate

Three rules, and the engine keeps all of them for you.

Off by default enabledByDefault is false. A first-time visitor hears nothing.
Remembered The choice is written to localStorage under your own key, and blocked storage is not an error.
Gesture first Even with sound remembered as on, no AudioContext is created until a click, tap or keypress.
Always switchable The toggle is a real button with aria-pressed, fixed on screen, reachable by keyboard at any point.
Quiet in the background Hiding the tab suspends the context; coming back resumes it.