[go: up one dir, main page]

v2.9.0 · 7.6 kB

UI sound effects, performed live.

Comics had to draw the KA-CHUNK. Your buttons get to make it. Foley is a JavaScript library of 28 cues, synthesized with Web Audio the moment someone clicks, types, or toggles. No audio files, no dependencies.

$ npm install @foleyjs/core
Get started
Click anywhere once to unlock audio.
Letters pageAll letters 100% synthesized, like everything else on this page.
I removed the entire visual UI. The app is sound only now. Revenue tripled.
a founder who has gone too far
We A/B tested ‘thock’. The B group unionized.
a growth lead, under oath
My cat answers to ‘chime’ now. I no longer control this household.
a cat owner, formerly in charge
The ‘denied’ thud healed something in me.
someone’s therapist, confused but supportive
I played ‘complete’ at my wedding. Even the CI pipeline wept.
a groom, deployed successfully
I put it on my smart fridge. ‘warning’ plays at 2am. I’ve lost ten pounds.
an unverifiable success story

28 cues in 7 families. Press any of them.

Each family has its own material: noise for touch, glides for motion, harmonics for news. Every cue has a key, so you can also just start typing.

Reshapes all 28 cues at once. Exports follow.
Global loudness for every cue.
Shift the library ±12 semitones.
Synthesized room reverb.

Keyboard mode: 1–0, Q–P, A–K. The download button on each cue saves a 16-bit .wav with your current transpose, space, and theme, ready for Figma, video, or a native app.

Hear it on real controls.

A cue sounds different on a grid of samples than on a button you meant to press. Every control here uses the same attributes and calls you would ship.

Two-part press

Down and up are different sounds, so a click feels like a mechanism. Hold it: the release waits for you.

autosave off
data-foley-press · data-foley-release

Toggle

A click and a clack. On and off are siblings, not twins, so you hear the state without looking.

notifications off
data-foley-toggle

Hover ticks

A grain of feedback as the pointer crosses each option. Turn on “play cues on hover” above to hear it.

data-foley-hover="tick"

Typing

A soft mechanical thock per keystroke and a flourish on Enter. Try writing a sentence.

data-foley-type="thock"

Notifications

Toasts sound because they mounted. The page never calls play() for them; observe() hears them arrive.

data-foley-enter="ping"

Progress

Ticks while the work happens, a rise as it finishes, then the arrival chord. Start an upload.

Drop a file · or click to simulate
play("rise") → play("complete")

Stepper

The same tick, re-pitched with the count, so quantity has a contour. Go past the limits to hear “denied”.

2
seats (1–8)
play("tick", { pitch })

Slider

Detent ticks that rise in pitch with the value: the sound of a thumb wheel.

brightness 40%
play("tick", { pitch })

Not your sound? Redraw it.

Four plain dials reshape any cue while you listen. Export a .wav or JSON, share it as a link, or apply it site-wide as a sound set your app loads in one line.

no overrides yet

Space replays. Exports honor your transpose, space, and theme, and designs live in the URL, so a copied link carries the sound.

Install, add an attribute, bind. That's the job.

Foley ships as one ES module. Attributes cover the common cases, play() covers the rest, and the React and Vue bindings wrap the same core.

1

Install

$ npm install @foleyjs/core
2

Mark up and bind

<!-- one attribute per behavior -->
<button data-foley-press data-foley-release>Save</button>
<a data-foley-hover="tick">Docs</a>
<button data-foley-toggle>Dark mode</button>
<input data-foley-type="thock">
<!-- and things nobody clicked -->
<div data-foley-enter="bubble">Saved</div>
import { bind, observe, play, set } from "@foleyjs/core";

bind();                     // wires every data-foley-*
observe();                  // …and elements appearing or changing state
set({ volume: 0.7,          // 0 – 1
      transpose: 0,         // semitones, ±12
      space: 0.2,           // reverb send
      theme: "glass" });    // a name, or your sound set object

play("complete");           // any of the 28 cues
set({ theme: brandSet });   // load your identity from the designer
play("tick", { pitch: 4, volume: 0.3 });

const wav = await toWav("chime"); // Blob, rendered offline
3

In React or Vue

// npm install @foleyjs/react
import { useFoley } from "@foleyjs/react";

function App() {
  const { play } = useFoley({ volume: 0.7 });
  return <button  => play("success")}>
    Save
  </button>;
}
// npm install @foleyjs/vue
import { FoleyPlugin } from "@foleyjs/vue";
app.use(FoleyPlugin, { theme: "soft" });

<!-- then in any template -->
<button v-foley="'success'">Save</button>
<a v-foley:hover="'tick'">Docs</a>

Questions people actually ask.

The short answers. The docs have the long ones, and agents.md has the version for your coding agent.

Does Foley ship audio files?

No. Every cue is built at play time from Web Audio oscillators and filtered noise, so there is nothing to download, cache, or license.

How do I add a sound to a button?

Add an attribute such as data-foley-press and call bind() once at startup. It delegates from the root, so markup rendered later sounds too, and hover also fires on keyboard focus.

Will UI sounds annoy my users?

Foley is built not to. A master limiter caps loudness, a 60 ms cooldown stops repeats from stacking, pitch is humanized up to 30 cents, loops go quiet in background tabs, and set({ muted: true }) silences everything.

Does it work with React and Vue?

Yes. @foleyjs/react provides a useFoley() hook and @foleyjs/vue a plugin and a v-foley directive. Both wrap the same core, so cues and sound sets carry over.

Can I design my own sounds?

Yes. Cues are data. Edit one in the designer above or with getSpec() and playSpec(), then ship a sound set: your product's sonic identity as JSON.

Why does nothing play until I click?

Browsers block audio until a user gesture. bind() installs a one-time unlock listener, and play() resumes the audio context on its own.

That's the whole library.

One module, 28 cues, and a designer for the sounds it doesn't have yet. Your interface has been miming long enough.

$ npm install @foleyjs/core