Skip to content

ui: scroll vote dropdown to center current grade on open (#3796)#3801

Merged
KATO-Hiro merged 10 commits into
stagingfrom
feature/#3796
Jul 3, 2026
Merged

ui: scroll vote dropdown to center current grade on open (#3796)#3801
KATO-Hiro merged 10 commits into
stagingfrom
feature/#3796

Conversation

@river0525

@river0525 river0525 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • グレード済み問題の投票ドロップダウンを開いたとき、「ふつう」(公式グレードに対応する項目)が中央に来るようにスクロール
  • 「詳細」リンクをスクロール範囲外の先頭に固定表示(常に見える)
  • スクロール計算ロジックを grade_scroll.ts の純粋関数 calcCenteredScrollTop に抽出(テスト付き)

実装の詳細

  • bind:isOpen={isDropdownOpen} で Flowbite Dropdown の開閉状態を追跡
  • グレード一覧を <div bind:this={gradeListContainer} class="h-44 overflow-y-auto"> でラップ
  • $effectisDropdownOpen の変化を検知し、taskResult.grade !== PENDING のときにスクロール位置を計算・適用
  • calcCenteredScrollTop(targetIndex, scrollHeight, itemCount, clientHeight) で centering 計算を純粋関数化

Test plan

  • グレード済み問題(Q1〜D6)のドロップダウンを開き、その問題の公式グレードが中央付近に表示されることを確認
  • PENDING(グレード未確定)問題のドロップダウンではスクロールが発生しないことを確認
  • 「詳細」リンクがスクロール外の先頭に常時表示されることを確認
  • PC・スマートフォン・タブレット各サイズでレイアウト崩れがないことを確認

Closes #3796

🤖 Generated with Claude Code

https://claude.ai/code/session_01EGhZMRXzv7YDEgpo9GVxAn

Summary by CodeRabbit

  • New Features

    • 投票用グレード一覧で、現在の選択位置がドロップダウン中央付近に自動表示されるようになりました。
    • 一覧は固定高さのスクロール領域で表示され、長い候補でも見やすくなりました。
  • Bug Fixes

    • 非保留タスクのグレード選択時に、候補リストの先頭や末尾に偏りにくくなりました。
    • 表示できる高さがない場合でも、スクロール処理が安全に動作します。

river0525 and others added 3 commits July 1, 2026 20:14
…3796)

When a graded task's vote dropdown opens, auto-scroll the grade list so
the item matching the task's official grade ("ふつう") is centered in
the visible area, reducing the need to scroll manually.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EGhZMRXzv7YDEgpo9GVxAn
`indexOf` on `nonPendingGrades` (which excludes PENDING) required
a narrower argument type. Replaced with `findIndex` to avoid the cast.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EGhZMRXzv7YDEgpo9GVxAn
Extracts the itemHeight/scrollTop calculation from the $effect into a
pure function `calcCenteredScrollTop` in `grade_scroll.ts` with tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EGhZMRXzv7YDEgpo9GVxAn
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@KATO-Hiro, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 35 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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.

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 reviews.

How do review 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 refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0e0e6459-8515-446d-ab92-0fd0dd9c40b2

📥 Commits

Reviewing files that changed from the base of the PR and between aae49d4 and cf0716c.

📒 Files selected for processing (3)
  • src/features/votes/components/VotableGrade.svelte
  • src/features/votes/utils/grade_scroll_position.test.ts
  • src/features/votes/utils/grade_scroll_position.ts
📝 Walkthrough

Walkthrough

VotableGrade.svelte のドロップダウン表示時に、現在のタスクグレード位置を中央寄せする自動スクロール機能を追加。中央寄せの scrollTop を計算する calcCenteredScrollTop 関数を新規実装し、対応するユニットテストを追加した。

Changes

グレード自動センタリングスクロール

Layer / File(s) Summary
センタリング計算ロジックとテスト
src/features/votes/utils/grade_scroll_position.ts, src/features/votes/utils/grade_scroll_position.test.ts
calcCenteredScrollTop を新規実装し、itemCount/scrollHeight が0の場合は0を返し、対象アイテムを中央寄せするscrollTopを算出、上下端でクランプする。通常/エッジ/無効入力ケースのテストを追加。
ドロップダウンの自動スクロール適用
src/features/votes/components/VotableGrade.svelte
calcCenteredScrollTop をインポートし、gradeListContainer を bind:this で保持。$effect 内で非PENDING時に現在グレードのindexを特定し、requestAnimationFrame経由でscrollTopを更新。ドロップダウン内の nonPendingGrades 描画を高さ固定・縦スクロールのコンテナへ移動。

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

  • AtCoder-NoviSteps/AtCoderNoviSteps#3447: VotableGrade.svelte のドロップダウン(非PENDING時の各グレード行)を同じ箇所で再構成しており、本PRのスクロール用コンテナ移動と衝突し得るため。

Suggested reviewers: KATO-Hiro

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 変更内容の中心である投票ドロップダウンの自動スクロールを端的に表しており、タイトルとして適切です。
Linked Issues check ✅ Passed #3796 の要件である、グレード済み問題の投票時に現在グレードを中央へ寄せる挙動を実装できています。
Out of Scope Changes check ✅ Passed 追加されたユーティリティ、テスト、UI再配置はいずれもスクロール中心化の目的に沿っており、明確な逸脱はありません。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#3796

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.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/votes/components/VotableGrade.svelte`:
- Around line 99-121: The grade scroll logic in VotableGrade.svelte still mixes
business rules into the $effect by computing targetIndex with
nonPendingGrades.findIndex and handling the PENDING/element guards inline. Move
this logic into a util alongside calcCenteredScrollTop, such as a grade_scroll
helper, and have the component call that helper to get the target index and
guard result. Keep the $effect focused on wiring gradeListContainer and
scrollTop, and make the extracted util easy to unit test.

In `@src/features/votes/utils/grade_scroll.ts`:
- Around line 11-16: The grade_scroll utility currently clamps only the lower
bound, so it can return a scrollTop beyond the maximum scrollable range. Update
the getScrollTop logic in grade_scroll.ts to also clamp against scrollHeight -
clientHeight, keeping the returned value within the actual scrollable interval.
Use the existing itemCount, scrollHeight, clientHeight, and targetIndex
calculation in the function as the reference point.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 37112687-caef-4c92-9405-3d33fea72b91

📥 Commits

Reviewing files that changed from the base of the PR and between 4ac28e7 and 8163524.

📒 Files selected for processing (3)
  • src/features/votes/components/VotableGrade.svelte
  • src/features/votes/utils/grade_scroll.test.ts
  • src/features/votes/utils/grade_scroll.ts

Comment thread src/features/votes/components/VotableGrade.svelte Outdated
Comment thread src/features/votes/utils/grade_scroll.ts Outdated
Adds upper-bound clamp against scrollHeight - clientHeight so the
function always returns a value within [0, maxScrollTop].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D25pgX4cUCZDJoyqDCyGC5
Flowbite's Popper uses popover="manual" and calls showPopover() inside
onintrostart, which fires via requestAnimationFrame. The previous $effect
ran synchronously before that RAF, reading scrollHeight=0 from the hidden
popover and producing no scroll.

Fix: remove isDropdownOpen/$bindable (gradeListContainer going from
undefined to the element is sufficient as the open signal), and defer
scrollTop assignment to a RAF scheduled after the Popper's own RAF.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D25pgX4cUCZDJoyqDCyGC5
@river0525

river0525 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

@KATO-Hiro
PCでの動作確認、AIレビューへの対応完了いたしました。
実際の環境でスマホなどでもご確認いただき、問題なければマージお願いいたします。

@river0525 river0525 requested a review from KATO-Hiro July 2, 2026 05:28
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nt order

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@KATO-Hiro KATO-Hiro left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@river0525

ありがとうございます
PC や スマホやタブレット相当の画面サイズも正しく表示されることを確認しました

LGTM です
マージします

@KATO-Hiro KATO-Hiro merged commit 426d398 into staging Jul 3, 2026
3 checks passed
@KATO-Hiro KATO-Hiro deleted the feature/#3796 branch July 3, 2026 23:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ui / ux] 管理者がグレード済みの問題の投票を押すときに、中央が「ふつう」となるようにしましょう

2 participants