Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add new prop scrollPosition #756

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

OysterD3
Copy link

@OysterD3 OysterD3 commented Nov 25, 2024

ant-design/ant-design#39433

Summary by CodeRabbit

  • 新功能

    • TabItem接口中增加了scrollPosition属性,提供更细致的标签滚动控制。
    • 新增文档文件scroll-position.md,展示滚动位置功能的示例。
    • 更新Tabs组件,支持根据用户选择动态调整标签的滚动位置。
    • TabNavList组件增强了滚动行为的灵活性,支持新的scrollPosition属性。
  • 文档

    • 更新README文档,包含新的scrollPosition属性信息。

Copy link

vercel bot commented Nov 25, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
tabs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 25, 2024 9:33am

Copy link

coderabbitai bot commented Nov 25, 2024

Walkthrough

该拉取请求引入了一个新的属性 scrollPosition,该属性添加到 TabItem 接口中,并在 README.md 中进行了文档更新。新属性的类型为联合类型,包括 'start''end''center''auto',默认值为 'auto'。此外,新的 Markdown 文件 scroll-position.md 被添加到 docs/demo 目录中,包含了与滚动位置功能相关的示例代码。多个组件的接口也进行了相应的更新,以支持新的滚动位置配置。

Changes

文件路径 更改摘要
README.md 添加了 scrollPosition 属性到 TabItem 接口,并更新了文档以反映此更改。
docs/demo/scroll-position.md 创建了新的 Markdown 文件 scroll-position.md,包含演示的前言和代码块引用。
docs/examples/scroll-position.tsx 添加了新的 React 功能组件,使用 Tabs 组件并支持配置滚动位置,包含状态管理和用户交互示例。
src/TabNavList/index.tsx TabNavListProps 接口中添加了可选属性 scrollPosition,并更新 scrollToTab 函数以支持新属性。
src/Tabs.tsx TabsProps 接口中添加了 scrollPosition 属性,移除了 onNextClickonPrevClickkeyboard 属性。
src/interface.ts 更新了类型定义,添加了新类型 ScrollPosition,并进行了语法调整以符合 TypeScript 的类型声明规范。

Possibly related PRs

Poem

在兔子洞中跳跃欢,
新属性如春风般。
滚动位置更灵活,
标签跳跃乐无边。
文档更新不落后,
兔子欢唱庆新篇! 🐰✨

Warning

Rate limit exceeded

@OysterD3 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 0 minutes and 9 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 15ce46d and 0078378.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 15ce46d and 0078378.

📒 Files selected for processing (1)
  • README.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • README.md

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (2)
docs/examples/scroll-position.tsx (2)

1-5: 导入路径不一致

建议统一使用相对路径或别名路径,避免混合使用。目前同时使用了 @/interface../../src 两种不同的导入方式。

建议修改如下:

-import type { ScrollPosition } from '@/interface';
+import type { ScrollPosition } from '../../src/interface';

24-30: 建议优化重复的事件处理逻辑

四个单选按钮使用了相同的 onChange 处理逻辑,建议提取为共用函数以减少代码重复。

建议修改如下:

+const handleScrollPositionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+  setScrollPosition(e.target.value as ScrollPosition);
+};

// 然后在所有 radio 按钮中使用:
-onChange={e => setScrollPosition(e.target.value as ScrollPosition)}
+onChange={handleScrollPositionChange}

Also applies to: 34-40, 44-50, 54-60

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1b88fdd and 5739d25.

📒 Files selected for processing (7)
  • README.md (1 hunks)
  • docs/demo/scroll-position.md (1 hunks)
  • docs/examples/scroll-position.tsx (1 hunks)
  • src/TabNavList/TabNode.tsx (1 hunks)
  • src/TabNavList/index.tsx (7 hunks)
  • src/Tabs.tsx (4 hunks)
  • src/interface.ts (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/demo/scroll-position.md
🔇 Additional comments (16)
src/TabNavList/index.tsx (4)

22-22: 正确添加了 scrollPosition 属性

成功将 ScrollPosition 类型和 scrollPosition 属性添加到接口和组件中,为滚动位置提供了更灵活的控制。

Also applies to: 59-59, 109-109


156-157: 更新了 needScroll 的计算逻辑

调整了 needScroll 的计算方式,以反映新增的滚动位置逻辑,确保在需要滚动时准确地判断。


Line range hint 272-315: 验证 scrollToTab 函数中滚动逻辑的正确性

scrollToTab 函数中增加了对 scrollPosition 属性的处理,包括 'auto''start''end''center' 四种情况。建议仔细测试每种滚动位置,确保选项卡在不同设置下的滚动行为符合预期。

如果需要,我可以协助编写针对这些情况的测试用例,帮助验证逻辑的正确性。

Also applies to: 309-320


443-443: scrollPosition 添加到 useEffect 的依赖中

scrollPosition 添加到 useEffect 的依赖数组中,确保当该属性变化时,滚动逻辑能够及时更新。

src/interface.ts (4)

1-1: 导入语句优化得当!

DropdownProps 改为类型导入是一个很好的改进,这样可以确保更好的代码优化。


12-12: 接口语法更新符合规范!

将属性定界符从逗号改为分号符合 TypeScript 接口声明的最佳实践。


48-48: 接口语法统一性改进!

保持了与其他接口定义相同的分号分隔符风格。


93-93: 请确认新增的滚动位置类型定义!

新增的 ScrollPosition 类型包含了四个可选值:'start'、'end'、'center' 和 'auto'。建议:

  1. 确保在组件文档中详细说明每个值的具体行为
  2. 验证 'auto' 作为默认值是否合适
  3. 考虑是否需要添加相关的单元测试用例
✅ Verification successful

ScrollPosition 类型定义验证完成,实现合理!

经过验证,ScrollPosition 类型的实现是完善的:

  1. 示例文档 docs/examples/scroll-position.tsx 已经包含了完整的使用演示
  2. 代码中已将 'auto' 设置为默认值,且实现了合理的自动滚动逻辑
  3. 所有滚动位置值('start'、'end'、'center'、'auto')都在 TabNavList 组件中得到了正确处理

建议补充:

  • 添加单元测试用例以确保滚动位置的行为稳定性
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 检查是否已添加相关文档
rg -l "ScrollPosition" docs/

Length of output: 62


Script:

#!/bin/bash
# 检查文档内容
cat docs/examples/scroll-position.tsx

# 检查相关测试文件
rg -l "ScrollPosition" "**/*test*"

# 检查默认值的使用情况
rg "ScrollPosition.*auto" -A 2

Length of output: 2587


Script:

#!/bin/bash
# 检查组件中的默认值设置
rg "scrollPosition.*=.*" src/ -A 2

# 检查是否有相关的测试文件(使用正确的路径模式)
fd "test" --exec rg -l "ScrollPosition" {}

Length of output: 2459

docs/examples/scroll-position.tsx (3)

16-17: 状态管理实现得当

使用 useState 管理活动标签和滚动位置的状态,实现方式简洁明了。


73-83: 垂直布局示例实现完善

通过设置 tabPosition="left" 展示了垂直布局的用法,对于用户理解组件的灵活性很有帮助。


7-14: 测试数据生成合理

生成了50个标签项用于测试滚动行为,数量适中,能够充分展示滚动位置的效果。类型定义也很规范。

src/Tabs.tsx (4)

18-18: 类型定义清晰且位置恰当!

新增的 scrollPosition 属性类型定义合理,使用可选参数符合预期。

Also applies to: 76-77


105-105: 请验证默认值 'auto' 的行为是否符合预期

建议验证 scrollPosition 默认值 'auto' 是否与现有的滚动行为保持一致,以确保向后兼容性。

✅ Verification successful

scrollPosition 的默认值 'auto' 与现有滚动行为完全一致

从代码实现来看,'auto' 作为默认值是最合适的选择:

  1. 在 TabNavList/index.tsx 中的滚动逻辑实现显示,'auto' 模式会智能判断标签页的位置:

    • 当标签在可视区域外时自动滚动到可见位置
    • 当标签已经可见时保持当前滚动位置不变
  2. 在示例代码 docs/examples/scroll-position.tsx 中也验证了这一行为,'auto' 作为默认选项与其他定位模式(start/center/end)一起提供给用户选择。

  3. 这个默认值在 README.md 中也有明确的文档说明。

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 搜索相关的滚动行为实现
rg -l "scroll" --type tsx

Length of output: 53


Script:

#!/bin/bash
# 搜索相关的滚动行为实现,使用更通用的文件类型
rg -l "scroll" --type ts --type tsx --type jsx --type js

# 查找包含 scrollPosition 的文件
rg "scrollPosition" --type ts --type tsx --type jsx --type js

# 查找 Tabs 组件的定义和使用
ast-grep --pattern 'interface $_Props {
  $$$
  scrollPosition$_
  $$$
}'

Length of output: 250


Script:

#!/bin/bash
# 使用基本的 ripgrep 命令搜索,不指定文件类型
rg "scrollPosition" -A 5 -B 5

# 使用 fd 查找所有可能的 TypeScript/JavaScript 文件
fd -e ts -e tsx -e js -e jsx

# 查找 Tabs 组件的实现
rg "Tabs" -A 10 -B 10

Length of output: 102423


Line range hint 23-31: ⚠️ 提醒:破坏性变更

移除了以下属性:

  • onNextClick
  • onPrevClick
  • keyboard

建议:

  1. 在更新日志中明确标注这些破坏性变更
  2. 提供迁移指南,说明用户如何处理这些变更

189-189: 建议验证子组件的属性传递

需要确认:

  1. TabNavListWrapper 组件是否正确处理了 scrollPosition 属性
  2. 属性值是否正确传递到最终执行滚动的组件
✅ Verification successful

scrollPosition 属性已正确实现且完整传递

根据代码分析:

  1. scrollPosition 属性在 TabNavList 组件中得到了完整处理
  2. 该属性用于控制标签页滚动对齐方式,支持 'start'、'center'、'end' 和 'auto' 四种模式
  3. TabNavList 组件内部实现了相应的滚动逻辑,包括:
    • 水平和垂直方向的滚动支持
    • RTL(从右到左)布局的兼容
    • 自动滚动到活动标签的位置计算
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 检查 TabNavListWrapper 组件的实现
ast-grep --pattern 'interface TabNavListWrapperProps {
  $$$
}'

# 搜索相关的滚动实现代码
rg "scrollPosition.*=.*props" --type tsx

Length of output: 136


Script:

#!/bin/bash
# 检查 TabNavListWrapper 组件的实现和属性定义
ast-grep --pattern 'interface TabNavListWrapperProps {
  $$$
}'

# 搜索相关的滚动实现代码,使用正确的文件类型
rg "scrollPosition.*=.*props" -t ts -t tsx -t jsx

# 查找所有包含 TabNavListWrapper 的文件
fd -e ts -e tsx -e jsx TabNavListWrapper --exec cat {}

# 搜索所有与 scrollPosition 相关的代码
rg "scrollPosition" -t ts -t tsx -t jsx

Length of output: 272


Script:

#!/bin/bash
# 搜索所有与 TabNavListWrapper 相关的文件
find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.jsx" \) -exec grep -l "TabNavListWrapper" {} \;

# 搜索所有包含 scrollPosition 的文件
find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.jsx" \) -exec grep -l "scrollPosition" {} \;

# 显示包含 scrollPosition 的代码内容
find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.jsx" \) -exec grep -A 5 -B 5 "scrollPosition" {} \;

Length of output: 445


Script:

#!/bin/bash
# 查看 TabNavList/Wrapper.tsx 的具体实现
cat ./src/TabNavList/Wrapper.tsx

# 查看 TabNavList/index.tsx 中 scrollPosition 的使用
cat ./src/TabNavList/index.tsx

# 查看示例代码中 scrollPosition 的使用
cat ./docs/examples/scroll-position.tsx

Length of output: 20943

README.md (1)

143-143: 验证实现与文档的一致性

需要确认 scrollPosition 属性在代码中的实现是否与文档描述一致。

✅ Verification successful

Let me generate one more verification to check the type definition:


文档与实现完全一致

根据代码验证结果:

  • ScrollPosition 类型在 src/interface.ts 中定义为 'start' | 'end' | 'center' | 'auto'
  • TabNavList 组件正确实现了所有滚动位置的逻辑
  • 示例代码 docs/examples/scroll-position.tsx 展示了所有可用的滚动位置选项
  • 默认值 'auto'src/Tabs.tsx 中已设置
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 检查 TabItem 接口定义和实现
ast-grep --pattern 'interface TabItem {
  $$$
  scrollPosition?: $_;
  $$$
}'

# 检查属性的使用
rg -A 5 'scrollPosition.*=.*' 

Length of output: 6468


Script:

#!/bin/bash
# Check ScrollPosition type definition
ast-grep --pattern 'type ScrollPosition = $_;'

# Check TabNavList props interface
ast-grep --pattern 'interface TabNavListProps {
  $$$
  scrollPosition?: $_;
  $$$
}'

Length of output: 1713

docs/examples/scroll-position.tsx Outdated Show resolved Hide resolved
src/TabNavList/TabNode.tsx Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
@@ -323,7 +352,6 @@ const TabNavList = React.forwardRef<HTMLDivElement, TabNavListProps>((props, ref
onTabClick(key, e);
}}
onFocus={() => {
scrollToTab(key);
Copy link
Author

Choose a reason for hiding this comment

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

这个部分有点多余,因为useEffect里每当activeKey更换的时候会触发scrollToTab,所以没必要在这里触发多一次

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
src/TabNavList/index.tsx (1)

Line range hint 272-320: 建议重构滚动逻辑以提高可维护性

当前实现中存在以下问题:

  1. RTL/LTR 的逻辑结构重复
  2. 不同滚动位置的计算逻辑相似
  3. 计算中包含魔法数字

建议将计算逻辑抽象为独立函数:

+ const calculateTransform = (
+   position: ScrollPosition,
+   offset: { left: number, right: number, width: number },
+   isRTL: boolean,
+   visibleSize: number
+ ) => {
+   if (position === 'start') {
+     return isRTL ? offset.right : -offset.left;
+   }
+   if (position === 'end') {
+     return isRTL
+       ? offset.right + offset.width - visibleSize
+       : -(offset.left + offset.width - visibleSize);
+   }
+   if (position === 'center') {
+     return isRTL
+       ? offset.right + offset.width / 2 - visibleSize / 2
+       : -(offset.left + offset.width / 2 - visibleSize / 2);
+   }
+   // auto
+   if (isRTL) {
+     if (offset.right < transformLeft) {
+       return offset.right;
+     }
+     if (offset.right + offset.width > transformLeft + visibleSize) {
+       return offset.right + offset.width - visibleSize;
+     }
+   } else {
+     if (offset.left < -transformLeft) {
+       return -offset.left;
+     }
+     if (offset.left + offset.width > -transformLeft + visibleSize) {
+       return -(offset.left + offset.width - visibleSize);
+     }
+   }
+   return transformLeft;
+ };

  if (tabPositionTopOrBottom) {
-   // Original RTL/LTR logic
+   setTransformLeft(
+     alignInRange(
+       calculateTransform(scrollPosition, tabOffset, rtl, visibleTabContentValue)
+     )
+   );
    setTransformTop(0);
  } else {
-   // Original vertical logic
+   setTransformTop(
+     alignInRange(
+       calculateTransform(
+         scrollPosition,
+         { left: tabOffset.top, right: tabOffset.top, width: tabOffset.height },
+         false,
+         visibleTabContentValue
+       )
+     )
+   );
    setTransformLeft(0);
  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5739d25 and 15ce46d.

📒 Files selected for processing (2)
  • docs/examples/scroll-position.tsx (1 hunks)
  • src/TabNavList/index.tsx (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/examples/scroll-position.tsx
🔇 Additional comments (3)
src/TabNavList/index.tsx (3)

22-22: 接口变更看起来不错!

新增的 ScrollPosition 类型和 scrollPosition 可选属性的定义清晰明确。

Also applies to: 59-59


109-109: 属性解构合理!

scrollPosition 与其他滚动相关属性放在一起,保持了代码的一致性。


442-442: 依赖项更新正确!

scrollPosition 添加到 useEffect 的依赖数组中是必要的,这确保了滚动位置的改变会触发重新计算。

Copy link

codecov bot commented Nov 25, 2024

Codecov Report

Attention: Patch coverage is 56.25000% with 14 lines in your changes missing coverage. Please review.

Project coverage is 95.44%. Comparing base (1b88fdd) to head (0078378).
Report is 3 commits behind head on master.

Files with missing lines Patch % Lines
src/TabNavList/index.tsx 54.83% 14 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #756      +/-   ##
==========================================
- Coverage   97.72%   95.44%   -2.28%     
==========================================
  Files          18       18              
  Lines         702      724      +22     
  Branches      200      214      +14     
==========================================
+ Hits          686      691       +5     
- Misses         16       33      +17     

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

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.

1 participant