Agent Skills by ALSEL
Anthropic Claudeデザイン・クリエイティブ⭐ リポ 0品質スコア 50/100

accessibility-compliance

WCAG 2.2に準拠したインターフェースを実装し、モバイルアクセシビリティ、インクルーシブデザインパターン、支援技術のサポートを提供します。アクセシビリティの監査、ARIAパターンの実装、スクリーンリーダー対応の構築、またはインクルーシブなユーザー体験の確保が必要な際に使用してください。

description の原文を見る

Implement WCAG 2.2 compliant interfaces with mobile accessibility, inclusive design patterns, and assistive technology support. Use when auditing accessibility, implementing ARIA patterns, building for screen readers, or ensuring inclusive user experiences.

SKILL.md 本文

アクセシビリティコンプライアンス

すべてのユーザー(障害のあるユーザーを含む)に対応した、インクルーシブな体験を創造するためのアクセシビリティ実装をマスターします。

このスキルを使用する場合

  • WCAG 2.2 Level AA または AAA コンプライアンスを実装する
  • スクリーンリーダー対応インターフェースを構築する
  • インタラクティブコンポーネントにキーボードナビゲーションを追加する
  • フォーカス管理とフォーカストラップを実装する
  • 適切なラベリング付きのアクセシビリティフォームを作成する
  • 縮小モーション設定とハイコントラスト設定に対応する
  • モバイルアクセシビリティ機能を構築する(iOS VoiceOver、Android TalkBack)
  • アクセシビリティ監査を実施し、違反を修正する

コア機能

1. WCAG 2.2 ガイドライン

  • 認識可能性:コンテンツは異なる方法で提示できる必要があります
  • 操作可能性:インターフェースはキーボードおよび支援技術で操作できる必要があります
  • 理解可能性:コンテンツと操作が明確である必要があります
  • 堅牢性:コンテンツは現在および将来の支援技術で機能する必要があります

2. ARIA パターン

  • ロール:要素の目的を定義します(button、dialog、navigation)
  • ステート:現在の条件を示します(expanded、selected、disabled)
  • プロパティ:関係と追加情報を説明します(labelledby、describedby)
  • ライブリージョン:動的なコンテンツ変更を通知します

3. キーボードナビゲーション

  • フォーカス順序とタブシーケンス
  • フォーカスインジケーターと見える状態
  • キーボードショートカットとホットキー
  • モーダルとダイアログのフォーカストラップ

4. スクリーンリーダーサポート

  • セマンティックな HTML 構造
  • 画像の代替テキスト
  • 適切な見出し階層
  • スキップリンクとランドマーク

5. モバイルアクセシビリティ

  • タッチターゲットサイズ(最小 44x44dp)
  • VoiceOver および TalkBack 互換性
  • ジェスチャーの代替案
  • Dynamic Type サポート

クイックリファレンス

WCAG 2.2 成功基準チェックリスト

レベル基準説明
A1.1.1非テキストコンテンツに代替テキストがある
A1.3.1情報と関係がプログラムで判断可能である
A2.1.1すべての機能がキーボードアクセス可能である
A2.4.1メインコンテンツへスキップする仕組みがある
AA1.4.3コントラスト比 4.5:1(通常テキスト)、3:1(大きいテキスト)
AA1.4.11非テキストコントラスト 3:1
AA2.4.7フォーカスが視認できる
AA2.5.8ターゲットサイズ最小 24x24px(2.2 で新規)
AAA1.4.6強化コントラスト 7:1
AAA2.5.5ターゲットサイズ最小 44x44px

キーパターン

パターン 1:アクセシブルボタン

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: "primary" | "secondary";
  isLoading?: boolean;
}

function AccessibleButton({
  children,
  variant = "primary",
  isLoading = false,
  disabled,
  ...props
}: ButtonProps) {
  return (
    <button
      // ローディング中は無効化
      disabled={disabled || isLoading}
      // スクリーンリーダーにローディング状態を通知
      aria-busy={isLoading}
      // ボタンの現在の状態を説明
      aria-disabled={disabled || isLoading}
      className={cn(
        // 表示フォーカスリング
        "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
        // 最小タッチターゲットサイズ44x44px)
        "min-h-[44px] min-w-[44px]",
        variant === "primary" && "bg-primary text-primary-foreground",
        (disabled || isLoading) && "opacity-50 cursor-not-allowed",
      )}
      {...props}
    >
      {isLoading ? (
        <>
          <span className="sr-only">Loading</span>
          <Spinner aria-hidden="true" />
        </>
      ) : (
        children
      )}
    </button>
  );
}

パターン 2:アクセシブルモーダルダイアログ

import * as React from "react";
import { FocusTrap } from "@headlessui/react";

interface DialogProps {
  isOpen: boolean;
  onClose: () => void;
  title: string;
  children: React.ReactNode;
}

function AccessibleDialog({ isOpen, onClose, title, children }: DialogProps) {
  const titleId = React.useId();
  const descriptionId = React.useId();

  // Escape キーで閉じる
  React.useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === "Escape" && isOpen) {
        onClose();
      }
    };
    document.addEventListener("keydown", handleKeyDown);
    return () => document.removeEventListener("keydown", handleKeyDown);
  }, [isOpen, onClose]);

  // 開いている時は body スクロールを無効化
  React.useEffect(() => {
    if (isOpen) {
      document.body.style.overflow = "hidden";
    }
    return () => {
      document.body.style.overflow = "";
    };
  }, [isOpen]);

  if (!isOpen) return null;

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-labelledby={titleId}
      aria-describedby={descriptionId}
    >
      {/* バックドロップ */}
      <div
        className="fixed inset-0 bg-black/50"
        aria-hidden="true"
        onClick={onClose}
      />

      {/* フォーカストラップコンテナ */}
      <FocusTrap>
        <div className="fixed inset-0 flex items-center justify-center p-4">
          <div className="bg-background rounded-lg shadow-lg max-w-md w-full p-6">
            <h2 id={titleId} className="text-lg font-semibold">
              {title}
            </h2>
            <div id={descriptionId}>{children}</div>
            <button
              onClick={onClose}
              className="absolute top-4 right-4"
              aria-label="Close dialog"
            >
              <X className="h-4 w-4" />
            </button>
          </div>
        </div>
      </FocusTrap>
    </div>
  );
}

パターン 3:アクセシブルフォーム

function AccessibleForm() {
  const [errors, setErrors] = React.useState<Record<string, string>>({});

  return (
    <form aria-describedby="form-errors" noValidate>
      {/* スクリーンリーダー用エラーサマリー */}
      {Object.keys(errors).length > 0 && (
        <div
          id="form-errors"
          role="alert"
          aria-live="assertive"
          className="bg-destructive/10 border border-destructive p-4 rounded-md mb-4"
        >
          <h2 className="font-semibold text-destructive">
            次のエラーを修正してください:
          </h2>
          <ul className="list-disc list-inside mt-2">
            {Object.entries(errors).map(([field, message]) => (
              <li key={field}>
                <a href={`#${field}`} className="underline">
                  {message}
                </a>
              </li>
            ))}
          </ul>
        </div>
      )}

      {/* 必須フィールドとエラー */}
      <div className="space-y-2">
        <label htmlFor="email" className="block font-medium">
          メールアドレス
          <span aria-hidden="true" className="text-destructive ml-1">
            *
          </span>
          <span className="sr-only">(必須)</span>
        </label>
        <input
          id="email"
          name="email"
          type="email"
          required
          aria-required="true"
          aria-invalid={!!errors.email}
          aria-describedby={errors.email ? "email-error" : "email-hint"}
          className={cn(
            "w-full px-3 py-2 border rounded-md",
            errors.email && "border-destructive",
          )}
        />
        {errors.email ? (
          <p id="email-error" className="text-sm text-destructive" role="alert">
            {errors.email}
          </p>
        ) : (
          <p id="email-hint" className="text-sm text-muted-foreground">
            メールアドレスは共有しません。
          </p>
        )}
      </div>

      <button type="submit" className="mt-4">
        送信
      </button>
    </form>
  );
}

パターン 4:スキップナビゲーションリンク

function SkipLink() {
  return (
    <a
      href="#main-content"
      className={cn(
        // デフォルトでは非表示フォーカス時に表示
        "sr-only focus:not-sr-only",
        "focus:absolute focus:top-4 focus:left-4 focus:z-50",
        "focus:bg-background focus:px-4 focus:py-2 focus:rounded-md",
        "focus:ring-2 focus:ring-primary",
      )}
    >
      メインコンテンツにスキップ
    </a>
  );
}

// レイアウト内
function Layout({ children }) {
  return (
    <>
      <SkipLink />
      <header>...</header>
      <nav aria-label="Main navigation">...</nav>
      <main id="main-content" tabIndex={-1}>
        {children}
      </main>
      <footer>...</footer>
    </>
  );
}

パターン 5:お知らせ用ライブリージョン

function useAnnounce() {
  const [message, setMessage] = React.useState("");

  const announce = React.useCallback(
    (text: string, priority: "polite" | "assertive" = "polite") => {
      setMessage(""); // 再通知を確保するためクリア
      setTimeout(() => setMessage(text), 100);
    },
    [],
  );

  const Announcer = () => (
    <div
      role="status"
      aria-live="polite"
      aria-atomic="true"
      className="sr-only"
    >
      {message}
    </div>
  );

  return { announce, Announcer };
}

// 使用例
function SearchResults({ results, isLoading }) {
  const { announce, Announcer } = useAnnounce();

  React.useEffect(() => {
    if (!isLoading && results) {
      announce(`${results.length} 件の結果が見つかりました`);
    }
  }, [results, isLoading, announce]);

  return (
    <>
      <Announcer />
      <ul>{/* 結果 */}</ul>
    </>
  );
}

色コントラスト要件

// コントラスト比ユーティリティ
function getContrastRatio(foreground: string, background: string): number {
  const fgLuminance = getLuminance(foreground);
  const bgLuminance = getLuminance(background);
  const lighter = Math.max(fgLuminance, bgLuminance);
  const darker = Math.min(fgLuminance, bgLuminance);
  return (lighter + 0.05) / (darker + 0.05);
}

// WCAG 要件
const CONTRAST_REQUIREMENTS = {
  // 通常テキスト(<18pt または <14pt bold)
  normalText: {
    AA: 4.5,
    AAA: 7,
  },
  // 大きいテキスト(>=18pt または >=14pt bold)
  largeText: {
    AA: 3,
    AAA: 4.5,
  },
  // UI コンポーネントとグラフィック
  uiComponents: {
    AA: 3,
  },
};

ベストプラクティス

  1. セマンティック HTML を使用:可能な限り ARIA ではなくネイティブ要素を使用
  2. 実際のユーザーでテスト:ユーザーテストに障害のある人を含める
  3. キーボードファースト:マウスなしで機能するインタラクションを設計
  4. フォーカススタイルを無効化しない:スタイルを設定して削除しない
  5. 代替テキストを提供:すべての非テキストコンテンツに説明が必要
  6. ズームに対応:200% ズームでコンテンツが動作すること
  7. 変更を通知:動的なコンテンツにはライブリージョンを使用
  8. ユーザー設定を尊重:prefers-reduced-motion と prefers-contrast を確認

一般的な問題

  • alt テキストがない:説明なしの画像
  • 色コントラスト不足:背景に対してテキストが読みにくい
  • キーボードトラップ:フォーカスがコンポーネント内に留まる
  • ラベルがない:関連付けられたラベルのないフォーム入力
  • 自動再生メディア:ユーザーの操作なしで再生されるコンテンツ
  • アクセシビリティに対応していないカスタムコントロール:ネイティブ機能の実装が不十分
  • スキップリンクがない:繰り返しコンテンツをバイパスできない
  • フォーカス順序の問題:タブ順序が表示順序と一致しない

テストツール

  • 自動テスト:axe DevTools、WAVE、Lighthouse
  • 手動テスト:VoiceOver(macOS/iOS)、NVDA/JAWS(Windows)、TalkBack(Android)
  • シミュレーター:NoCoffee(視覚)、Silktide(様々な障害)

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
wshobson
リポジトリ
wshobson/agents
ライセンス
MIT
最終更新
不明

Source: https://github.com/wshobson/agents / ライセンス: MIT

関連スキル

汎用デザイン・クリエイティブ⭐ リポ 1,739

nano-banana-2

inference.sh CLIを通じてGoogle Gemini 3.1 Flash Image Preview(Nano Banana 2)で画像を生成します。テキストから画像を生成する機能、画像編集、最大14枚の複数画像入力、Google Searchグラウンディング機能に対応しています。トリガーワード:「nano banana 2」「nanobanana 2」「gemini 3.1 flash image」「gemini 3 1 flash image preview」「google image generation」

by openakita
汎用デザイン・クリエイティブ⭐ リポ 815

octocode-slides

洗練されたマルチファイル形式のHTMLプレゼンテーションを生成します。6段階のフロー(概要 → リサーチ → アウトライン → デザイン → 実装 → レビュー)で構成されています。各スライドは独立したHTMLファイルとなり、iframeで読み込まれます。「スライドを作成してほしい」「プレゼンテーションを作ってほしい」「HTMLスライドを生成してほしい」「デックを構築してほしい」といった依頼や、ノート・ドキュメント・コードを洗練されたプレゼンテーションに変換する際に使用できます。

by bgauryy
汎用デザイン・クリエイティブ⭐ リポ 482

gpt-image2-ppt

OpenAIのgpt-image-2を使用して、視覚的に優れたPPTスライドを生成します。Spatial Glass、Tech Blue、Editorial Monoなど10種類のキュレーション済みスタイルに対応し、ユーザーが提供したPPTXファイルを模倣するテンプレートクローンモードも搭載しています。HTMLビューアと16:9形式のPPTXファイルを出力します。プレゼンテーション、スライド、ピッチデック、投資家向けPPT、雑誌風PPTの作成依頼などで活用してください。

by JuneYaooo
Anthropic Claudeデザイン・クリエイティブ⭐ リポ 299

nano-banana

Nano Banana PRO(Gemini 3 Pro Image)およびNano Banana(Gemini 2.5 Flash Image)を使用したAI画像生成機能です。以下の場合に活用できます:(1)テキストプロンプトからの画像生成、(2)既存画像の編集、(3)インフォグラフィックス、ロゴ、商品写真、ステッカーなどのプロフェッショナルなビジュアルアセット制作、(4)複数画像での人物キャラクターの一貫性保持、(5)正確なテキスト描画を含む画像生成、(6)AI生成ビジュアルが必要なあらゆるタスク。「画像を生成」「画像を作成」「写真を作る」「ロゴをデザイン」「インフォグラフィックスを作成」「AI画像」「nano banana」またはその他の画像生成リクエストをトリガーとして機能します。

by majiayu000
Anthropic Claudeデザイン・クリエイティブ⭐ リポ 299

oiloil-ui-ux-guide

モダンでクリーンなUI/UXガイダンス・レビュースキルです。新機能や既存システム(Webアプリ)に対して、実行可能なUI/UX改善提案、デザイン原則、デザインレビューチェックリストが必要な場合に活用できます。CRAP(コントラスト・反復・配置・近接)をベースに、タスクファーストなUX、情報設計、フィードバック・システムステータス、一貫性、affordances、エラー防止・復旧、認知負荷を重視します。モダンミニマルスタイル(クリーン・余白・タイポグラフィ主導)を強制し、不要なテキストを削減、アイコンとしての絵文字を禁止し、統一されたアイコンセットから直感的で洗練されたアイコンを推奨します。

by majiayu000
Anthropic Claudeデザイン・クリエイティブ⭐ リポ 299

axiom-hig-ref

Apple Human Interface Guidelines リファレンス — 色(セマンティックカラー、カスタムカラー、パターン)、背景(マテリアル階層、ダイナミック背景)、タイポグラフィ(標準スタイル、カスタムフォント、Dynamic Type)、SF Symbols(レンダリングモード、色、多言語対応)、ダークモード、アクセシビリティ、プラットフォーム固有の考慮事項を網羅したガイドラインです。

by majiayu000
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: wshobson · wshobson/agents · ライセンス: MIT