Audit interface sound feedback for UX quality, accessibility, and practical implementation patterns.
Real-world examples
Live HTML demos for this skill — rendered directly in the page. 4 examples.
- 01
Accessible sound preferences
Mute toggle, independent volume, prefers-reduced-motion gate, and a visual status chip that always mirrors the audio cue.
- 02
When sound is appropriate
Confirmations and errors get cues; typing, hover, and scroll stay silent — side-by-side pass/fail of the appropriateness matrix.
- 03
Preload & rapid replay
Buffers synthesized cues on init, defaults to subtle volume (0.3), and resets playback so rapid clicks never stall.
- 04
Sound weight matches action
Soft click for a toggle, short chime for purchase, gentle alert for validation — never a triumphant fanfare or punishing buzzer.
Skill markdown
# Sounds on the Web
Review UI code for audio feedback best practices and accessibility.
## How It Works
1. Read the specified files (or prompt user for files/pattern)
2. Check against all rules below
3. Output findings in `file:line` format
## Rule Categories
| Priority | Category | Prefix |
|----------|----------|--------|
| 1 | Accessibility | `a11y-` |
| 2 | Appropriateness | `appropriate-` |
| 3 | Implementation | `impl-` |
| 4 | Weight Matching | `weight-` |
## Rules
### Accessibility Rules
#### `a11y-visual-equivalent`
Every audio cue must have a visual equivalent; sound never replaces visual feedback.
**Fail:**
```tsx
function SubmitButton({ onClick }) {
const handleClick = () => {
playSound("success");
onClick(); // No visual confirmation
};
}
```
**Pass:**
```tsx
function SubmitButton({ onClick }) {
const [status, setStatus] = useState("idle");
const handleClick = () => {
playSound("success");
setStatus("success"); // Visual feedback too
onClick();
};
return <button data-status={status}>Submit</button>;
}
```
#### `a11y-toggle-setting`
Provide explicit toggle to disable sounds in settings.
**Fail:**
```tsx
// No way to disable sounds
function App() {
return <SoundProvider>{children}</SoundProvider>;
}
```
**Pass:**
```tsx
function App() {
const { soundEnabled } = usePreferences();
return (
<SoundProvider enabled={soundEnabled}>
{children}
</SoundProvider>
);
}
```
#### `a11y-reduced-motion-check`
Respect prefers-reduced-motion as proxy for sound sensitivity.
**Fail:**
```tsx
function playSound(name: string) {
audio.play(); // Plays regardless of preferences
}
```
**Pass:**
```tsx
function playSound(name: string) {
const prefersReducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
if (prefersReducedMotion) return;
audio.play();
}
```
#### `a11y-volume-control`
Allow volume adjustment independent of system volume.
**Fail:**
```tsx
function playSound() {
audio.volume = 1; // Always full volume
audio.play();
}
```
**Pass:**
```tsx
function playSound() {
const { volume } = usePreferences();
audio.volume = volume; // User-controlled
audio.play();
}
```
### Appropriateness Rules
#### `appropriate-no-high-frequency`
Do not add sound to high-frequency interactions (typing, keyboard navigation).
**Fail:**
```tsx
function Input({ onChange }) {
const handleChange = (e) => {
playSound("keystroke"); // Annoying on every keystroke
onChange(e);
};
}
```
**Pass:**
```tsx
function Input({ onChange }) {
// No sound on typing - visual feedback only
return <input onChange={onChange} />;
}
```
#### `appropriate-confirmations-only`
Sound is appropriate for confirmations: payments, uploads, form submissions.
**Pass:**
```tsx
async function handlePayment() {
await processPayment();
playSound("success"); // Appropriate - significant action
showConfirmation();
}
```
#### `appropriate-errors-warnings`
Sound is appropriate for errors and warnings that can't be overlooked.
**Pass:**
```tsx
function handleError(error: Error) {
playSound("error"); // Appropriate - needs attention
showErrorToast(error.message);
}
```
#### `appropriate-no-decorative`
Do not add sound to decorative moments with no informational value.
**Fail:**
```tsx
function Card({ onHover }) {
return (
<div onMouseEnter={() => playSound("hover")}> {/* Decorative, no value */}
{children}
</div>
);
}
```
#### `appropriate-no-punishing`
Sound should inform, not punish; avoid harsh sounds for user mistakes.
**Fail:**
```tsx
function ValidationError() {
playSound("loud-buzzer"); // Punishing
return <span>Invalid input</span>;
}
```
**Pass:**
```tsx
function ValidationError() {
playSound("gentle-alert"); // Informative but not harsh
return <span>Invalid input</span>;
}
```
### Implementation Rules
#### `impl-preload-audio`
Preload audio files to avoid playback delay.
**Fail:**
```tsx
function playSound(name: string) {
const audio = new Audio(`/sounds/${name}.mp3`); // Loads on demand
audio.play();
}
```
**Pass:**
```tsx
const sounds = {
success: new Audio("/sounds/success.mp3"),
error: new Audio("/sounds/error.mp3"),
};
// Preload on app init
Object.values(sounds).forEach(audio => audio.load());
function playSound(name: keyof typeof sounds) {
sounds[name].currentTime = 0;
sounds[name].play();
}
```
#### `impl-default-subtle`
Default volume should be subtle, not loud.
**Fail:**
```tsx
const DEFAULT_VOLUME = 1.0; // Too loud
```
**Pass:**
```tsx
const DEFAULT_VOLUME = 0.3; // Subtle default
```
#### `impl-reset-current-time`
Reset audio currentTime before replay to allow rapid triggering.
**Fail:**
```tsx
function playSound() {
audio.play(); // Won't replay if already playing
}
```
**Pass:**
```tsx
function playSound() {
audio.currentTime = 0;
audio.play();
}
```
### Weight Matching Rules
#### `weight-match-action`
Sound weight should match acti
…More from raphaelsalaja
- 12 Principles Of AnimationApply Disney's 12 animation principles to web interfaces to make motion feel natural, organic, and human.
- Generating Sounds With AiAudit Web Audio API code for procedural sound synthesis quality, UX decisions, and parameter best practices.
- Mastering Animate PresenceAudit Motion and Framer Motion exit/presence patterns with practical fixes for AnimatePresence usage.
- Morphing IconsBuild icon components that morph between SVG shapes with smooth, line-based transformation.
- Pseudo ElementsAudit CSS pseudo-elements and View Transitions usage for hover effects, decorative layers, and transitions.
- To Spring Or Not To SpringAudit animation timing choices to decide when springs versus easing curves produce better motion.