DEV Community

Romain SIMON
Romain SIMON

Posted on

How I designed an open-source semantic sound system for interfaces

UI SFX — open-source interface sound effects

Most UI sound libraries start with files: click.mp3, pop.mp3, ding.mp3.

That works until a product needs a coherent sound language. A save action should mean the same thing whether the product feels minimal, playful, cinematic, or calm. The file is an implementation detail; the product event is the stable API.

I built UI SFX around that idea: an open-source semantic sound system with 78 interaction cues, 12 sonic personalities, and 936 CC0 MP3/Ogg assets for web apps, mobile apps, SaaS products, and games.

Start with meaning, not filenames

The public API describes what happened:

import { createUISFX } from 'uisfx'

const ui = createUISFX({ pack: 'minimal' })

saveButton.addEventListener('click', () => {
  ui.play('success')
})
Enter fullscreen mode Exit fullscreen mode

The same success event can be rendered by the Minimal, Arcade, Studio, Zen, or Cinematic pack without changing product code.

That gives sound the same separation of concerns we expect from visual design tokens: the semantic layer remains stable while the presentation layer can change.

A taxonomy that covers real product states

The library organizes 78 cues into 13 categories:

  • Input
  • Selection
  • Navigation
  • Editing
  • Movement
  • Communication
  • Feedback
  • Progress
  • Loops
  • Media
  • System
  • Reward
  • Commerce

Each category contains six cues. This is deliberately broader than button clicks: products also need distinct sounds for confirmation, undo, errors, connection changes, recording, loading, checkout, achievements, and more.

One-shots and loops need different APIs

Most interface sounds are brief one-shots. Continuous states are different: recording, loading, syncing, or an active connection must return something the interface can stop.

const recording = ui.play('recording')

// Later
recording?.stop()
Enter fullscreen mode Exit fullscreen mode

A loop must also restart in the newly selected pack when the product changes sonic personality. That behavior belongs in the runtime, not in every component using it.

ui.setPack('arcade')
Enter fullscreen mode Exit fullscreen mode

Small runtime, large library

The runtime is dependency-free and about 10.2 kB. Audio is loaded on demand, so the application does not download all 936 assets up front.

The package includes:

  • 72 one-shot cues per pack
  • 6 seamless loops per pack
  • MP3 and Ogg formats
  • TypeScript support
  • volume and mute controls
  • runtime pack switching

Install it with:

npm install uisfx
Enter fullscreen mode Exit fullscreen mode

Browsers still require user intent

One practical constraint matters: browsers often block audio before the first user gesture. A sound library should not pretend that autoplay policy does not exist.

UI SFX unlocks audio from a legitimate interaction, preloads common hover cues, and keeps sound optional. Interfaces still need visual and textual feedback; sound is an additional channel, never the only one.

It also respects reduced-motion-style product expectations: delightful feedback should never become compulsory noise. Users need mute and volume controls.

Twelve personalities, one event model

The current packs range from restrained to expressive:

Minimal, Soft, Glass, Arcade, Sci-Fi, Organic, Luxury, Paper, Rubber, Cinematic, Studio, and Zen.

The point is not novelty. It is to let a product choose a coherent sonic character while preserving the same event vocabulary. A design system can then change personality without rewriting interaction logic.

Try it

The interactive site lets you audition every cue across every pack:

UI SFX is open source and the audio assets are CC0. I would love feedback on the taxonomy, the runtime API, and which product states still need a better semantic cue.

Top comments (0)