🎨 Palette: 動的フォーム検証のアクセシビリティ改善(Slug検証)#1025
Conversation
Release: staging -> main (2026-06-24 15:53)
This adds `aria-describedby` and `aria-live="polite"` to the slug validation status elements on the collection creation and organization creation pages, allowing screen readers to announce the availability status dynamically. 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 50 minutes and 45 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 To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. 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 (3)
✨ 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 improves accessibility for dynamic form validation on the new collection and new organization pages by adding aria-describedby and aria-live="polite" attributes to the slug input and status elements, as documented in the updated .Jules/palette.md. The reviewer provided feedback to further enhance accessibility and visual design, suggesting status-specific text colors with dark mode support for the status messages, and recommending updating text content directly inside the aria-live container to ensure reliable screen reader announcements.
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.
| className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm dark:border-gray-700 dark:bg-gray-900" | ||
| /> | ||
| <p className="text-xs mt-1 text-gray-500"> | ||
| <p id="slug-status" aria-live="polite" className="text-xs mt-1 text-gray-500"> |
There was a problem hiding this comment.
💡 改善の提案:ステータスに応じた文字色の適用とダークモード対応
現在、スラッグの検証ステータス(「使用可能」「使用済み」など)がすべて text-gray-500 で表示されています。
ユーザーが視覚的にも直感的にステータスを理解できるように、orgs/new/page.tsx と同様にステータスに応じた色(使用可能なら緑、エラー/使用済みなら赤)を適用することをお勧めします。
また、ダークモード時のコントラスト比を考慮し、dark:text-green-400 や dark:text-red-400 を指定することで、WCAGのコントラスト基準を満たすアクセシブルな配色に改善できます。
| <p id="slug-status" aria-live="polite" className="text-xs mt-1 text-gray-500"> | |
| <p | |
| id="slug-status" | |
| aria-live="polite" | |
| className={ | |
| "text-xs mt-1 " + | |
| (slugStatus === "available" | |
| ? "text-green-600 dark:text-green-400" | |
| : slugStatus === "taken" || slugStatus === "invalid" | |
| ? "text-red-600 dark:text-red-400" | |
| : "text-gray-500 dark:text-gray-400") | |
| } | |
| > |
| <div id="slug-status" aria-live="polite" className="mt-1"> | ||
| {slugStatusText()} | ||
| </div> |
There was a problem hiding this comment.
💡 改善の提案:アクセシビリティの向上、ダークモード対応、および実装の共通化
現在の実装では、slugStatusText() が返す <span> 要素を動的に挿入/削除していますが、一部のスクリーンリーダーでは aria-live 領域内のDOM要素の追加・削除を正しく検知できない場合があります。
コンテナ要素(div)のテキストコンテンツのみを直接更新するように変更することで、より確実にアナウンスされるようになります。
また、以下の改善も同時に行えます:
- ダークモード対応:
text-green-600やtext-red-600はダークモードの背景でコントラストが低く見づらいため、dark:text-green-400やdark:text-red-400を追加して視認性を向上させます。 - 実装の共通化:
collections/new/page.tsxと同様のインライン条件分岐に統一することで、コードの可読性と一貫性が向上します。
※ この変更を適用した後、不要になった slugStatusText 関数(121〜138行目)は削除してください。
| <div id="slug-status" aria-live="polite" className="mt-1"> | |
| {slugStatusText()} | |
| </div> | |
| <div | |
| id="slug-status" | |
| aria-live="polite" | |
| className={ | |
| "text-xs mt-1 " + | |
| (slugStatus === "available" | |
| ? "text-green-600 dark:text-green-400" | |
| : slugStatus === "taken" || slugStatus === "invalid" | |
| ? "text-red-600 dark:text-red-400" | |
| : "text-gray-400 dark:text-gray-500") | |
| } | |
| > | |
| {slugStatus === "checking" && "確認中..."} | |
| {slugStatus === "available" && "✓ 使用可能"} | |
| {slugStatus === "taken" && "✗ 使用済み"} | |
| {slugStatus === "invalid" && "※ 3〜40文字、英小文字・数字・ハイフンのみ"} | |
| </div> |
| className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm dark:border-gray-700 dark:bg-gray-900" | ||
| /> | ||
| <p className="text-xs mt-1 text-gray-500"> | ||
| <p id="slug-status" aria-live="polite" className="text-xs mt-1 text-gray-500"> |
There was a problem hiding this comment.
aria-live="polite" の代わりに role="status" を使用することを検討してください。role="status" は暗黙的に aria-live="polite" と aria-atomic="true" の両方を設定するため、ステータスメッセージが部分更新されず常に全文がアナウンスされることが保証されます。また、要素の意味(「ステータスメッセージ」)もセマンティックに伝わります。
| <p id="slug-status" aria-live="polite" className="text-xs mt-1 text-gray-500"> | |
| <p id="slug-status" role="status" aria-live="polite" aria-atomic="true" className="text-xs mt-1 text-gray-500"> |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/src/app/collections/new/page.tsx
Line: 296
Comment:
`aria-live="polite"` の代わりに `role="status"` を使用することを検討してください。`role="status"` は暗黙的に `aria-live="polite"` と `aria-atomic="true"` の両方を設定するため、ステータスメッセージが部分更新されず常に全文がアナウンスされることが保証されます。また、要素の意味(「ステータスメッセージ」)もセマンティックに伝わります。
```suggestion
<p id="slug-status" role="status" aria-live="polite" aria-atomic="true" className="text-xs mt-1 text-gray-500">
```
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!
| /> | ||
| </div> | ||
| <div className="mt-1">{slugStatusText()}</div> | ||
| <div id="slug-status" aria-live="polite" className="mt-1"> |
There was a problem hiding this comment.
collections/new と同様に、role="status" と aria-atomic="true" の追加を検討してください。スクリーンリーダーによっては aria-live="polite" のみでは変更された部分テキストのみをアナウンスする場合があり、aria-atomic="true" によりステータス全体が一貫して読み上げられます。
| <div id="slug-status" aria-live="polite" className="mt-1"> | |
| <div id="slug-status" role="status" aria-live="polite" aria-atomic="true" className="mt-1"> |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/src/app/orgs/new/page.tsx
Line: 191
Comment:
`collections/new` と同様に、`role="status"` と `aria-atomic="true"` の追加を検討してください。スクリーンリーダーによっては `aria-live="polite"` のみでは変更された部分テキストのみをアナウンスする場合があり、`aria-atomic="true"` によりステータス全体が一貫して読み上げられます。
```suggestion
<div id="slug-status" role="status" aria-live="polite" aria-atomic="true" className="mt-1">
```
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!
💡 What:
collections/newとorgs/newページのスラッグ(URL識別子)入力フィールドにおいて、動的なバリデーションのステータス(「確認中...」「使用可能」「使用済み」など)にaria-describedbyとaria-live="polite"を追加しました。🎯 Why: 従来の実装では、スクリーンリーダーを使用するユーザーは、入力中に非同期で変化するスラッグの利用可能ステータスを即座に知ることができず、フォーカスを移動してステータステキストを個別に探す必要がありました。この変更により、ユーザーが入力を行っている間に、検証ステータスの変化が自然にアナウンスされるようになり、アクセシビリティが向上します。
📸 Before/After: 視覚的な変更はありません(HTMLの属性のみの追加です)。
♿ Accessibility:
<input>) にaria-describedby="slug-status"を付与しました。<p>または<div>) にid="slug-status"とaria-live="polite"を追加し、動的な変更がスクリーンリーダーに伝わるようにしました。PR created automatically by Jules for task 3237905151982779644 started by @is0692vs
Greptile Summary
このPRでは、
collections/newおよびorgs/newページのスラッグ入力フィールドにaria-describedby=\"slug-status\"を付与し、対応するステータス表示要素(<p>/<div>)にid=\"slug-status\"とaria-live=\"polite\"を追加することで、スクリーンリーダー向けアクセシビリティを改善します。collections/new/page.tsx: スラッグ<input>にaria-describedbyを、ステータス<p>にidとaria-live=\"polite\"を追加。orgs/new/page.tsx: 同様に<input>にaria-describedbyを、ステータス<div>にidとaria-live=\"polite\"を追加。.Jules/palette.md: 今回の改善内容をチームの学習ログとして記録。Confidence Score: 4/5
HTMLの属性追加のみでロジックへの変更はなく、アクセシビリティ改善として有益な変更です。マージ自体のリスクは低いです。
aria-live="polite"にaria-atomic="true"が設定されていないため、一部のスクリーンリーダーではステータスメッセージの部分テキストのみがアナウンスされる可能性があります。実害は限定的ですが、改善の余地があります。両ページファイルで
aria-atomic="true"の追加を検討することを推奨します。Important Files Changed
に id="slug-status" と aria-live="polite" を付与。role="status" の利用を検討する余地がある。
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant U as ユーザー participant I as input要素 participant L as ライブリージョン participant API as サーバー U->>I: フォーカス I-->>U: ラベル+aria-describedbyの現在の内容を読み上げ U->>I: テキスト入力 I->>L: "slugStatus=checking に更新" L-->>U: aria-liveにより「確認中...」をアナウンス I->>API: スラッグ利用可否を非同期確認 API-->>I: 結果返却 I->>L: "slugStatus=available/taken に更新" L-->>U: aria-liveにより「使用可能」または「使用済み」をアナウンス%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant U as ユーザー participant I as input要素 participant L as ライブリージョン participant API as サーバー U->>I: フォーカス I-->>U: ラベル+aria-describedbyの現在の内容を読み上げ U->>I: テキスト入力 I->>L: "slugStatus=checking に更新" L-->>U: aria-liveにより「確認中...」をアナウンス I->>API: スラッグ利用可否を非同期確認 API-->>I: 結果返却 I->>L: "slugStatus=available/taken に更新" L-->>U: aria-liveにより「使用可能」または「使用済み」をアナウンスPrompt To Fix All With AI
Reviews (1): Last reviewed commit: "feat(web): add aria-describedby and aria..." | Re-trigger Greptile