Loading...
Loading...
Audit UI code for audio feedback best practices. Use when reviewing sound implementation, checking audio UX decisions, or auditing accessibility. Outputs file:line findings.
npx skill4agent add raphaelsalaja/userinterface-wiki sounds-on-the-webfile:line| Priority | Category | Prefix |
|---|---|---|
| 1 | Accessibility | |
| 2 | Appropriateness | |
| 3 | Implementation | |
| 4 | Weight Matching | |
a11y-visual-equivalentfunction SubmitButton({ onClick }) {
const handleClick = () => {
playSound("success");
onClick(); // No visual confirmation
};
}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// No way to disable sounds
function App() {
return <SoundProvider>{children}</SoundProvider>;
}function App() {
const { soundEnabled } = usePreferences();
return (
<SoundProvider enabled={soundEnabled}>
{children}
</SoundProvider>
);
}a11y-reduced-motion-checkfunction playSound(name: string) {
audio.play(); // Plays regardless of preferences
}function playSound(name: string) {
const prefersReducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
if (prefersReducedMotion) return;
audio.play();
}a11y-volume-controlfunction playSound() {
audio.volume = 1; // Always full volume
audio.play();
}function playSound() {
const { volume } = usePreferences();
audio.volume = volume; // User-controlled
audio.play();
}appropriate-no-high-frequencyfunction Input({ onChange }) {
const handleChange = (e) => {
playSound("keystroke"); // Annoying on every keystroke
onChange(e);
};
}function Input({ onChange }) {
// No sound on typing - visual feedback only
return <input onChange={onChange} />;
}appropriate-confirmations-onlyasync function handlePayment() {
await processPayment();
playSound("success"); // Appropriate - significant action
showConfirmation();
}appropriate-errors-warningsfunction handleError(error: Error) {
playSound("error"); // Appropriate - needs attention
showErrorToast(error.message);
}appropriate-no-decorativefunction Card({ onHover }) {
return (
<div onMouseEnter={() => playSound("hover")}> {/* Decorative, no value */}
{children}
</div>
);
}appropriate-no-punishingfunction ValidationError() {
playSound("loud-buzzer"); // Punishing
return <span>Invalid input</span>;
}function ValidationError() {
playSound("gentle-alert"); // Informative but not harsh
return <span>Invalid input</span>;
}impl-preload-audiofunction playSound(name: string) {
const audio = new Audio(`/sounds/${name}.mp3`); // Loads on demand
audio.play();
}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-subtleconst DEFAULT_VOLUME = 1.0; // Too loudconst DEFAULT_VOLUME = 0.3; // Subtle defaultimpl-reset-current-timefunction playSound() {
audio.play(); // Won't replay if already playing
}function playSound() {
audio.currentTime = 0;
audio.play();
}weight-match-action// Loud fanfare for minor action
function handleToggle() {
playSound("triumphant-fanfare");
setEnabled(!enabled);
}// Subtle click for minor action
function handleToggle() {
playSound("soft-click");
setEnabled(!enabled);
}
// Richer sound for significant action
function handlePurchase() {
playSound("success-chime");
completePurchase();
}weight-duration-matches-action// 2-second sound for instant action
function handleClick() {
playSound("long-whoosh"); // 2000ms
// Action completes immediately
}// Short sound for instant action
function handleClick() {
playSound("click"); // 50ms
}
// Longer sound for process
function handleUpload() {
playSound("upload-progress"); // Matches upload duration
}file:line - [rule-id] description of issue
Example:
components/input/index.tsx:23 - [appropriate-no-high-frequency] Playing sound on every keystroke
lib/sounds.ts:45 - [a11y-reduced-motion-check] Not checking prefers-reduced-motion| Rule | Count | Severity |
|---|---|---|
| 2 | HIGH |
| 1 | HIGH |
| 3 | MEDIUM |
| Interaction | Sound? | Reason |
|---|---|---|
| Payment success | Yes | Significant confirmation |
| Form submission | Yes | User needs assurance |
| Error state | Yes | Can't be overlooked |
| Notification | Yes | May not be looking at screen |
| Button click | Maybe | Only for significant buttons |
| Typing | No | Too frequent |
| Hover | No | Decorative only |
| Scroll | No | Too frequent |
| Navigation | No | Keyboard nav would be noisy |