mcpField
T
typo3-accessibility

typo3-accessibility

github.com/dirnbauerデザイン・UI3348 回インストール13 週間前に更新
リポジトリ

typo3-accessibility について

TYPO3 Accessibility は、TYPO3 v14 サイトを WCAG 2.2 AA に照らして監査・改善する技能です。公開前チェックリスト、監査手順、アクセシブルな Fluid テンプレート例を備え、自動検査の証拠と人による確認事項を区別します。

主な機能

  1. 01WCAG 2.2 AA 公開前チェックリスト
  2. 02axe-core による監査手順
  3. 03キーボード操作とセマンティクスの確認
  4. 04アクセシブルな Fluid テンプレート例
  5. 05監査根拠と追加確認事項の報告

活用シーン

  1. 01公開前のアクセシビリティ確認
  2. 02レンダリング済み TYPO3 ページの監査
  3. 03キーボード操作とフォームの確認
  4. 04監査結果と未確認事項の記録

インストール

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

$npx skills add https://github.com/dirnbauer/webconsulting-skills --skill typo3-accessibility

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
03-php-accessibility-middleware-and-helpers.md
04-javascript-accessible-widgets.md
05-css-focus-and-contrast-essentials.md
06-typo3-specific-configuration.md
07-testing-and-tools.md
08-accessibility-extensions.md
09-wcag-2-2-quick-reference.md
10-anti-patterns-flag-these-in-reviews.md
credits-and-attribution.md
full-guide.md
related-skills.md
v14-only-accessibility-changes.md
scripts/
wcag22_audit.cjs

詳細

TYPO3 アクセシビリティ(WCAG 2.2 AA)

出典:https://github.com/dirnbauer/webconsulting-skills

互換性: TYPO3 v14.x のみに対応しています。このコレクションの対象に旧バージョンのコアは含まれません。

TYPO3 API を優先: カスタムマークアップを追加する前に、必ず TYPO3 の組み込み API、Fluid ViewHelper、コア機能を使用してください。メソッドが TYPO3 v14 に存在することを確認してください。

TypoScript より PHP と JS を優先: このスキルでは、PHP ミドルウェア、Fluid パーシャル、バニラ JavaScript のソリューションを提供します。TypoScript の例は使用せず、PHP ベースの手法を使用してください。

1. アクセシビリティチェックリスト(公開前の確認項目)

デプロイの前に、このチェックリストを確認してください。項目を修正したらチェックを付けます。

セマンティックな構造
  • すべてのページに <h1> がちょうど 1 つある
  • 見出しの階層が順番になっている(h1 > h2 > h3、飛ばさない)
  • ランドマーク要素を使用している:<main>、<nav>、<header>、<footer>、<aside>
  • スキップリンクが最初にフォーカス可能な要素になっている
  • <html lang="..."> がページの言語と一致している
  • コンテンツ内で言語が変わる箇所では、包含要素に lang 属性を使用している
画像とメディア
  • すべての <img> に alt 属性がある(装飾目的の場合は alt="")
  • すべての <img> に明示的な width と height がある(CLS を防止)
  • 複雑な画像(グラフ、インフォグラフィック)に長い説明がある
  • 動画にキャプション/字幕がある
  • 音声コンテンツに文字起こしがある
  • 音声付きのメディアを自動再生しない
色とコントラスト
  • テキストのコントラスト比が 4.5:1 以上(通常のテキスト)/3:1 以上(大きなテキスト:24px 以上/太字で 18.66px 以上)
  • UI コンポーネントとグラフィックオブジェクトのコントラスト比が 3:1 以上
  • 色だけで情報を伝えない(アイコン、テキスト、またはパターンを追加する)
  • ダークモード(実装している場合)でもコントラスト比を維持している
キーボード操作とフォーカス
  • すべてのインタラクティブ要素に Tab キーで移動できる
  • フォーカス順が視覚的な順序と一致している
  • すべてのインタラクティブ要素に視認できるフォーカスインジケーターがある(:focus-visible)
  • モーダルを除き、フォーカストラップがない(モーダルでは適切にトラップする必要があります)
  • Escape キーでモーダル/オーバーレイが閉じ、トリガーにフォーカスが戻る
  • カスタムウィジェットに適切なキーボードハンドラーがある
フォーム
  • すべての入力にプログラムで関連付けられた <label> がある(明示的な for/id、またはラップで関連付ける)
  • プレースホルダーを唯一のラベルとして使用していない
  • 必須フィールドが視覚的に示され、required 属性も指定されている
  • エラーメッセージが aria-describedby と aria-invalid で入力に関連付けられている
  • フォームグループで <fieldset> と <legend> を使用している
  • 入力に適切な type 属性と autocomplete 属性がある
ARIA と動的コンテンツ
  • アイコンのみのボタンに aria-label がある
  • 装飾アイコンに aria-hidden="true" がある
  • 動的な更新で aria-live="polite" または role="status" を使用している
  • エラー通知で role="alert" を使用している
  • アクティブなナビゲーションリンクに aria-current="page" がある
  • 展開可能な要素で aria-expanded を使用している
モーションとインタラクション
  • prefers-reduced-motion に対応している(CSS と JS)
  • コンテンツが 1 秒あたり 3 回を超えて点滅しない
  • タッチターゲットが WCAG 2.2 AA 2.5.8 の要件を満たしている(最小 24×24 CSS ピクセル)。実現可能な場合は、より快適な基準として 44×44 を使用する
  • ビューポートのメタタグで user-scalable=no を設定していない
TYPO3 固有の項目
  • バックエンド:File List のすべての画像で代替テキスト欄が入力されている
  • バックエンド:コンテンツ要素に内容を表すヘッダーがある(非表示にする場合は header_layout = 100)
  • バックエンド:ページプロパティに適切な <title> と description が設定されている
  • Fluid テンプレートで <f:link.page>/<f:link.typolink> を使用している(手動で href を指定した <a> ではなく)
  • Content Block/Content Element のテンプレートが、以下のアクセシブルなパターンに従っている

2. WCAG 2.2 適合性監査のワークフロー

WCAG 2.2 の監査を依頼された場合は、作業を引き渡す前にエージェントが実施できることを行います。

  1. 監査対象の URL、言語、ビューポート、フォーム、ダイアログ、メニュー、メディア、ダウンロード、サードパーティの埋め込みコンテンツを特定します。
  2. axe-core の WCAG 2.0/2.1/2.2 A/AA タグを指定して、レンダリングされたページに対し scripts/wcag22_audit.cjs を実行します。
  3. 自動検出されたすべての違反と incomplete 項目を確認し、修正するか、内容を記録します。監査スクリプトは、可能な場合、color-contrast の incomplete ノードのコントラストを計算します。対応をエスカレーションする前に、その結果を利用してください。未解決の incomplete を合格として扱わないでください。
  4. セマンティックな構造、ページの言語、ランドマーク、<h1> が1つであること、見出しの順序、スキップリンク、画像の alt、画像の寸法、ビューポートのズーム、フッター/ヘッダーのナビゲーション、フォーカス可能性、ターゲットサイズの候補、インラインテキストリンクに関するターゲットサイズの例外を確認します。
  5. 可能な場合は、実際に Tab キーで移動してキーボード操作の順序を確認します。明らかなテンプレート/コンポーネントの不具合は、すぐに修正します。
  6. 次の2つのセクションを含む監査レポートを作成します。
    • エージェントが完了した検証結果: コマンド、URL、ビューポート、ツールのバージョン、違反、修正、残存する技術的リスク。
    • 人間/ユーザーのみが行うフォローアップ: スクリーンリーダーでの確認、法的声明の承認、該当する場合に限り、特定デバイスのみで行う作業、サードパーティ/PDF/メディア、ユーザーテストに関する作業。

適合性監査を依頼された場合は、Testing & Tools の詳細な手順に従ってください。自動テストの実行に成功しても、WCAG 適合性を主張できるわけではありません。自動化とコード検査で確認できる範囲についての証拠となります。

3. Fluid テンプレートのパターン

3.1 ランドマークを使用したページレイアウト


<f:render section="Main" />

<f:layout name="Default" />
<f:section name="Main">

<a href="#main-content" class="skip-link">
    <f:translate key="LLL:EXT:site_package/Resources/Private/Language/locallang.xlf:skip_to_content" />
</a>

<header>
    
    <f:cObject typoscriptObjectPath="lib.mainNavigation" />
</header>

<main id="main-content">
    <f:render section="Content" />
</main>

<footer>
    <nav aria-label="{f:translate(key: 'LLL:EXT:site_package/Resources/Private/Language/locallang.xlf:nav.footer')}">
        <f:cObject typoscriptObjectPath="lib.footerNavigation" />
    </nav>
</footer>

</f:section>
3.2 スキップリンクの CSS
.skip-link {
    position: absolute;
    top: -100%;
    left: 0;
    z-index: 10000;
    padding: 0.75rem 1.5rem;
    background: var(--color-primary, #2563eb);
    color: var(--color-on-primary, #fff);
    font-weight: 600;
    text-decoration: none;
}
.skip-link:focus {
    top: 0;
}
3.3 アクセシブルな画像のレンダリング

<f:if condition="{image}">
    <figure>
        <f:image
            image="{image}"
            alt="{image.alternative}"
            title="{image.title}"
            width="{dimensions.width}"
            height="{dimensions.height}"
            loading="{f:if(condition: lazyLoad, then: 'lazy', else: 'eager')}"
            additionalAttributes="{decoding: 'async'}"
        />
        <f:if condition="{image.description}">
            <figcaption>{image.description}</figcaption>
        </f:if>
    </figure>
</f:if>

装飾用画像の場合(情報としての価値がない場合):

<f:image image="{image}" alt="" />
3.4 アクセシブルなコンテンツ要素のラッパー

<f:if condition="{data.header} && {data.header_layout} != '100'">
    <f:switch expression="{data.header_layout}">
        <f:case value="1"><h1>{data.header}</h1></f:case>
        <f:case value="2"><h2>{data.header}</h2></f:case>
        <f:case value="3"><h3>{data.header}</h3></f:case>
        <f:case value="4"><h4>{data.header}</h4></f:case>
        <f:case value="5"><h5>{data.header}</h5></f:case>
        <f:defaultCase><h2>{data.header}</h2></f:defaultCase>
    </f:switch>
</f:if>
3.5 アクセシブルなナビゲーションの部分テンプレート

<nav aria-label="{f:translate(key: 'LLL:EXT:site_package/Resources/Private/Language/locallang.xlf:nav.main')}">
    
    <ul role="list">
        <f:for each="{menu}" as="item">
            <li>
                <f:if condition="{item.active}">
                    <f:then>
                        <a href="{item.link}" aria-current="page">{item.title}</a>
                    </f:then>
                    <f:else>
                        <a href="{item.link}">{item.title}</a>
                    </f:else>
                </f:if>

                <f:if condition="{item.children}">
                    <ul>
                        <f:for each="{item.children}" as="child">
                            <li>
                                <a href="{child.link}"
                                   {f:if(condition: child.active, then: 'aria-current="page"')}>
                                    {child.title}
                                </a>
                            </li>
                        </f:for>
                    </ul>
                </f:if>
            </li>
        </f:for>
    </ul>
</nav>
3.6 アクセシブルなアコーディオン(コンテンツブロック/カスタム CE)
<div class="accordion" data-accordion>
    <f:for each="{items}" as="item" iteration="iter">
        <div class="accordion__item">
            
            <div role="heading" aria-level="{f:if(condition: headingLevel, then: headingLevel, else: '3')}">
                <button
                    type="button"
                    class="accordion__trigger"
                    aria-expanded="false"
                    aria-controls="accordion-panel-{data.uid}-{iter.index}"
                    id="accordion-header-{data.uid}-{iter.index}"
                    data-accordion-trigger
                >
                    {item.header}
                </button>
            </div>
            <div
                id="accordion-panel-{data.uid}-{iter.index}"
                role="region"
                aria-labelledby="accordion-header-{data.uid}-{iter.index}"
                class="accordion__panel"
                hidden
            >
                <f:format.html>{item.bodytext}</f:format.html>
            </div>
        </div>
    </f:for>
</div>
3.7 アクセシブルなタブコンポーネント
<div class="tabs" data-tabs>
    <div role="tablist" aria-label="{f:translate(key: 'tabs.label')}">
        <f:for each="{items}" as="item" iteration="iter">
            <button
                type="button"
                role="tab"
                id="tab-{data.uid}-{iter.index}"
                aria-controls="tabpanel-{data.uid}-{iter.index}"
                aria-selected="{f:if(condition: iter.isFirst, then: 'true', else: 'false')}"
                tabindex="{f:if(condition: iter.isFirst, then: '0', else: '-1')}"
            >
                {item.header}
            </button>
        </f:for>
    </div>

    <f:for each="{items}" as="item" iteration="iter">
        <div
            role="tabpanel"
            id="tabpanel-{data.uid}-{iter.index}"
            aria-labelledby="tab-{data.uid}-{iter.index}"
            tabindex="0"
            {f:if(condition: iter.isFirst, then: '', else: 'hidden')}
        >
            <f:format.html>{item.bodytext}</f:format.html>
        </div>
    </f:for>
</div>

詳細なリファレンス

詳細な例、長いテンプレート、トラブルシューティング用の一覧表、付録、または上記に含まれていないセクションが必要な場合は、完全ガイドをお読みください。範囲の限られたタスクでは、このファイルを読み込まず、スキルが段階的に情報を開示するようにしてください。

コメント