Skip to content

Conversation

@yangyanAurora
Copy link

@yangyanAurora yangyanAurora commented Dec 25, 2025

🤔 这个变动的性质是?

  • 新特性提交
  • 日常 bug 修复
  • 站点、文档改进
  • 演示代码改进
  • 组件样式/交互改进
  • TypeScript 定义更新
  • 包体积优化
  • 性能优化
  • 功能增强
  • 国际化改进
  • 重构
  • 代码风格优化
  • 测试用例
  • 分支合并
  • 其他改动(是关于什么的改动?)

🔗 相关 Issue

💡 需求背景和解决方案

☑️ 请求合并前的自查清单

⚠️ 请自检并全部勾选全部选项⚠️

  • 文档已补充或无须补充
  • 代码演示已提供或无须提供
  • TypeScript 定义已补充或无须补充
  • fork仓库代码是否为最新避免文件冲突
  • Files changed 没有 package.json lock 等无关文件

Summary by CodeRabbit

发行说明

  • 样式改进

    • 优化了表单项标签的文本换行行为,标签文本可在空间受限时自动换行以避免溢出
  • 功能增强

    • 提升了 Toast 通知的参数校验,现在对标题和内容均进行更严格的检查
    • Toast 的标题支持更丰富的内容格式(可接受更复杂的节点)

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions github-actions bot added action:review This PR needs more reviews (less than 2 approvals) 3.x Target branch 3.x labels Dec 25, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 25, 2025

Walkthrough

本PR包含三项改动:表单项标签由white-space: nowrap改为word-wrap: break-word以允许换行;Toast 的 show() 方法改为对 titlecontent 两项做参数级校验;将 BaseToasttitle 类型由 string 扩展为 ReactNode

Changes

Cohort / File(s) 变更摘要
表单项样式调整
src/packages/formitem/formitem.scss
.nut-form-item-label-right.nut-form-item-label-left 中将 white-space: nowrap 替换为 word-wrap: break-word,调整标签文本换行策略
Toast 参数校验增强
src/packages/toast/toast.tsx
show(option) 中,新增对 optiontitlecontent 字段的逐项校验(通过遍历并对指定键调用 errorMsg),替代原先仅对 content 的单一校验
Toast 类型与文档更新
src/types/spec/toast/base.ts, src/packages/toast/doc*.md
BaseToast<OVERLAY_PROPS>title 字段类型从 string 改为 ReactNode,并同步更新多语言文档中的 title 类型说明

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • irisSong
  • oasis-cloud

Poem

🐰 标签轻轻跳一圈,换行悄然来相见,
Toast 标题更宽容,校验细致不马虎,
一行代码一缕香,更新小改亦欢颜。

Pre-merge checks and finishing touches

❌ Failed checks (4 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning PR标题过于宽泛且缺乏具体说明,未能清晰传达主要变更内容。 建议将标题改为更具体的描述,如'fix: 更新Toast组件title属性类型支持ReactNode',以准确反映变更内容。
Description check ⚠️ Warning PR描述未填充,仅包含模板占位符,缺少关键信息如变动性质、相关Issue、解决方案和自检清单勾选。 请完整填写PR描述模板,包括勾选变动性质、补充相关Issue链接、详细说明需求背景和解决方案、勾选自检清单各项。
Linked Issues check ⚠️ Warning PR描述中相关Issue部分未填写,无法追溯此次变更的需求来源或相关讨论。 在PR描述中补充相关的Issue链接,说明此次变更的需求背景和相关讨论。
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed 虽然formitem.scss中的样式调整与主要变更(Toast title类型更新)关联不大,但整体变更范围相对集中。
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d005f1b and ec4c225.

📒 Files selected for processing (4)
  • src/packages/toast/doc.en-US.md
  • src/packages/toast/doc.md
  • src/packages/toast/doc.taro.md
  • src/packages/toast/doc.zh-TW.md
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: oasis-cloud
Repo: jdf2e/nutui-react PR: 2700
File: src/packages/animatingnumbers/animatingnumbers.harmony.css:25-32
Timestamp: 2024-11-06T05:56:06.800Z
Learning: 在优化 NutUI React 动画性能时,添加 `will-change` 属性可能会对布局产生影响,需要谨慎使用。
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (4)
src/packages/toast/doc.zh-TW.md (1)

62-62: 文档更新正确,与类型系统变更保持一致。

title 属性类型由 string 更新为 React.ReactNode,允许 Toast 标题接受更多类型的内容(如 JSX 元素、数字等),这与组件的类型定义保持一致。

src/packages/toast/doc.en-US.md (1)

64-64: 文档类型声明更新一致。

与其他语言版本保持同步,title 属性类型从 string 更新为 React.ReactNode,确保多语言文档的 API 规范一致性。

src/packages/toast/doc.taro.md (1)

63-63: Taro 平台文档类型声明一致更新。

Taro 版本文档也相应更新了 title 属性类型为 React.ReactNode,确保跨平台文档的 API 一致性。

src/packages/toast/doc.md (1)

61-61: 文档更新与实现一致。

title 属性类型已在所有实现文件中正确更新为 React.ReactNode。验证结果:

  • BaseToast 类型定义(src/types/spec/toast/base.ts)中 title 已声明为 ReactNode
  • WebToastProps 正确扩展 BaseToast ✓
  • TaroToastProps 正确扩展 BaseToast ✓
  • ReactNode 从 React 正确导入 ✓

变更在所有语言版本文档和实现代码中保持完全一致。


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.

@codecov
Copy link

codecov bot commented Dec 25, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.16%. Comparing base (da29016) to head (a4d2d05).
⚠️ Report is 1 commits behind head on feat_v3.x.

Additional details and impacted files
@@            Coverage Diff             @@
##           feat_v3.x    #3408   +/-   ##
==========================================
  Coverage      88.15%   88.16%           
==========================================
  Files            291      291           
  Lines          19212    19215    +3     
  Branches        2988     2990    +2     
==========================================
+ Hits           16937    16940    +3     
  Misses          2269     2269           
  Partials           6        6           

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

🧹 Nitpick comments (2)
src/packages/formitem/formitem.scss (1)

136-136: 标签换行功能已正确实现

white-space: nowrap 替换为 word-wrap: break-word 可以让表单标签文本自动换行,改善了长标签的显示效果。

不过需要注意,第 18 行的 .nut-form-item-label 类已经设置了 word-wrap: break-word。如果这些位置修饰符类(.nut-form-item-label-right.nut-form-item-label-left)通常与父类一起使用,则可能存在属性重复。建议验证这些类的实际应用场景,确认是否需要显式声明以提高 CSS 优先级。

#!/bin/bash
# 描述:查找 formitem 相关组件中这些 CSS 类的使用方式

# 搜索 .nut-form-item-label-right 和 .nut-form-item-label-left 的使用
rg -n -A3 -B3 --type=tsx --type=ts --type=jsx --type=js 'nut-form-item-label-(right|left)'

Also applies to: 142-142

src/packages/toast/toast.tsx (1)

66-68: 可选的代码简化建议

当前的过滤和迭代模式功能正确,但可以简化以提高可读性:

🔎 建议的重构方案
-  const checkParam = ['title', 'content']
-  Object.entries(option)
-    .filter(([k, v]) => checkParam.includes(k))
-    .forEach(([k, v]) => errorMsg(v))
+  const checkParam = ['title', 'content'] as const
+  checkParam.forEach((key) => {
+    if (key in option) {
+      errorMsg(option[key])
+    }
+  })
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2060383 and d005f1b.

📒 Files selected for processing (3)
  • src/packages/formitem/formitem.scss
  • src/packages/toast/toast.tsx
  • src/types/spec/toast/base.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: oasis-cloud
Repo: jdf2e/nutui-react PR: 2700
File: src/packages/animatingnumbers/animatingnumbers.harmony.css:25-32
Timestamp: 2024-11-06T05:56:06.800Z
Learning: 在优化 NutUI React 动画性能时,添加 `will-change` 属性可能会对布局产生影响,需要谨慎使用。
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: test

Comment on lines +65 to +68
const checkParam = ['title', 'content']
Object.entries(option)
.filter(([k, v]) => checkParam.includes(k))
.forEach(([k, v]) => errorMsg(v))
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

❓ Verification inconclusive

React rendering 0 and false as child elements behavior


Short answer

  • React treats false, true, null and undefined as “ignore me” when used as children — they produce no DOM output. It DOES render numbers and strings, so 0 is rendered as text. [1][2]

Why

  • React’s renderer only skips booleans/null/undefined to support common conditional patterns (e.g. cond && ). Numbers (including 0) are valid renderable children, so 0 will be inserted as text. [1][2]

How to avoid accidentally showing 0

  • Use an explicit boolean expression: {items.length > 0 && }. [2]
  • Use a ternary: {count ? {count} : null} or {count > 0 ? {count} : null}. [3]
  • Coerce to null when you want nothing: {condition ? : null} (preferred). [3]

Examples

  • 0 && // renders "0"
  • false && // renders nothing
  • {count ? {count} : null} // only shows when count != 0. [1][3]

Sources

  • React “False in JSX” tip. [1]
  • Explanation of children and length-check pitfall. [2]
  • Common fixes / patterns (ternary vs &&). [3]

Script executed:

# First, let's examine the toast.tsx file at the specified lines
fd "toast.tsx" -type f | head -20

Repository: jdf2e/nutui-react


Repository: jdf2e/nutui-react
Script execution failed with unrecoverable error: [CAPABILITY:RUN_SHELL_SCRIPT] Failed to clone repository jdf2e/nutui-react: Clone operation failed


Script executed:

# Also search for base.ts to check the type changes mentioned
fd "base.ts" -type f | grep -i toast

Repository: jdf2e/nutui-react


Repository: jdf2e/nutui-react
Exit code: 1

stderr:

error: 'ype' isn't a valid value for '--type <filetype>'
  [possible values: file, directory, symlink, executable, empty, socket, pipe]

For more information try '--help'

Script executed:

# List all toast-related files
find . -name "*toast*" -type f 2>/dev/null | head -20

Repository: jdf2e/nutui-react


Repository: jdf2e/nutui-react
Exit code: 0

stdout:

./src/packages/toast/__test__/toast.spec.tsx
./src/packages/toast/toast.scss
./src/packages/toast/toast.taro.tsx
./src/packages/toast/toast.tsx

Script executed:

# Search for errorMsg function definition
rg "errorMsg" -A 5 -B 2

Repository: jdf2e/nutui-react


Repository: jdf2e/nutui-react
Exit code: 0

stdout:

src/sites/sites-react/doc/docs/react/migrate-from-v1.md-- `noButton` 重命名为 `hideFooter`
src/sites/sites-react/doc/docs/react/migrate-from-v1.md-- `onOk` 重命名为 `onConfirm`
src/sites/sites-react/doc/docs/react/migrate-from-v1.md:- `errorMsg` 重命名为 `error`
src/sites/sites-react/doc/docs/react/migrate-from-v1.md-- 移除 `closeOnClickOverlay`,默认支持透传 Popup 属性
src/sites/sites-react/doc/docs/react/migrate-from-v1.md-- `title`、`description`、`tips`、`error` 类型修改为 `ReactNode`
src/sites/sites-react/doc/docs/react/migrate-from-v1.md-- `modelValue` 重命名为 `value`,受控模式
src/sites/sites-react/doc/docs/react/migrate-from-v1.md-- 新增 `onFoucs` 事件
src/sites/sites-react/doc/docs/react/migrate-from-v1.md-
--
src/sites/sites-react/doc/docs/taro/migrate-from-v1.md-- `noButton` 重命名为 `hideFooter`
src/sites/sites-react/doc/docs/taro/migrate-from-v1.md-- `onOk` 重命名为 `onConfirm`
src/sites/sites-react/doc/docs/taro/migrate-from-v1.md:- `errorMsg` 重命名为 `error`
src/sites/sites-react/doc/docs/taro/migrate-from-v1.md-- 移除 `closeOnClickOverlay`,默认支持透传 Popup 属性
src/sites/sites-react/doc/docs/taro/migrate-from-v1.md-- `title`、`description`、`tips`、`error` 类型修改为 `ReactNode`
src/sites/sites-react/doc/docs/taro/migrate-from-v1.md-- `modelValue` 重命名为 `value`,受控模式
src/sites/sites-react/doc/docs/taro/migrate-from-v1.md-- 新增 `onFoucs` 事件
src/sites/sites-react/doc/docs/taro/migrate-from-v1.md-
--
src/packages/toast/toast.tsx-}
src/packages/toast/toast.tsx-
src/packages/toast/toast.tsx:const errorMsg = (msg: any) => {
src/packages/toast/toast.tsx-  if (!msg) {
src/packages/toast/toast.tsx-    console.warn('[NutUI Toast]: msg cannot be null')
src/packages/toast/toast.tsx-  }
src/packages/toast/toast.tsx-}
src/packages/toast/toast.tsx-
src/packages/toast/toast.tsx-function show(option: ToastNativeProps | string) {
src/packages/toast/toast.tsx-  if (typeof option === 'string') {
src/packages/toast/toast.tsx:    errorMsg(option)
src/packages/toast/toast.tsx-    return notice({ content: option })
src/packages/toast/toast.tsx-  }
src/packages/toast/toast.tsx-  const checkParam = ['title', 'content']
src/packages/toast/toast.tsx-  Object.entries(option)
src/packages/toast/toast.tsx-    .filter(([k, v]) => checkParam.includes(k))
src/packages/toast/toast.tsx:    .forEach(([k, v]) => errorMsg(v))
src/packages/toast/toast.tsx-  return notice({
src/packages/toast/toast.tsx-    ...option,
src/packages/toast/toast.tsx-  })
src/packages/toast/toast.tsx-}
src/packages/toast/toast.tsx-
--
src/packages/notify/notify.tsx-}
src/packages/notify/notify.tsx-
src/packages/notify/notify.tsx:const errorMsg = (message: any) => {
src/packages/notify/notify.tsx-  if (!message) {
src/packages/notify/notify.tsx-    console.warn('[NutUI Notify]: message不能为空')
src/packages/notify/notify.tsx-  }
src/packages/notify/notify.tsx-}
src/packages/notify/notify.tsx-
src/packages/notify/notify.tsx-export default {
src/packages/notify/notify.tsx-  text(message: string | React.ReactNode, option = {}) {
src/packages/notify/notify.tsx:    errorMsg(message)
src/packages/notify/notify.tsx-    return notice({ message, type: 'base', ...option })
src/packages/notify/notify.tsx-  },
src/packages/notify/notify.tsx-  hide() {
src/packages/notify/notify.tsx-    if (messageInstance) {
src/packages/notify/notify.tsx-      messageInstance.destroy()
--
packages/nutui-codemod/transforms/rules/props-rules.js-      replacer: 'onConfirm',
packages/nutui-codemod/transforms/rules/props-rules.js-    },
packages/nutui-codemod/transforms/rules/props-rules.js:    errorMsg: {
packages/nutui-codemod/transforms/rules/props-rules.js-      action: 'rename',
packages/nutui-codemod/transforms/rules/props-rules.js-      replacer: 'error',
packages/nutui-codemod/transforms/rules/props-rules.js-    },
packages/nutui-codemod/transforms/rules/props-rules.js-    modelValue: {
packages/nutui-codemod/transforms/rules/props-rules.js-      action: 'rename',

Script executed:

# Search for type definitions in base.ts
rg "title.*ReactNode\|content.*ReactNode" -A 2 -B 2

Repository: jdf2e/nutui-react


Repository: jdf2e/nutui-react
Exit code: 1


Script executed:

# Get the specific lines from toast.tsx
rg "const checkParam = \['title'" -A 5 -B 5

Repository: jdf2e/nutui-react


Repository: jdf2e/nutui-react
Exit code: 0

stdout:

src/packages/toast/toast.tsx-function show(option: ToastNativeProps | string) {
src/packages/toast/toast.tsx-  if (typeof option === 'string') {
src/packages/toast/toast.tsx-    errorMsg(option)
src/packages/toast/toast.tsx-    return notice({ content: option })
src/packages/toast/toast.tsx-  }
src/packages/toast/toast.tsx:  const checkParam = ['title', 'content']
src/packages/toast/toast.tsx-  Object.entries(option)
src/packages/toast/toast.tsx-    .filter(([k, v]) => checkParam.includes(k))
src/packages/toast/toast.tsx-    .forEach(([k, v]) => errorMsg(v))
src/packages/toast/toast.tsx-  return notice({
src/packages/toast/toast.tsx-    ...option,

参数验证逻辑存在缺陷:对 ReactNode 类型的检查过于严格

虽然扩展验证范围到 titlecontent 的思路正确,但 errorMsg 函数使用 !msg 检查存在问题。根据 React 规范,数字 0 是有效的 ReactNode 值(会被渲染为文本),而 falsenullundefined 才是被忽略的值。当前的检查逻辑会将 0 误判为无效。

同时,由于 titlecontent 现在是 ReactNode 类型,警告消息"msg cannot be null"不够准确。

建议改进验证逻辑,准确检查真正需要避免的空值:

const errorMsg = (msg: any) => {
-  if (!msg) {
-    console.warn('[NutUI Toast]: msg cannot be null')
+  if (msg == null || msg === '') {
+    console.warn('[NutUI Toast]: title and content cannot be empty')
   }
}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/packages/toast/toast.tsx around lines 65-68, the current validation uses
a falsy check (!msg) which incorrectly treats 0 as invalid; update the
validation to explicitly reject only React-ignored values (null, undefined, and
false) — e.g. check msg === null || msg === undefined || msg === false — and
update the warning text to something like "msg cannot be null, undefined, or
false" to reflect ReactNode types.

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

Labels

3.x Target branch 3.x action:review This PR needs more reviews (less than 2 approvals) size/S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant