mcpField
S
sounds-on-the-web

sounds-on-the-web

github.com/raphaelsalajaデザイン・UI42212 回インストール今日更新
リポジトリ

sounds-on-the-web について

sounds-on-the-web は、音によるフィードバックを使う UI コードを、アクセシビリティ、適切性、実装、音の重さの観点から確認するスキルです。音の妥当性や、視覚的な通知とユーザー設定の有無を点検できます。

主な機能

  1. 01音声のアクセシビリティ確認
  2. 02音を使う場面の評価
  3. 03音声実装のレビュー
  4. 04音の重さと長さの確認
  5. 05ファイル名と行番号付きの報告

活用シーン

  1. 01UI コードの音声フィードバック監査
  2. 02設定における音量・音声制御の確認
  3. 03エラー音や確認音のレビュー

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/raphaelsalaja/skill --skill sounds-on-the-web

インストール後、Claude Code で/sounds-on-the-webを入力して読み込まれたか確認します。

詳細

Web 上のサウンド

音声フィードバックのベストプラクティスとアクセシビリティについて、UI コードをレビューします。

仕組み

  1. 指定されたファイルを読み込みます(または、ユーザーにファイル/パターンを確認します)
  2. 以下のすべてのルールに照らしてチェックします
  3. file:line 形式で指摘事項を出力します

ルールカテゴリ

優先度カテゴリプレフィックス
1アクセシビリティa11y-
2適切性appropriate-
3実装impl-
4重みの一致weight-

ルール

アクセシビリティのルール
a11y-visual-equivalent

すべての音声キューには視覚的な代替手段が必要です。サウンドが視覚的なフィードバックに取って代わることはありません。

不合格:

function 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-check

サウンドへの過敏さの代替指標として、prefers-reduced-motion を尊重します。

不合格:

function 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-control

システム音量とは独立して音量を調整できるようにします。

不合格:

function playSound() {
  audio.volume = 1; // Always full volume
  audio.play();
}

合格:

function playSound() {
  const { volume } = usePreferences();
  audio.volume = volume; // User-controlled
  audio.play();
}
適切性のルール
appropriate-no-high-frequency

タイピングやキーボード操作など、頻繁に発生するインタラクションにはサウンドを追加しません。

不合格:

function 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-only

支払い、アップロード、フォーム送信などの確認には、サウンドが適しています。

合格:

async function handlePayment() {
  await processPayment();
  playSound("success"); // Appropriate - significant action
  showConfirmation();
}
appropriate-errors-warnings

見落とされる可能性のあるエラーや警告には、サウンドが適しています。

合格:

function handleError(error: Error) {
  playSound("error"); // Appropriate - needs attention
  showErrorToast(error.message);
}
appropriate-no-decorative

情報としての価値がない装飾的な場面には、サウンドを追加しません。

不合格:

function Card({ onHover }) {
  return (
    <div onMouseEnter={() => playSound("hover")}> {/* Decorative, no value */}
      {children}
    </div>
  );
}
appropriate-no-punishing

サウンドは罰するためではなく、情報を伝えるためのものです。ユーザーのミスに対して不快なサウンドを鳴らすことは避けます。

不合格:

function 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-audio

再生の遅延を防ぐため、音声ファイルを事前に読み込みます。

不合格:

function 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-subtle

デフォルトの音量は大きくせず、控えめにします。

不合格:

const DEFAULT_VOLUME = 1.0; // Too loud

合格:

const DEFAULT_VOLUME = 0.3; // Subtle default
impl-reset-current-time

すばやく再生できるよう、再生し直す前に音声の currentTime をリセットします。

不合格:

function 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

サマリーテーブル

指摘事項の後に、次のサマリーを出力します。

ルール件数重大度
a11y-visual-equivalent2高
appropriate-no-high-frequency1高
impl-preload-audio3中

サウンドの適切性マトリックス

インタラクションサウンド理由
支払い成功あり重要な確認
フォーム送信ありユーザーに安心感を与える必要がある
エラー状態あり見落とされてはならない
通知あり画面を見ていない可能性がある
ボタンのクリック場合による重要なボタンに限る
タイピングなし頻度が高すぎる
ホバーなし装飾的なものにすぎない
スクロールなし頻度が高すぎる
ナビゲーションなしキーボード操作では音がうるさくなる

参考資料

コメント