Skip to content

Conversation

@guoyunhe
Copy link
Contributor

@guoyunhe guoyunhe commented Oct 17, 2025

新增 spinner 类型,增减按钮分别放到左右两侧,以实现类似于淘宝加购数量的效果:

<InputNumber type="spinner" />
image

Summary by CodeRabbit

  • 新功能
    • InputNumber 新增 type='spinner' 模式,支持以旋钮式上下步进显示与交互。
  • 样式
    • 为 spinner 模式添加样式,调整布局与边框分隔以匹配新交互。
  • 文档
    • 增加 spinner 示例页及代码片段,展示受控/非受控、changeOnBlur 等用法与交互开关。
  • 测试
    • 更新并扩展测试以覆盖 spinner 类型与相关行为。
  • 辅助功能
    • 优化步进控件 ARIA 描述与交互一致性。

@vercel
Copy link

vercel bot commented Oct 17, 2025

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

A member of the Team first needs to authorize it.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @guoyunhe, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求为 InputNumber 组件引入了一个新的 'spinner' 类型。这个新类型通过将增减按钮分别放置在输入框的两侧,提供了一种直观的用户体验,特别适用于需要快速调整数值的场景,例如电商网站中的商品数量选择。此更改涉及组件属性的扩展、渲染逻辑的调整以及相应样式的添加,以确保新功能能够无缝集成并正确显示。

Highlights

  • 新增 InputNumber 组件的 spinner 类型: 为 InputNumber 组件引入了一个新的 'spinner' 类型,旨在提供类似淘宝商品数量增减的交互效果。
  • 增减按钮左右分列: 在 'spinner' 类型下,增量和减量按钮将分别放置在输入框的左右两侧,而非传统的一侧堆叠。
  • 样式和逻辑更新: 更新了 InputNumber 组件的样式(通过 Less)和内部逻辑,以支持新的 'type' 属性,并正确渲染和定位 'spinner' 类型的按钮。
  • StepHandler 组件增强: StepHandler 组件新增了 'upHidden' 和 'downHidden' 属性,允许更灵活地控制增减按钮的显示与隐藏。
  • 新增演示和文档: 添加了一个新的演示文件 'spinner.tsx' 来展示 'spinner' 类型的功能,并更新了文档以包含此新示例。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link

coderabbitai bot commented Oct 17, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

添加 InputNumber 的可选属性 type?: 'input' | 'spinner' 并默认 'input',根据 type 调整 StepHandler 渲染位置与组件 class;重构 StepHandler 为基于 action: 'up' | 'down' 的单一控件接口;新增 spinner 示例与样式;更新测试格式与断言。

Changes

Cohort / File(s) 变更摘要
样式:type-spinner
assets/index.less
新增 . -type-spinner 相关 LESS 规则,定义 spinner 布局、handler 大小、高度与边框样式。
核心:InputNumber 类型扩展
src/InputNumber.tsx
在公有接口 InputNumberProps 中添加 `type?: 'input'
控件:StepHandler 重构为 action 驱动
src/StepHandler.tsx
将原本分离的 up/down 渲染合并为基于 `action: 'up'
示例:spinner 演示组件
docs/demo/spinner.tsx
新增 React 示例文件,展示 spinner 模式下受控/非受控与 changeOnBlur 用例,含切换 disabled/readOnly/keyboard/wheel/stringMode 的控制按钮。
文档:示例页更新
docs/example.md
在示例文档中新增 spinner 节并引用 ./demo/spinner.tsx 代码示例。
测试:格式与断言调整
tests/props.test.tsx
对测试文件做格式化与断言更新,加入/调整对新增 type(spinner)相关的测试断言与属性检查(仅测试层面改动)。

Sequence Diagram(s)

sequenceDiagram
    participant User as 用户
    participant Public as InputNumber(public)
    participant Internal as InternalInputNumber
    participant Step as StepHandler

    rect rgb(232,248,255)
    User->>Public: 传入 props(含 type='spinner')
    Public->>Internal: 传递 props 与 type(class 包含 -type-spinner)
    end

    rect rgb(247,247,247)
    Internal->>Step: 渲染 action='down' 的 StepHandler(输入前)
    Internal->>Step: 渲染 action='up' 的 StepHandler(输入后)
    Note right of Step: StepHandler 根据 action 决定 增/减 行为
    end

    User->>Step: 点击或按住 增/减
    Step->>Internal: 触发 onStep(action)
    Internal->>Public: 更新值并触发 onChange
    Public->>User: 返回新的值 / 触发回调
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 分钟

重点检查:

  • StepHandler.tsx 的 action 驱动实现是否完整保留原有节流/停止(RAF/safeOnStopStep)与无障碍(ARIA)行为;
  • InputNumber.tsx 中 type 向下传递、渲染分支与 className 拼接是否影响现有样式或选择器;
  • assets/index.less 的选择器与命名是否与现有样式发生冲突。

Possibly related PRs

Suggested reviewers

  • afc163

Poem

🐰 轻敲键盘兔子跳,
spinner 上下节奏妙,
按钮合并更简洁,样式也到位,
示例文档示范好,
小兔一跳庆更新 🥕

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed PR标题"feat(spinner): support spinner type"清晰准确地反映了本次提交的核心变化。根据文件摘要,该PR的主要目的是为InputNumber组件添加一个新的"spinner"类型,包括在左右两侧放置增减按钮的UI模式。标题简洁明了,避免了模糊用语,能够让团队成员在浏览历史记录时迅速理解这次变更的主要内容。所有的文件变更(样式、演示文件、核心组件和测试)都围绕这个"支持spinner类型"的核心功能展开。
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review

你好,感谢你的贡献。本次 PR 新增了 spinner 类型的 InputNumber 组件,将增减按钮分别置于输入框两侧,功能实现良好。代码整体结构清晰,但在一些细节上还有可以改进的地方。我主要提出了三点建议:

  1. InputNumber.tsx 中,spinner 类型没有遵循 controls 属性的控制,导致即使 controls={false} 按钮依然会显示。
  2. spinner.tsx 示例文件中,onChange 事件处理器的类型定义不完整,当开启 stringMode 时可能导致类型错误。
  3. index.less 样式文件中,颜色值 #d9d9d9 多次硬编码,建议提取为变量以方便维护。
    请查看具体的代码审查评论。

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

🧹 Nitpick comments (1)
src/InputNumber.tsx (1)

624-632: spinner 模式实现正确,但可考虑优化代码复用。

spinner 模式的双 StepHandler 布局(左侧减号、右侧加号)实现了预期的数量选择器 UX。注意到之前的审查意见关于 controls 属性检查的建议已经得到落实(两处都有 controls && 判断)。

不过,两个 StepHandler 块的代码存在一定的重复。

可选优化建议:可以考虑提取一个辅助函数来减少重复代码,例如:

+    const renderSpinnerHandler = (position: 'left' | 'right') => {
+      const isLeft = position === 'left';
+      return (
+        <StepHandler
+          prefixCls={prefixCls}
+          {...(isLeft ? { downNode: downHandler } : { upNode: upHandler })}
+          {...(isLeft ? { downDisabled } : { upDisabled })}
+          {...(isLeft ? { upHidden: true } : { downHidden: true })}
+          onStep={onInternalStep}
+        />
+      );
+    };
+
-        {type === 'spinner' && controls && (
-          <StepHandler
-            prefixCls={prefixCls}
-            downNode={downHandler}
-            downDisabled={downDisabled}
-            upHidden
-            onStep={onInternalStep}
-          />
-        )}
+        {type === 'spinner' && controls && renderSpinnerHandler('left')}

         <div className={`${inputClassName}-wrap`}>
           {/* ... input ... */}
         </div>

-        {type === 'spinner' && controls && (
-          <StepHandler
-            prefixCls={prefixCls}
-            upNode={upHandler}
-            upDisabled={upDisabled}
-            downHidden
-            onStep={onInternalStep}
-          />
-        )}
+        {type === 'spinner' && controls && renderSpinnerHandler('right')}

Also applies to: 652-660

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 862c9bb and d5a3e4b.

📒 Files selected for processing (5)
  • assets/index.less (1 hunks)
  • docs/demo/spinner.tsx (1 hunks)
  • docs/example.md (1 hunks)
  • src/InputNumber.tsx (7 hunks)
  • src/StepHandler.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • assets/index.less
  • docs/demo/spinner.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-09-29T06:18:11.993Z
Learnt from: bombillazo
PR: react-component/input-number#644
File: src/InputNumber.tsx:173-174
Timestamp: 2024-09-29T06:18:11.993Z
Learning: In `src/InputNumber.tsx`, within the `InternalInputNumber` component, the state variables `prevValueRef` and `inputValueRef` are typed as `string | number` to maintain consistency with existing code.

Applied to files:

  • src/InputNumber.tsx
🧬 Code graph analysis (1)
src/InputNumber.tsx (1)
src/StepHandler.tsx (1)
  • StepHandler (28-134)
🔇 Additional comments (6)
src/StepHandler.tsx (2)

22-24: 新增的隐藏控制属性实现合理。

upHiddendownHidden 属性为条件渲染提供了清晰的控制方式,支持 spinner 模式的独立按钮布局需求。


105-131: 条件渲染逻辑正确。

使用 !upHidden!downHidden 进行条件渲染的实现清晰且符合预期,disabled 状态的处理也保持了一致性。

docs/example.md (1)

55-58: LGTM!

新增的 spinner 演示文档入口与现有格式保持一致。

src/InputNumber.tsx (3)

66-67: 新增的 type 属性设计合理。

type?: 'input' | 'spinner' 提供了清晰的模式选择,类型定义准确。


613-622: 现有输入模式的条件渲染处理正确。

为原有的 input 模式添加条件判断保持了向后兼容性,逻辑清晰。


668-668: type 属性的默认值和传递处理正确。

type = 'input' 的默认值确保了向后兼容性,className 和 props 的传递也都正确实现。

Also applies to: 703-703, 724-724

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

🧹 Nitpick comments (1)
src/InputNumber.tsx (1)

66-67: 可选:为 type 属性添加 JSDoc 注释。

建议为新增的 type 属性添加 JSDoc 注释,说明 'input''spinner' 两种模式的区别和使用场景,以提升开发者体验。

例如:

+  /** 
+   * 输入框类型
+   * - 'input': 默认模式,步进按钮在右侧垂直排列
+   * - 'spinner': 数量选择器模式,减少按钮在左侧,增加按钮在右侧
+   */
   type?: 'input' | 'spinner';
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d5a3e4b and fda11c6.

📒 Files selected for processing (5)
  • assets/index.less (1 hunks)
  • docs/demo/spinner.tsx (1 hunks)
  • docs/example.md (1 hunks)
  • src/InputNumber.tsx (9 hunks)
  • src/StepHandler.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/StepHandler.tsx
  • docs/demo/spinner.tsx
  • docs/example.md
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-09-29T06:18:11.993Z
Learnt from: bombillazo
PR: react-component/input-number#644
File: src/InputNumber.tsx:173-174
Timestamp: 2024-09-29T06:18:11.993Z
Learning: In `src/InputNumber.tsx`, within the `InternalInputNumber` component, the state variables `prevValueRef` and `inputValueRef` are typed as `string | number` to maintain consistency with existing code.

Applied to files:

  • src/InputNumber.tsx
🧬 Code graph analysis (1)
src/InputNumber.tsx (1)
src/StepHandler.tsx (1)
  • StepHandler (28-134)
🔇 Additional comments (5)
src/InputNumber.tsx (4)

89-90: LGTM!

新增的 spinnerUpHandlerspinnerDownHandler 属性设计合理,与现有的 upHandler/downHandler 保持了一致的命名模式,为 spinner 模式提供了独立的自定义能力。


617-664: LGTM!

条件渲染逻辑实现正确:

  • type === 'input' 模式:在输入框右侧渲染包含上下按钮的步进控件
  • type === 'spinner' 模式:在输入框左右两侧分别渲染减少和增加按钮

所有三处 StepHandler 的渲染都正确地检查了 controls 属性,确保在 controls={false} 时能正确隐藏按钮。降级逻辑(spinnerDownHandler || downHandlerspinnerUpHandler || upHandler)也为向后兼容提供了良好支持。


707-707: LGTM!

通过 ${prefixCls}-type-${type} 为不同类型添加专属类名,与 assets/index.less 中的样式规则正确对应,实现了类型样式的隔离。


672-672: LGTM!

type 设置默认值 'input' 确保了向后兼容性,现有代码无需修改即可继续使用默认的输入框模式。

assets/index.less (1)

137-160: LGTM!

spinner 类型的样式实现正确:

  • 使用 display: inline-flexalign-items: center 实现了左右按钮布局
  • 通过调整 border-left/border-right 和高度样式,使增减按钮分别显示在输入框两侧
  • 样式规则与 src/InputNumber.tsx 中的条件渲染逻辑配合良好,实现了预期的数量选择器 UX

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

🧹 Nitpick comments (1)
assets/index.less (1)

137-160: Spinner 样式布局合理

样式规则正确实现了 spinner 类型的横向布局,包括 flex 容器设置、固定宽度的按钮区域以及适当的边框调整。

需要注意的是,第 153 行和第 158 行继续使用了硬编码的颜色值 #d9d9d9。如之前评审中所提到的,建议将该颜色提取为 Less 变量以提高可维护性,不过这可以作为后续重构任务处理。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fda11c6 and d6cec40.

📒 Files selected for processing (5)
  • assets/index.less (1 hunks)
  • docs/demo/spinner.tsx (1 hunks)
  • docs/example.md (1 hunks)
  • src/InputNumber.tsx (7 hunks)
  • src/StepHandler.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/demo/spinner.tsx
  • src/StepHandler.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-09-29T06:18:11.993Z
Learnt from: bombillazo
PR: react-component/input-number#644
File: src/InputNumber.tsx:173-174
Timestamp: 2024-09-29T06:18:11.993Z
Learning: In `src/InputNumber.tsx`, within the `InternalInputNumber` component, the state variables `prevValueRef` and `inputValueRef` are typed as `string | number` to maintain consistency with existing code.

Applied to files:

  • src/InputNumber.tsx
🧬 Code graph analysis (1)
src/InputNumber.tsx (1)
src/StepHandler.tsx (1)
  • StepHandler (28-134)
🔇 Additional comments (8)
src/InputNumber.tsx (7)

66-67: 类型定义清晰,向后兼容

新增的 type 属性使用了明确的联合类型,保持了 API 的类型安全性,且作为可选属性不会破坏现有代码。


613-622: 输入模式渲染逻辑正确

正确检查了 typecontrols 属性,保持了原有输入模式的行为。


624-632: Spinner 模式左侧按钮渲染正确

正确使用 upHidden 属性隐藏上方按钮,仅显示减量按钮。同时也正确检查了 controls 属性,符合预期行为。


652-660: Spinner 模式右侧按钮渲染正确

正确使用 downHidden 属性隐藏下方按钮,仅显示增量按钮。与左侧按钮配合,实现了完整的 spinner 布局。


668-668: 默认值确保向后兼容

type 默认设置为 'input' 保证了现有代码无需修改即可继续工作。


703-703: 类名动态包含类型信息

在 className 中包含 type-${type} 后缀,为不同类型提供了独立的样式命名空间,便于 CSS 针对性定制。


724-724: 属性正确传递至内部组件

type 属性正确传递给 InternalInputNumber,确保了内部渲染逻辑能够访问到该配置。

docs/example.md (1)

55-58: 文档更新清晰简洁

新增的 spinner 示例章节格式与现有示例保持一致,便于用户查找和使用。

@vercel
Copy link

vercel bot commented Oct 27, 2025

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

Project Deployment Preview Comments Updated (UTC)
input-number Ready Ready Preview Comment Nov 3, 2025 7:50am

@codecov
Copy link

codecov bot commented Oct 28, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.01%. Comparing base (fb92575) to head (a38ca89).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #721      +/-   ##
==========================================
+ Coverage   95.98%   96.01%   +0.02%     
==========================================
  Files           7        7              
  Lines         299      301       +2     
  Branches       78       81       +3     
==========================================
+ Hits          287      289       +2     
  Misses         12       12              

☔ View full report in Codecov by Sentry.
📢 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.

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

🧹 Nitpick comments (1)
tests/props.test.tsx (1)

410-415: 基础测试覆盖合理,可选择性增强。

测试正确验证了 type="spinner" 属性会添加对应的 CSS 类名。测试语法和结构正确。

可选建议:考虑添加更全面的测试用例,例如:

  • 验证 spinner 模式下左右按钮是否正确渲染
  • 测试默认 type(应为 'input')是否正常工作
  • 验证点击 spinner 按钮的交互行为

可以在此测试套件中添加以下测试用例:

it('render input type by default', () => {
  const { container } = render(<InputNumber value={1} />);
  expect(container.querySelector('.rc-input-number')).toHaveClass('rc-input-number-type-input');
});

it('spinner type should have left and right handlers', () => {
  const { container } = render(<InputNumber value={1} type="spinner" />);
  expect(container.querySelector('.rc-input-number-handler-down')).toBeTruthy();
  expect(container.querySelector('.rc-input-number-handler-up')).toBeTruthy();
});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d6cec40 and dfd8e1b.

⛔ Files ignored due to path filters (1)
  • tests/__snapshots__/baseInput.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (3)
  • assets/index.less (1 hunks)
  • src/StepHandler.tsx (3 hunks)
  • tests/props.test.tsx (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/StepHandler.tsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-09-29T06:18:11.993Z
Learnt from: bombillazo
PR: react-component/input-number#644
File: src/InputNumber.tsx:173-174
Timestamp: 2024-09-29T06:18:11.993Z
Learning: In `src/InputNumber.tsx`, within the `InternalInputNumber` component, the state variables `prevValueRef` and `inputValueRef` are typed as `string | number` to maintain consistency with existing code.

Applied to files:

  • tests/props.test.tsx
📚 Learning: 2024-10-08T21:56:37.546Z
Learnt from: bombillazo
PR: react-component/input-number#644
File: tests/validator.test.tsx:34-83
Timestamp: 2024-10-08T21:56:37.546Z
Learning: In `tests/validator.test.tsx`, the test cases focus on the `validator` function. When the validator condition is not met, the input value should not change. The `formatter` is tested separately in another file.

Applied to files:

  • tests/props.test.tsx
🔇 Additional comments (2)
assets/index.less (1)

137-155: Spinner 样式逻辑正确。

新增的 spinner 样式规则正确实现了水平布局:

  • 使用 inline-flexalign-items: center 实现按钮与输入框水平排列
  • 通过 flex: 0 0 20px 固定按钮宽度
  • 移除上下按钮之间的边框(border-bottom: 0border-top: 0),添加左右分隔边框
  • 样式符合 PR 描述中的"左右分布递增递减按钮"的设计

注意:之前的评审已指出第 150 行(以及第 154 行)的硬编码颜色值 #d9d9d9 应提取为 Less 变量以提高可维护性。这个建议仍然有效。

tests/props.test.tsx (1)

5-5: 格式化改进恰当。

这些格式化更改提高了代码一致性:

  • 统一使用双引号
  • 为按钮添加 type="button" 属性避免意外的表单提交
  • 改善了多行代码的可读性

Also applies to: 97-98, 115-116, 187-187, 216-216, 277-279, 285-285, 292-292, 299-299, 307-309, 389-389, 419-419, 428-428, 436-436

prefixCls={prefixCls}
upNode={upHandler}
upDisabled={upDisabled}
downHidden
Copy link
Member

Choose a reason for hiding this comment

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

耦合度有点太高了,StepHandler 单独拆一个子组件出来消费吧

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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dfd8e1b and 9ec02df.

📒 Files selected for processing (2)
  • src/InputNumber.tsx (7 hunks)
  • src/StepHandler.tsx (4 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-09-29T06:18:11.993Z
Learnt from: bombillazo
Repo: react-component/input-number PR: 644
File: src/InputNumber.tsx:173-174
Timestamp: 2024-09-29T06:18:11.993Z
Learning: In `src/InputNumber.tsx`, within the `InternalInputNumber` component, the state variables `prevValueRef` and `inputValueRef` are typed as `string | number` to maintain consistency with existing code.

Applied to files:

  • src/InputNumber.tsx
📚 Learning: 2024-10-08T21:56:37.546Z
Learnt from: bombillazo
Repo: react-component/input-number PR: 644
File: src/InputNumber.tsx:393-395
Timestamp: 2024-10-08T21:56:37.546Z
Learning: The `InputNumber` component does not use error states or messages; it is designed to prevent the value from updating if validation fails without displaying additional feedback to the user.

Applied to files:

  • src/InputNumber.tsx
🧬 Code graph analysis (1)
src/InputNumber.tsx (1)
src/StepHandler.tsx (1)
  • StepHandler (25-113)
🪛 Biome (2.1.2)
src/StepHandler.tsx

[error] 110-110: Wrap comments inside children within braces.

Unsafe fix: Wrap the comments with braces

(lint/suspicious/noCommentText)

🔇 Additional comments (11)
src/InputNumber.tsx (8)

66-67: LGTM!

新增的 type 属性声明正确,可选类型和联合类型定义清晰合理。


592-607: LGTM!

正确使用了重构后的 StepHandler 组件的 action-based API,props 传递正确。


630-638: LGTM!

input 模式的渲染逻辑正确保留了原有行为,并正确处理了 controls 属性。


640-640: LGTM!

正确添加了 controls 属性判断,解决了之前评审中提到的问题。


660-660: LGTM!

正确添加了 controls 属性判断,与 line 640 的逻辑保持一致。


668-668: LGTM!

默认值 'input' 确保了向后兼容性,未指定 type 时保持原有行为。


703-703: LGTM!

添加基于 type 的 className 后缀,便于针对不同类型进行样式定制。


724-724: LGTM!

正确将 type prop 传递给内部组件。

src/StepHandler.tsx (3)

17-23: LGTM!

重构为基于 action 的统一接口,相比之前的分离 up/down props,API 设计更简洁清晰。


46-61: LGTM!

onStepMouseDown 逻辑正确,通过 action === 'up' 将 action 转换为方向布尔值,保持了 onStep 回调的接口契约。


94-106: LGTM!

渲染逻辑正确,ARIA 属性设置恰当,事件处理完善。假定上述 className 问题被修复后,此段代码将正常工作。

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 150bd00 and a38ca89.

📒 Files selected for processing (2)
  • src/InputNumber.tsx (13 hunks)
  • src/StepHandler.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/InputNumber.tsx
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: bombillazo
Repo: react-component/input-number PR: 644
File: src/InputNumber.tsx:173-174
Timestamp: 2024-09-29T06:18:11.993Z
Learning: In `src/InputNumber.tsx`, within the `InternalInputNumber` component, the state variables `prevValueRef` and `inputValueRef` are typed as `string | number` to maintain consistency with existing code.

Comment on lines 100 to +112
return (
<div className={clsx(`${handlerClassName}-wrap`, classNames?.actions)} style={styles?.actions}>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e, true);
}}
aria-label="Increase Value"
aria-disabled={upDisabled}
className={upClassName}
>
{upNode || <span unselectable="on" className={`${prefixCls}-handler-up-inner`} />}
</span>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e, false);
}}
aria-label="Decrease Value"
aria-disabled={downDisabled}
className={downClassName}
>
{downNode || <span unselectable="on" className={`${prefixCls}-handler-down-inner`} />}
</span>
</div>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e);
}}
aria-label={isUpAction ? 'Increase Value' : 'Decrease Value'}
aria-disabled={disabled}
className={mergedClassName}
style={style}
>
{children || <span unselectable="on" className={`${prefixCls}-handler-${action}-inner`} />}
</span>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

添加 tabIndex 属性以支持键盘焦点。

role="button" 的元素需要 tabIndex 才能接收键盘焦点。当前键盘用户无法通过 Tab 键聚焦到此控件。

应用此 diff 添加 tabIndex:

   return (
     <span
       {...sharedHandlerProps}
       onMouseDown={(e) => {
         onStepMouseDown(e);
       }}
       aria-label={isUpAction ? 'Increase Value' : 'Decrease Value'}
       aria-disabled={disabled}
+      tabIndex={disabled ? -1 : 0}
       className={mergedClassName}
       style={style}
     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return (
<div className={clsx(`${handlerClassName}-wrap`, classNames?.actions)} style={styles?.actions}>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e, true);
}}
aria-label="Increase Value"
aria-disabled={upDisabled}
className={upClassName}
>
{upNode || <span unselectable="on" className={`${prefixCls}-handler-up-inner`} />}
</span>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e, false);
}}
aria-label="Decrease Value"
aria-disabled={downDisabled}
className={downClassName}
>
{downNode || <span unselectable="on" className={`${prefixCls}-handler-down-inner`} />}
</span>
</div>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e);
}}
aria-label={isUpAction ? 'Increase Value' : 'Decrease Value'}
aria-disabled={disabled}
className={mergedClassName}
style={style}
>
{children || <span unselectable="on" className={`${prefixCls}-handler-${action}-inner`} />}
</span>
return (
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e);
}}
aria-label={isUpAction ? 'Increase Value' : 'Decrease Value'}
aria-disabled={disabled}
tabIndex={disabled ? -1 : 0}
className={mergedClassName}
style={style}
>
{children || <span unselectable="on" className={`${prefixCls}-handler-${action}-inner`} />}
</span>
🤖 Prompt for AI Agents
In src/StepHandler.tsx around lines 100 to 112, the span with role="button"
lacks a tabIndex so it can't receive keyboard focus; add a tabIndex attribute
(e.g. tabIndex={disabled ? -1 : 0}) to the span so it is focusable when enabled
and removed from tab order when disabled, keeping other props and handlers
intact.

⚠️ Potential issue | 🔴 Critical

添加键盘事件处理以满足可访问性要求。

组件使用了 role="button" 但缺少键盘事件处理,导致键盘用户无法与控件交互。按照 WCAG 2.1.1 (Keyboard) 标准,按钮必须响应 Enter 和 Space 键。

应用此 diff 添加键盘支持:

+  const onKeyDown = (e: React.KeyboardEvent) => {
+    if (e.key === 'Enter' || e.key === ' ') {
+      e.preventDefault();
+      if (!disabled) {
+        onStepMouseDown(e as any);
+      }
+    }
+  };
+
   return (
     <span
       {...sharedHandlerProps}
       onMouseDown={(e) => {
         onStepMouseDown(e);
       }}
+      onKeyDown={onKeyDown}
       aria-label={isUpAction ? 'Increase Value' : 'Decrease Value'}
       aria-disabled={disabled}
       className={mergedClassName}
       style={style}
     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return (
<div className={clsx(`${handlerClassName}-wrap`, classNames?.actions)} style={styles?.actions}>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e, true);
}}
aria-label="Increase Value"
aria-disabled={upDisabled}
className={upClassName}
>
{upNode || <span unselectable="on" className={`${prefixCls}-handler-up-inner`} />}
</span>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e, false);
}}
aria-label="Decrease Value"
aria-disabled={downDisabled}
className={downClassName}
>
{downNode || <span unselectable="on" className={`${prefixCls}-handler-down-inner`} />}
</span>
</div>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e);
}}
aria-label={isUpAction ? 'Increase Value' : 'Decrease Value'}
aria-disabled={disabled}
className={mergedClassName}
style={style}
>
{children || <span unselectable="on" className={`${prefixCls}-handler-${action}-inner`} />}
</span>
const onKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
if (!disabled) {
onStepMouseDown(e as any);
}
}
};
return (
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e);
}}
onKeyDown={onKeyDown}
aria-label={isUpAction ? 'Increase Value' : 'Decrease Value'}
aria-disabled={disabled}
className={mergedClassName}
style={style}
>
{children || <span unselectable="on" className={`${prefixCls}-handler-${action}-inner`} />}
</span>
);
🤖 Prompt for AI Agents
In src/StepHandler.tsx around lines 100 to 112, the span uses role="button" but
lacks keyboard handlers; add role="button" (if not already present) and
implement an onKeyDown handler that listens for Enter and Space keys to invoke
the same action as onMouseDown (call onStepMouseDown) — for Space also call
e.preventDefault() to avoid page scroll; optionally handle onKeyUp for Space if
your mouse handler relies on keyup/release semantics; ensure aria-disabled is
respected so the handlers early-return when disabled.

Comment on lines +103 to +105
onMouseDown={(e) => {
onStepMouseDown(e);
}}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

在交互处理器中检查 disabled 状态。

disabled=true 时,onMouseDown 处理器仍然会触发 onStepMouseDown,导致用户可以与禁用状态的按钮交互。这违反了 aria-disabled 的语义。

应用此 diff 添加 disabled 检查:

   <span
     {...sharedHandlerProps}
     onMouseDown={(e) => {
-      onStepMouseDown(e);
+      if (!disabled) {
+        onStepMouseDown(e);
+      }
     }}
     aria-label={isUpAction ? 'Increase Value' : 'Decrease Value'}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onMouseDown={(e) => {
onStepMouseDown(e);
}}
onMouseDown={(e) => {
if (!disabled) {
onStepMouseDown(e);
}
}}
🤖 Prompt for AI Agents
In src/StepHandler.tsx around lines 103 to 105, the onMouseDown handler always
calls onStepMouseDown even when the step is disabled; update the handler to
first check the component's disabled state (e.g., props.disabled or
aria-disabled) and bail out early when disabled is true so the click does
nothing and respects aria-disabled semantics; ensure the check uses the same
prop used elsewhere for disabled state and returns without calling
onStepMouseDown when disabled.

@zombieJ zombieJ merged commit aa6c583 into react-component:master Nov 3, 2025
9 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Nov 3, 2025
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