Skip to content

fix: honor offset in non-virtual scrollTo, export scroll config types#57

Open
aojunhao123 wants to merge 3 commits into
react-component:masterfrom
aojunhao123:fix/non-virtual-scroll-offset
Open

fix: honor offset in non-virtual scrollTo, export scroll config types#57
aojunhao123 wants to merge 3 commits into
react-component:masterfrom
aojunhao123:fix/non-virtual-scroll-offset

Conversation

@aojunhao123

@aojunhao123 aojunhao123 commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

scrollTo({ key, align, offset }) already applied offset in the virtual list, but the non-virtual (virtual={false}) RawList path ignored it. It set a --rc-listy-item-scroll-margin-top CSS variable that only accounted for the sticky-header height, never the user's offset, and it never set a bottom margin — so align: 'bottom' offsets did nothing at all in non-virtual mode.

This PR brings the non-virtual path to parity and tidies up the approach:

  • RawList now honors offset — it sets scrollMarginTop / scrollMarginBottom directly on the scroll target at scroll time (sticky-header height + offset for items with align: 'top', offset otherwise), matching the virtual list.
  • Drops the CSS-variable indirection (--rc-listy-item-scroll-margin-top) and the per-render inline scrollMarginTop on every item. The margin is now applied only on the actual target, and only while scrolling.
  • Exports ScrollAlign and ListyScrollToConfig from the package entry so consumers can type the config they pass to scrollTo (previously declared but not exported).
  • Adds a scroll-to demo that exercises both virtual and raw modes with live align / offset / key / group controls.

No changes to the public config shape — offset was already a typed option; it simply didn't work in non-virtual mode.

Test plan

  • tests/listy.behavior.test.tsx and tests/semantic.test.tsx updated and passing (25/25) — assert scrollMarginTop/scrollMarginBottom reflect header height + offset on the target, and that a user-supplied styles.item.scrollMarginTop is present at rest but the internal offset wins on the scroll target.
  • tsc --noEmit clean
  • eslint clean on changed source and the new demo
  • Manually verify the scroll-to demo in both virtual and non-virtual modes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 新功能
    • 新增“滚动到指定位置”演示页面与示例入口,支持虚拟滚动、top/bottom/auto 对齐、offset,以及按 item key/分组滚动展示。
    • 对外补充滚动对齐与配置类型(ScrollAlign、ListyScrollToConfig)。
  • 问题修复/改进
    • 优化粘性分组与条目的 scroll 边距计算与应用精度,正确处理 offset,确保顶部/底部/自动对齐更一致。
    • 调整虚拟列表粘性分组在 align: bottom 时的滚动落点逻辑。
  • 测试
    • 更新并扩展滚动边距相关用例断言,覆盖分组、sticky 与 virtual 场景。

@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

@aojunhao123 is attempting to deploy a commit to the React Component Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d92bdef2-32a8-4ad2-b53c-755ebdb5ba48

📥 Commits

Reviewing files that changed from the base of the PR and between a7b56d1 and 7b6970c.

📒 Files selected for processing (8)
  • docs/demos/scroll-to.md
  • docs/examples/scroll-to.tsx
  • src/RawList/index.tsx
  • src/RawList/useRawListScroll.ts
  • src/VirtualList/index.tsx
  • src/index.ts
  • tests/listy.behavior.test.tsx
  • tests/semantic.test.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/index.ts
  • src/RawList/index.tsx
  • src/VirtualList/index.tsx
  • tests/semantic.test.tsx
  • tests/listy.behavior.test.tsx
  • src/RawList/useRawListScroll.ts
  • docs/examples/scroll-to.tsx

Walkthrough

新增 scrollTo 交互式演示,调整 RawList 和 VirtualList 的滚动边距与对齐处理,公开滚动配置类型,并补充分组、sticky、virtual 与原生滚动测试。

Changes

滚动边距与 scrollTo 流程

Layer / File(s) Summary
滚动边距应用与类型导出
src/index.ts, src/RawList/index.tsx, src/RawList/useRawListScroll.ts, src/VirtualList/index.tsx
RawList 移除旧的分组滚动边距处理;滚动逻辑根据目标、对齐方式和 offset 设置 scrollMarginTopscrollMarginBottom;sticky 分组在非 bottom 对齐时应用组头偏移,并导出 ScrollAlignListyScrollToConfig
滚动边距行为验证
tests/listy.behavior.test.tsx, tests/semantic.test.tsx
测试分组、非分组、sticky、virtual 及原生滚动场景中的边距计算,并验证自定义条目样式保持不变。
scrollTo 交互式示例
docs/demos/scroll-to.md, docs/examples/scroll-to.tsx
新增文档页面和示例组件,支持 virtual、对齐方式、offset、条目 key 与分组 key 滚动操作。

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ListyRef
  participant useRawListScroll
  participant TargetElement
  participant Browser
  ListyRef->>useRawListScroll: scrollTo(config)
  useRawListScroll->>TargetElement: 设置 scrollMarginTop/Bottom
  useRawListScroll->>Browser: 调用 scrollIntoView
Loading

Possibly related PRs

Poem

兔子挥爪滚到底,
顶部底部都对齐。
offset 轻轻加一笔,
分组条目跳入溪。
新例闪闪,测试齐!

🚥 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 标题准确概括了核心改动:非虚拟列表的 scrollTo 现在支持 offset,并新增滚动配置类型导出。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@codecov

codecov Bot commented Jul 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (6fb43b7) to head (7b6970c).

Additional details and impacted files
@@            Coverage Diff            @@
##            master       #57   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            8         8           
  Lines          211       209    -2     
  Branches        62        58    -4     
=========================================
- Hits           211       209    -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@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 introduces support for custom offsets when scrolling to items or group headers in RawList. It refactors the scroll margin application by replacing the CSS-variable-based approach with direct inline styles (scrollMarginTop and scrollMarginBottom) dynamically computed on the target element. It also adds a new "Scroll To" demo, exports relevant types, and updates the test suite to verify the new behavior. There are no review comments, so I have no feedback to provide.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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/RawList/useRawListScroll.ts`:
- Around line 69-77: 在 useRawListScroll 中分离 item 与 group 的滚动定位属性:根据 isItem 选择
data-item-key 或 data-group-key 构造选择器,避免继续使用
data-key;同时确保对应的条目和分组节点分别写入匹配的数据属性,并保留现有 applyScrollMargin 的定位行为。
- Around line 39-52: Update applyScrollMargin so sticky header height is
included for item targets whenever align is not 'bottom', including 'auto';
retain zero header offset for bottom alignment and non-item targets.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 41b08372-c439-473b-a4a2-4559168c7b23

📥 Commits

Reviewing files that changed from the base of the PR and between 13f952a and b83e38c.

📒 Files selected for processing (7)
  • docs/demos/scroll-to.md
  • docs/examples/scroll-to.tsx
  • src/RawList/index.tsx
  • src/RawList/useRawListScroll.ts
  • src/index.ts
  • tests/listy.behavior.test.tsx
  • tests/semantic.test.tsx

Comment thread src/RawList/useRawListScroll.ts
Comment thread src/RawList/useRawListScroll.ts
@zombieJ

zombieJ commented Jul 14, 2026

Copy link
Copy Markdown
Member

来自 Code Review Skill

这个 PR 在做什么

这个 PR 为 RawList 的 item/group scrollTo 补齐 offset,处理 sticky header 和 auto 对齐,并公开滚动配置类型。它还增加了完整演示以及 RawList、VirtualList、sticky、语义样式相关测试。

结论

不适合合并

存在一个可由合法输入触发的滚动目标混淆问题:item key 与 group key 相同时,会滚动到错误节点。应先拆分两类节点的定位属性并补充回归测试;此外,当前分支与 master 存在合并冲突,需要先更新分支。

问题清单

🔴 高优先级(阻塞合并)

  • item 与 group 共用 data-key,相同 key 会命中错误的滚动目标src/RawList/useRawListScroll.ts:72
    RawList 同时把 data-key 写在 group section 和 item 上;由于 group section 位于 item 之前,scrollTo({ key: value }) 在 item key 与 group key 字符串相同时会选中 group section。这样不仅滚动位置错误,sticky header offset 也会基于错误节点计算。建议分别使用 data-item-keydata-group-key,按配置类型构造选择器,并加入 key 冲突测试。

🟡 中优先级(建议修复)

无。

🟢 低优先级(可选改进)

无。

The virtual list already applied the `offset` from `scrollTo({ key, align,
offset })`, but the non-virtual RawList path ignored it: it set a
`--rc-listy-item-scroll-margin-top` CSS variable that only accounted for the
sticky header height and never the user's offset, and it never set a bottom
margin, so `align: 'bottom'` offsets did nothing.

- RawList now applies `scrollMarginTop`/`scrollMarginBottom` directly on the
  scroll target at scroll time (header height + offset for items on `top`
  align, offset otherwise), matching the virtual path.
- Drop the CSS-variable indirection and the per-render inline scrollMarginTop
  on every item; the margin is applied only on the target, only when scrolling.
- Export `ScrollAlign` and `ListyScrollToConfig` so consumers can type the
  config they pass to `scrollTo`.
- Add a `scroll-to` demo exercising both virtual and raw modes.
`align: 'auto'` maps to `scrollIntoView({ block: 'nearest' })`, which can land
the item at the container top where the sticky header would occlude it. The
header offset was only added for `align: 'top'`, so `auto` (and the default)
were left uncorrected in both the raw and virtual paths.

Apply the header offset whenever alignment is not explicitly `bottom`, in both
RawList and VirtualList, keeping the two modes consistent.
@aojunhao123 aojunhao123 force-pushed the fix/non-virtual-scroll-offset branch from 62adb9d to 7b6970c Compare July 14, 2026 03:38
@zombieJ

zombieJ commented Jul 14, 2026

Copy link
Copy Markdown
Member

来自 Code Review Skill

这个 PR 在做什么

PR #57 已 rebase 到包含 #56 的最新 master,合并冲突已经解决。它为非虚拟列表的 scrollTo 补齐 offset 支持,同时调整 sticky 分组的自动对齐逻辑、导出滚动配置类型,并增加演示与测试。

结论

不适合合并

RawList 的 offset 实现基本正确,但 VirtualList 对 align: 'auto' 的 sticky header 补偿会错误影响最终选择 bottom 对齐的情况。核心 CI 均通过;Vercel 仍只是团队授权失败。

问题清单

🔴 高优先级(阻塞合并)

  • auto 最终按底部对齐时仍错误叠加 sticky header 高度src/VirtualList/index.tsx:106
    rc-virtual-list 会根据目标位于视口上方还是下方,将 auto 动态解析为 top 或 bottom;但这里预先把 header 高度加入统一的 offset。当目标位于视口下方时,底部对齐也会多出一个 header 高度,造成错误的底部间距。新增测试只调用了 offset 函数,没有覆盖 auto → bottom 的实际落点;建议暂时只对显式 align: 'top' 补偿,或让补偿能够根据最终对齐方向决定。

🟡 中优先级(建议修复)

  • 调用 scrollTo 会永久覆盖用户传入的 scroll margin 样式src/RawList/useRawListScroll.ts:49
    直接修改 React 管理的 element.style.scrollMarginTop/Bottom 后没有恢复。若用户通过 styles.item 设置这些属性,调用一次 scrollTo 后其值会被永久替换;普通 rerender 也不一定恢复,因为 React 认为 style props 没有变化。建议在 scrollIntoView 前保存原值,并在浏览器读取滚动参数后恢复,或继续用内部 CSS 变量隔离状态。

🟢 低优先级(可选改进)

  • item/group 同名 key 仍会选错目标src/RawList/useRawListScroll.ts:72
    上次指出的问题仍存在。不过重新对比 master 后确认,这是已有实现中的历史问题,并非本 PR 引入,因此不再作为本次合并阻塞项;仍建议后续拆分 data-item-keydata-group-key

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.

2 participants