diff --git a/.Jules/palette.md b/.Jules/palette.md index a997ba7e..755b123b 100644 --- a/.Jules/palette.md +++ b/.Jules/palette.md @@ -25,3 +25,7 @@ ## 2026-06-08 - Badge Snippet Accessible Names **Learning:** アイコンやコピーなどの汎用的なアクションを実行するボタンが複数リストされている場合、スクリーンリーダーユーザーがどの項目のアクションかを識別できるように、`aria-label` に具体的なコンテキスト(例: `Copy ${snippet.label}`)を含めることが重要です。同時に、表示されているテキスト(この場合は 'Copy')を `aria-label` に含めることで WCAG 2.5.3(Label in Name)に準拠します。 **Action:** 今後、リスト内やコンテキストが不明瞭なボタン(特に同じテキストラベルを持つ複数のボタン)を実装・改善する際は、必ず `aria-label` に詳細な説明を含めるようにします。また、以前試みた「文字数カウンターの aria-live 属性の削除」は、スクリーンリーダーユーザーへのフィードバックを完全に奪うことになりアクセシビリティを低下させる(リグレッション)ため、行わないよう注意します。 + +## 2026-06-18 - Dynamic Form Validation Accessibility +**Learning:** フォーム内の動的なバリデーションステータス(例:スラッグの使用可能確認)を伝える際、入力フィールドに `aria-describedby` を設定してステータス要素と関連付け、ステータス要素自身に `aria-live="polite"` を付与することで、スクリーンリーダーユーザーが入力状態の変化を自然に把握できるようになります。また、フォーム送信エラーなど動的に出現するエラーメッセージ要素には `role="alert"` を付与することで、表示された瞬間にユーザーへ重要な通知として読み上げられます。 +**Action:** 今後、非同期でステータスが更新される入力フィールドや動的なエラーメッセージを実装・改善する際は、`aria-describedby`、`aria-live="polite"`、`role="alert"` を適切に組み合わせてアクセシビリティを確保します。 diff --git a/apps/web/src/app/collections/new/page.tsx b/apps/web/src/app/collections/new/page.tsx index 52abae2a..33e5206b 100644 --- a/apps/web/src/app/collections/new/page.tsx +++ b/apps/web/src/app/collections/new/page.tsx @@ -290,9 +290,14 @@ export default function NewCollectionPage() { setSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, "")); }} maxLength={40} + aria-describedby="slug-status" className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm dark:border-gray-700 dark:bg-gray-900" /> -

+

{slugStatus === "checking" && "確認中..."} {slugStatus === "available" && "✓ 使用可能"} {slugStatus === "taken" && "✗ 使用済み"} @@ -347,7 +352,11 @@ export default function NewCollectionPage() { - {error &&

{error}

} + {error && ( +

+ {error} +

+ )}