🎨 Palette: 動的エラーメッセージに role="alert" を追加しアクセシビリティを向上#993
Conversation
This commit adds `role="alert"` to conditionally rendered error messages in the following components to improve screen reader accessibility: - apps/web/src/app/collections/new/page.tsx - apps/web/src/app/orgs/new/page.tsx - apps/web/src/app/papers/[id]/edit/page.tsx - apps/web/src/app/upload/page.tsx Co-authored-by: is0692vs <135803462+is0692vs@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
|
Warning Review limit reached
More reviews will be available in 57 minutes and 2 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
このリポジトリでは staging 先行フローを採用しています。PR のターゲットを |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Code Review
This pull request documents a new accessibility standard in .Jules/palette.md and adds the role="alert" attribute to dynamic error messages across several pages to improve screen reader accessibility. The review feedback suggests that dynamically mounting elements with role="alert" can prevent screen readers from reliably announcing the errors. It is recommended to keep these elements in the DOM at all times, updating only their text content and conditionally applying styles to avoid empty styled boxes.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| </div> | ||
|
|
||
| {error && <p className="text-sm text-red-600">{error}</p>} | ||
| {error && <p role="alert" className="text-sm text-red-600">{error}</p>} |
There was a problem hiding this comment.
💡 改善の提案:スクリーンリーダーでの確実な読み上げ
role="alert" を持つ要素を {error && ...} のように動的にマウント(DOMに追加)すると、一部のスクリーンリーダーやブラウザの組み合わせにおいて、エラー発生時の自動読み上げが正しくトリガーされない場合があります。
アクセシビリティのベストプラクティス(MDNの推奨事項など)では、role="alert" を持つコンテナ要素は常にDOM上に存在させておき、その中身(テキスト)を動的に更新することが推奨されています。
要素を常にDOMに残し、エラーメッセージのみを動的に流し込むように変更することを検討してください。
| {error && <p role="alert" className="text-sm text-red-600">{error}</p>} | |
| <p role="alert" className="text-sm text-red-600">{error || ""}</p> |
| </div> | ||
|
|
||
| {error && <p className="text-sm text-red-600">{error}</p>} | ||
| {error && <p role="alert" className="text-sm text-red-600">{error}</p>} |
There was a problem hiding this comment.
💡 改善の提案:スクリーンリーダーでの確実な読み上げ
role="alert" を持つ要素を動的にマウントすると、一部のスクリーンリーダーで読み上げがトリガーされないことがあります。コンテナ要素を常にDOMに配置し、テキストのみを動的に更新することで、より確実にエラーが通知されるようになります。
| {error && <p role="alert" className="text-sm text-red-600">{error}</p>} | |
| <p role="alert" className="text-sm text-red-600">{error || ""}</p> |
| {error && ( | ||
| <div className="mb-6 rounded-md bg-red-50 p-4 text-sm text-red-700 dark:bg-red-900/30 dark:text-red-400"> | ||
| <div role="alert" className="mb-6 rounded-md bg-red-50 p-4 text-sm text-red-700 dark:bg-red-900/30 dark:text-red-400"> | ||
| {error} | ||
| </div> | ||
| )} |
There was a problem hiding this comment.
💡 改善の提案:スクリーンリーダーでの確実な読み上げ
role="alert" を持つ要素を動的にマウントすると、一部のスクリーンリーダーで読み上げがトリガーされないことがあります。
スタイル適用クラス(mb-6 rounded-md bg-red-50 p-4...)を error の有無に応じて条件付きで適用することで、不要な空の赤いボックスが表示されるのを防ぎつつ、role="alert" のコンテナ要素を常にDOMに維持できます。
| {error && ( | |
| <div className="mb-6 rounded-md bg-red-50 p-4 text-sm text-red-700 dark:bg-red-900/30 dark:text-red-400"> | |
| <div role="alert" className="mb-6 rounded-md bg-red-50 p-4 text-sm text-red-700 dark:bg-red-900/30 dark:text-red-400"> | |
| {error} | |
| </div> | |
| )} | |
| <div | |
| role="alert" | |
| className={error ? "mb-6 rounded-md bg-red-50 p-4 text-sm text-red-700 dark:bg-red-900/30 dark:text-red-400" : ""} | |
| > | |
| {error} | |
| </div> |
| {error && ( | ||
| <div className="rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-950/40 dark:text-red-300"> | ||
| <div role="alert" className="rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-950/40 dark:text-red-300"> | ||
| {error} | ||
| </div> | ||
| )} |
There was a problem hiding this comment.
💡 改善の提案:スクリーンリーダーでの確実な読み上げ
role="alert" を持つ要素を動的にマウントすると、一部のスクリーンリーダーで読み上げがトリガーされないことがあります。
スタイル適用クラスを error の有無に応じて条件付きで適用することで、不要な空の赤いボックスが表示されるのを防ぎつつ、role="alert" のコンテナ要素を常にDOMに維持できます。
| {error && ( | |
| <div className="rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-950/40 dark:text-red-300"> | |
| <div role="alert" className="rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-950/40 dark:text-red-300"> | |
| {error} | |
| </div> | |
| )} | |
| <div | |
| role="alert" | |
| className={error ? "rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-950/40 dark:text-red-300" : ""} | |
| > | |
| {error} | |
| </div> |
| {error && ( | ||
| <div className="rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-950/40 dark:text-red-300"> | ||
| <div role="alert" className="rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-950/40 dark:text-red-300"> | ||
| {error} | ||
| </div> | ||
| )} |
There was a problem hiding this comment.
role="alert" を条件付きマウントで使用することの信頼性
WAI-ARIA 仕様では「ライブリージョンのコンテナ要素は、コンテンツを更新し始める前にDOMに存在していなければならない」とされています。{error && <div role="alert">...</div>} というパターンは要素ごとDOMに追加するため、古いスクリーンリーダー(古いNVDA・JAWSのバージョンなど)では読み上げが発火しない場合があります。より信頼性の高いパターンは、コンテナを常にDOMに存在させてコンテンツだけを更新する方法です。例: <div role="alert" aria-atomic="true">{error}</div> を常にレンダリングし、コンテンツが空のときは空文字とする方法が推奨されます。同じパターンは collections/new・orgs/new・papers/[id]/edit にも存在します。
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/src/app/upload/page.tsx
Line: 560-564
Comment:
**`role="alert"` を条件付きマウントで使用することの信頼性**
WAI-ARIA 仕様では「ライブリージョンのコンテナ要素は、コンテンツを更新し始める前にDOMに存在していなければならない」とされています。`{error && <div role="alert">...</div>}` というパターンは要素ごとDOMに追加するため、古いスクリーンリーダー(古いNVDA・JAWSのバージョンなど)では読み上げが発火しない場合があります。より信頼性の高いパターンは、コンテナを常にDOMに存在させてコンテンツだけを更新する方法です。例: `<div role="alert" aria-atomic="true">{error}</div>` を常にレンダリングし、コンテンツが空のときは空文字とする方法が推奨されます。同じパターンは `collections/new`・`orgs/new`・`papers/[id]/edit` にも存在します。
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
🎨 Palette: 動的エラーメッセージのアクセシビリティ向上
💡 概要 (What)
動的にレンダリングされるバリデーションエラーやAPIの送信エラーメッセージの要素に、
role="alert"属性を追加しました。以下のページに適用しています:
apps/web/src/app/collections/new/page.tsx)apps/web/src/app/orgs/new/page.tsx)apps/web/src/app/papers/[id]/edit/page.tsx)apps/web/src/app/upload/page.tsx)🎯 理由 (Why)
ReactなどのSPAでは、フォームの送信ボタンを押した後にバリデーションエラーやサーバーエラーが発生し、DOMにエラーメッセージが動的に追加されるケースが多々あります。
このとき、視覚的にはエラーが表示されていても、スクリーンリーダーを使用しているユーザーには、エラーが発生したことが即座に伝わりません。
role="alert"をコンテナ要素に設定することで、この要素がDOMに追加された瞬間にスクリーンリーダーが内容を自動的かつ優先的に読み上げるようになり、視覚障害のあるユーザーにとって非常に直感的で親切なUXを提供できます。📸 Before/After (Visual Change)
視覚的な変更はありません。すべてスクリーンリーダーや支援技術向けの改善です。
♿ アクセシビリティ (Accessibility)
PR created automatically by Jules for task 6283478814429325970 started by @is0692vs
Greptile Summary
4つのフォームページ(コレクション作成・組織作成・論文編集・アップロード)において、動的にレンダリングされるエラーメッセージ要素に
role="alert"を追加し、スクリーンリーダーがエラー発生時に内容を自動読み上げできるようにしたアクセシビリティ改善PRです。collections/new・orgs/new・papers/[id]/edit・uploadの4ページすべての{error && ...}条件付きレンダリング箇所にrole="alert"を付与しました。.Jules/palette.mdにこの改善パターンを学習ノートとして追記し、今後同様の実装に活用できるようにしています。Confidence Score: 4/5
視覚的・機能的な変更はなく、アクセシビリティ属性の追加のみのため、マージしても動作への影響はありません。
変更は4ファイルの1行ずつへの
role="alert"付与のみで、ロジックやUIには一切影響しません。ただし条件付きマウントパターンはWAI-ARIA仕様の推奨に沿っておらず、古い支援技術環境では効果が得られない可能性があります。4つのページファイルすべてで同一パターンが使用されているため、修正する場合は一括対応が必要です。
Important Files Changed
role="alert"の活用に関するルール)role="alert"を追加。条件付きマウントパターンのため古い支援技術では読み上げが発火しない可能性あり。role="alert"を追加。collections/newと同一のパターン。errorステートのコンテナにrole="alert"を追加。role="alert"を追加。条件付きマウントパターンの信頼性について改善の余地あり。Sequence Diagram
sequenceDiagram participant User as ユーザー participant Form as フォーム (React) participant API as APIサーバー participant SR as スクリーンリーダー User->>Form: フォーム送信 Form->>API: APIリクエスト API-->>Form: エラーレスポンス Form->>Form: setError(message) Note over Form: {error && <div role="alert">...} Form->>SR: "DOM挿入 → role="alert" 検知" SR-->>User: エラー内容を即座に読み上げPrompt To Fix All With AI
Reviews (1): Last reviewed commit: "feat(a11y): add role="alert" to dynamic ..." | Re-trigger Greptile