Skip to content

🎨 Palette: 動的エラーメッセージに role="alert" を追加しアクセシビリティを向上#993

Open
is0692vs wants to merge 1 commit into
stagingfrom
palette/add-role-alert-to-error-messages-6283478814429325970
Open

🎨 Palette: 動的エラーメッセージに role="alert" を追加しアクセシビリティを向上#993
is0692vs wants to merge 1 commit into
stagingfrom
palette/add-role-alert-to-error-messages-6283478814429325970

Conversation

@is0692vs

@is0692vs is0692vs commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

🎨 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/neworgs/newpapers/[id]/editupload の4ページすべての {error && ...} 条件付きレンダリング箇所に role="alert" を付与しました。
  • .Jules/palette.md にこの改善パターンを学習ノートとして追記し、今後同様の実装に活用できるようにしています。

Confidence Score: 4/5

視覚的・機能的な変更はなく、アクセシビリティ属性の追加のみのため、マージしても動作への影響はありません。

変更は4ファイルの1行ずつへの role="alert" 付与のみで、ロジックやUIには一切影響しません。ただし条件付きマウントパターンはWAI-ARIA仕様の推奨に沿っておらず、古い支援技術環境では効果が得られない可能性があります。

4つのページファイルすべてで同一パターンが使用されているため、修正する場合は一括対応が必要です。

Important Files Changed

Filename Overview
.Jules/palette.md 動的エラーメッセージのアクセシビリティ改善に関する学習ノートを追記(role="alert" の活用に関するルール)
apps/web/src/app/collections/new/page.tsx エラー表示要素に role="alert" を追加。条件付きマウントパターンのため古い支援技術では読み上げが発火しない可能性あり。
apps/web/src/app/orgs/new/page.tsx エラー表示要素に role="alert" を追加。collections/new と同一のパターン。
apps/web/src/app/papers/[id]/edit/page.tsx フォーム送信エラーおよびデータ取得エラーの両方を扱う error ステートのコンテナに role="alert" を追加。
apps/web/src/app/upload/page.tsx バリデーションエラーおよびAPIエラーのコンテナに 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: エラー内容を即座に読み上げ
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/web/src/app/upload/page.tsx:560-564
**`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` にも存在します。

Reviews (1): Last reviewed commit: "feat(a11y): add role="alert" to dynamic ..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

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>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 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 @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel

vercel Bot commented Jun 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
open-shelf Ignored Ignored Jun 14, 2026 2:59pm

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@is0692vs, we couldn't start this review because you've reached your PR review rate limit.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a1fc3a9f-7193-4c1d-a191-a8ebefb4462e

📥 Commits

Reviewing files that changed from the base of the PR and between a35977c and 119dd54.

📒 Files selected for processing (5)
  • .Jules/palette.md
  • 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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch palette/add-role-alert-to-error-messages-6283478814429325970

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot dosubot Bot added enhancement New feature or request javascript Pull requests that update javascript code labels Jun 14, 2026
@github-actions

Copy link
Copy Markdown

このリポジトリでは staging 先行フローを採用しています。PR のターゲットを staging に変更しました。staging で動作確認後、stagingmain の PR を作成してください。

@github-actions github-actions Bot changed the base branch from main to staging June 14, 2026 14:59
@codecov

codecov Bot commented Jun 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

💡 改善の提案:スクリーンリーダーでの確実な読み上げ

role="alert" を持つ要素を {error && ...} のように動的にマウント(DOMに追加)すると、一部のスクリーンリーダーやブラウザの組み合わせにおいて、エラー発生時の自動読み上げが正しくトリガーされない場合があります。

アクセシビリティのベストプラクティス(MDNの推奨事項など)では、role="alert" を持つコンテナ要素は常にDOM上に存在させておき、その中身(テキスト)を動的に更新することが推奨されています。

要素を常にDOMに残し、エラーメッセージのみを動的に流し込むように変更することを検討してください。

Suggested change
{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>}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

💡 改善の提案:スクリーンリーダーでの確実な読み上げ

role="alert" を持つ要素を動的にマウントすると、一部のスクリーンリーダーで読み上げがトリガーされないことがあります。コンテナ要素を常にDOMに配置し、テキストのみを動的に更新することで、より確実にエラーが通知されるようになります。

Suggested change
{error && <p role="alert" className="text-sm text-red-600">{error}</p>}
<p role="alert" className="text-sm text-red-600">{error || ""}</p>

Comment on lines 254 to 258
{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>
)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

💡 改善の提案:スクリーンリーダーでの確実な読み上げ

role="alert" を持つ要素を動的にマウントすると、一部のスクリーンリーダーで読み上げがトリガーされないことがあります。

スタイル適用クラス(mb-6 rounded-md bg-red-50 p-4...)を error の有無に応じて条件付きで適用することで、不要な空の赤いボックスが表示されるのを防ぎつつ、role="alert" のコンテナ要素を常にDOMに維持できます。

Suggested change
{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>

Comment on lines 560 to 564
{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>
)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

💡 改善の提案:スクリーンリーダーでの確実な読み上げ

role="alert" を持つ要素を動的にマウントすると、一部のスクリーンリーダーで読み上げがトリガーされないことがあります。

スタイル適用クラスを error の有無に応じて条件付きで適用することで、不要な空の赤いボックスが表示されるのを防ぎつつ、role="alert" のコンテナ要素を常にDOMに維持できます。

Suggested change
{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>

Comment on lines 560 to 564
{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>
)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 role="alert" を条件付きマウントで使用することの信頼性

WAI-ARIA 仕様では「ライブリージョンのコンテナ要素は、コンテンツを更新し始める前にDOMに存在していなければならない」とされています。{error && <div role="alert">...</div>} というパターンは要素ごとDOMに追加するため、古いスクリーンリーダー(古いNVDA・JAWSのバージョンなど)では読み上げが発火しない場合があります。より信頼性の高いパターンは、コンテナを常にDOMに存在させてコンテンツだけを更新する方法です。例: <div role="alert" aria-atomic="true">{error}</div> を常にレンダリングし、コンテンツが空のときは空文字とする方法が推奨されます。同じパターンは collections/neworgs/newpapers/[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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request javascript Pull requests that update javascript code size/S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant