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(checkbox): v14 #2802

Closed
wants to merge 4 commits into from
Closed

Conversation

oasis-cloud
Copy link
Collaborator

@oasis-cloud oasis-cloud commented Nov 27, 2024

🤔 这个变动的性质是?

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

🔗 相关 Issue

💡 需求背景和解决方案

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

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

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

Summary by CodeRabbit

  • 新功能
    • 引入新的 Icon 组件,简化复选框图标的渲染逻辑。
    • 复选框状态(正常、禁用、已选、已禁用)的视觉表示得到了增强。
  • 样式
    • 重构复选框样式,分离核心功能与视觉表现,提升了复选框的视觉效果。
  • 测试
    • 更新测试用例以反映新的复选框状态类名,确保测试与组件实现保持一致。

Copy link

coderabbitai bot commented Nov 27, 2024

Walkthrough

此次变更涉及对复选框组件的样式和结构进行重组。.nut-checkbox 类被拆分为 .nut-checkbox-self.nut-checkbox 两个类,后者引入了新的样式和状态管理。此外,复选框的图标渲染逻辑也进行了简化,使用新的 Icon 组件替代了多个具体的图标组件。整体上,这些修改旨在提升复选框的视觉表现和代码组织。

Changes

文件路径 更改摘要
src/packages/checkbox/checkbox.scss 修改了 .nut-checkbox 类的结构,新增 .nut-checkbox-self 类,整合复选框状态的样式。
src/packages/checkbox/checkbox.taro.tsx 替换了复选框组件中的图标组件,使用新的 Icon 组件,移除了旧的图标导入语句。
src/packages/checkbox/checkbox.tsx 同样替换了复选框中的图标组件,简化了图标渲染逻辑,保持了原有的状态管理和功能。
src/packages/checkbox/icon.tsx 新增了 Icon 组件,定义了 IconProps 接口,支持灵活的图标渲染和样式管理。
scripts/build-taro.mjs 更新了构建脚本以包含 icon.tsx 文件的处理,并改进了 SCSS 文件的构建逻辑。

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Checkbox
    participant Icon

    User->>Checkbox: 点击复选框
    Checkbox->>Icon: 渲染图标状态
    Icon-->>Checkbox: 返回图标
    Checkbox-->>User: 更新复选框状态
Loading

Possibly related PRs

Poem

兔子在草丛中跳跃,
复选框焕然一新,
图标闪闪发光,
样式整齐如新。
点击间状态变幻,
用户欢笑声声。 🐇✨


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.

@github-actions github-actions bot added the 3.x label Nov 27, 2024
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: 6

🧹 Outside diff range and nitpick comments (5)
src/packages/checkbox/icon.tsx (2)

10-22: 建议优化组件性能和类名处理

  1. 考虑使用 React.memo 来避免不必要的重渲染
  2. 建议使用类名工具库(如 classnames)来处理类名组合,以提高可维护性

建议按照以下方式修改:

+import classNames from 'classnames'
+
-const Icon = (props: Partial<IconProps>) => {
+const Icon = React.memo((props: Partial<IconProps>) => {
   const { tag, classPrefix, name } = mergeProps(
     {
       tag: 'div',
       classPrefix: 'nut-checkbox-self',
       name: 'normal',
     },
     props
   )
   return createElement<{ className: string }>(tag, {
-    className: `${classPrefix} ${classPrefix}-${name}`,
+    className: classNames(classPrefix, `${classPrefix}-${name}`),
   })
-}
+})

1-24: 建议完善组件文档和测试

为了提高组件的可维护性和可靠性,建议:

  1. 添加组件的 JSDoc 文档,包括:
    • 组件的用途说明
    • 属性的详细描述
    • 使用示例
  2. 添加单元测试,覆盖:
    • 不同状态的渲染结果
    • 属性的默认值处理
    • 自定义标签的渲染

需要我帮助生成相关的文档模板或测试用例吗?

src/packages/checkbox/checkbox.scss (2)

3-14: 建议优化边框宽度以提高可见度

border: 0.5px 在某些显示设备上可能显示不清晰,建议考虑使用 1px 或使用 transform: scale() 实现更细的边框。

-    border: 0.5px solid $color-text-disabled;
+    border: 1px solid $color-text-disabled;

Line range hint 1-200: 整体评估:代码结构清晰,但建议进行性能优化

代码结构组织良好,状态管理清晰,但有以下建议:

  1. 考虑使用 CSS 变量统一管理尺寸和颜色值
  2. 可以通过 CSS 选择器优化来减少样式规则的重复
  3. 建议添加响应式断点支持

建议考虑以下优化方向:

  1. 将重复的样式值抽取为主题变量
  2. 添加媒体查询以支持不同设备尺寸
  3. 考虑使用 CSS Grid 优化布局结构
src/packages/checkbox/checkbox.tsx (1)

105-125: 建议重构图标渲染逻辑以提高可读性

当前的条件渲染逻辑较为复杂,建议进行优化以提高代码的可维护性。

建议采用以下方式重构:

  const renderIcon = () => {
-   if (innerDisabled) {
-     if (innerIndeterminate) {
-       return <Icon name="disabled" />
-     }
-     if (innerChecked) {
-       return <Icon name="checked-disabled" />
-     }
-     return <Icon name="disabled" />
-   }
-   if (!innerChecked) {
-     return React.isValidElement(icon) ? icon : <Icon name="normal" />
-   }
-   if (innerIndeterminate) {
-     return React.isValidElement(indeterminateIcon) ? (
-       indeterminateIcon
-     ) : (
-       <Icon name="disabled" />
-     )
-   }
-   return React.isValidElement(activeIcon) ? (
-     activeIcon
-   ) : (
-     <Icon name="checked" />
-   )
+   const getIconName = () => {
+     if (innerDisabled) {
+       if (innerChecked) return 'checked-disabled'
+       return 'disabled'
+     }
+     if (innerIndeterminate) return 'disabled'
+     if (innerChecked) return 'checked'
+     return 'normal'
+   }
+
+   const customIcon = innerChecked ? activeIcon : icon
+   return React.isValidElement(customIcon) ? customIcon : <Icon name={getIconName()} />
  }

优化建议:

  1. 将图标名称的确定逻辑独立出来,使用单独的函数处理
  2. 减少嵌套的条件判断,使逻辑更清晰
  3. 统一处理自定义图标的逻辑

这样的重构可以:

  • 降低代码复杂度
  • 提高可读性
  • 使维护更容易
  • 减少潜在的错误
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9332996 and 8e28032.

📒 Files selected for processing (4)
  • src/packages/checkbox/checkbox.scss (1 hunks)
  • src/packages/checkbox/checkbox.taro.tsx (2 hunks)
  • src/packages/checkbox/checkbox.tsx (2 hunks)
  • src/packages/checkbox/icon.tsx (1 hunks)
🔇 Additional comments (3)
src/packages/checkbox/icon.tsx (1)

24-24: 导出语句符合规范

默认导出方式适合单组件文件,符合最佳实践。

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

13-13: 导入更改提升了代码组织性!

将多个具体的图标组件替换为统一的 Icon 组件是个很好的改进,这样可以:

  • 减少重复代码
  • 提高可维护性
  • 使图标管理更加集中和统一
src/packages/checkbox/checkbox.taro.tsx (1)

8-8: 导入更改看起来不错!

将图标处理逻辑集中到本地组件是一个很好的架构决策,这样可以:

  1. 集中管理图标逻辑
  2. 减少外部依赖
  3. 便于维护和修改图标行为

src/packages/checkbox/icon.tsx Show resolved Hide resolved
Comment on lines +16 to +62
&-checked,
&-disabled,
&-checked-disabled {
&:after {
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
content: ' ';
background: $color-primary-text;
}
}

&-icon-checked {
color: $color-primary;
transition-duration: 0.3s;
transition-property: color, border-color, background-color;
&-checked {
background: linear-gradient(
90deg,
$color-primary-stop-1 0%,
$color-primary-stop-2 100%
);
box-shadow: 0px 2px 4px 0px rgba(255, 15, 35, 0.2);

&:after {
width: 8px;
height: 8px;
border-radius: 50%;
}
}

&-disabled {
background: $color-text-disabled;

&.nut-checkbox-icon-disabled {
color: $color-primary-disabled-special;
&:after {
width: 8px;
height: 1.5px;
}
}

&-checked-disabled {
background: $color-primary-disabled-special;

&:after {
width: 8px;
height: 8px;
border-radius: 50%;
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

建议将固定数值抽取为 CSS 变量

代码中存在多个魔法数字(如 8px1.5px 等),建议将这些值抽取为 CSS 变量以提高可维护性和一致性。

+ $checkbox-indicator-size: 8px;
+ $checkbox-disabled-height: 1.5px;

  &-checked {
    &:after {
-      width: 8px;
-      height: 8px;
+      width: $checkbox-indicator-size;
+      height: $checkbox-indicator-size;
      border-radius: 50%;
    }
  }

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

Comment on lines 72 to 74
color: $checkbox-label-color;
white-space: nowrap;

Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

建议使用文本截断 mixin 替代单独的 white-space: nowrap

代码库中已有成熟的文本截断处理方案,建议使用 @include text-ellipsis()@include oneline-ellipsis() 来处理标签文本。其他组件(如 Tabs、NoticeBar)在使用 white-space: nowrap 时都配合了文本截断样式。

建议修改为:

.nut-checkbox-label {
    margin-left: $checkbox-label-margin-left;
    font-size: $checkbox-label-font-size;
    color: $checkbox-label-color;
    @include text-ellipsis();
}
🔗 Analysis chain

建议重新考虑 white-space: nowrap 的使用

强制不换行可能导致长文本标签溢出容器。建议添加文本截断或允许适当换行的样式。

.nut-checkbox-label {
    margin-left: $checkbox-label-margin-left;
    font-size: $checkbox-label-font-size;
    color: $checkbox-label-color;
-    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    word-break: break-word;
}
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 检查是否有其他组件使用类似的标签处理方式
rg -l 'white-space:\s*nowrap' 'src/packages/*/*.scss'

Length of output: 117


Script:

#!/bin/bash
# 使用 fd 查找所有 scss 文件并使用 rg 搜索 white-space: nowrap
fd -e scss -x rg -l 'white-space:\s*nowrap' {}

Length of output: 525


Script:

#!/bin/bash
# 检查其他组件中 white-space: nowrap 的具体使用场景和相关样式
rg 'white-space:\s*nowrap' -B 2 -A 2 ./src/packages/tour/tour.scss ./src/packages/tabs/tabs.scss ./src/packages/noticebar/noticebar.scss ./src/packages/navbar/navbar.scss

# 检查是否有文本截断相关的 mixin 定义
cat ./src/styles/mixins/text-ellipsis.scss

Length of output: 2322

@@ -97,31 +97,31 @@ export const Checkbox: FC<
const renderIcon = () => {
if (innerDisabled) {
if (innerIndeterminate) {
return <CheckDisabled className={color()} />
return <Icon tag={View} name="disabled" />
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

建议区分不同的禁用状态图标

目前在不同的禁用状态下使用了相同的图标名称 "disabled",这可能会导致用户体验问题。建议为不同的禁用状态使用独特的图标。

建议修改如下:

- return <Icon tag={View} name="disabled" />
+ return <Icon tag={View} name="indeterminate-disabled" />
- return <Icon tag={View} name="disabled" />
+ return <Icon tag={View} name="unchecked-disabled" />

Also applies to: 105-105

Comment on lines +100 to +124
return <Icon tag={View} name="disabled" />
}
if (innerChecked) {
return <Checked className={color()} />
return <Icon tag={View} name="checked-disabled" />
}
return <CheckDisabled className={color()} />
return <Icon tag={View} name="disabled" />
}
if (!innerChecked) {
return React.isValidElement(icon) ? (
icon
) : (
<CheckNormal className={color()} />
<Icon tag={View} name="normal" />
)
}
if (innerIndeterminate) {
return React.isValidElement(indeterminateIcon) ? (
indeterminateIcon
) : (
<CheckDisabled className={color()} />
<Icon tag={View} name="disabled" />
)
}
return React.isValidElement(activeIcon) ? (
activeIcon
) : (
<Checked className={color()} />
<Icon tag={View} name="checked" />
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

建议添加图标名称的类型检查

为了提高代码的可维护性和类型安全性,建议为 Icon 组件的 name 属性添加类型定义。

建议在 Icon 组件中添加以下类型定义:

type IconName = 'disabled' | 'checked-disabled' | 'normal' | 'checked' | 'indeterminate' | 'indeterminate-disabled' | 'unchecked-disabled';

interface IconProps {
  tag: typeof View;
  name: IconName;
}

)
}
if (innerIndeterminate) {
return React.isValidElement(indeterminateIcon) ? (
indeterminateIcon
) : (
<CheckDisabled className={color()} />
<Icon tag={View} name="disabled" />
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

修复 indeterminate 状态下的图标显示

当前 indeterminate 状态使用了 "disabled" 图标,这似乎是不正确的。

建议修改如下:

- return <Icon tag={View} name="disabled" />
+ return <Icon tag={View} name="indeterminate" />

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

Copy link
Collaborator

@Alex-huxiyang Alex-huxiyang left a comment

Choose a reason for hiding this comment

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

可以看下CI的test未通过

Copy link

codecov bot commented Dec 4, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 83.99%. Comparing base (b3920f1) to head (40cfc6a).
Report is 47 commits behind head on feat_v3.x.

Additional details and impacted files
@@            Coverage Diff             @@
##           feat_v3.x    #2802   +/-   ##
==========================================
  Coverage      83.98%   83.99%           
==========================================
  Files            220      221    +1     
  Lines          17882    17877    -5     
  Branches        2676     2666   -10     
==========================================
- Hits           15019    15015    -4     
+ Misses          2858     2857    -1     
  Partials           5        5           

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between e800642 and 40cfc6a.

⛔ Files ignored due to path filters (1)
  • src/packages/checkbox/__test__/__snapshots__/checkbox.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (1)
  • src/packages/checkbox/__test__/checkbox.spec.tsx (3 hunks)
🔇 Additional comments (3)
src/packages/checkbox/__test__/checkbox.spec.tsx (3)

78-79: 选择器更新符合新的命名规范!

测试用例中的类选择器已更新为新的命名规范,同时保持了原有的测试逻辑完整性。


127-129: 选择器正确反映了组合状态!

测试用例中的类选择器 .nut-checkbox-self-checked-disabled 准确地反映了复选框的选中且禁用状态。


182-182: 选择器更新保持一致性!

列表模式测试中的类选择器更新与之前的更改保持一致,符合新的命名规范。

Comment on lines +136 to +139
expect(container.querySelector('.nut-checkbox-self-disabled')).toBeTruthy()
// expect(
// container.querySelector('.nut-checkbox-self-indeterminate')
// ).toHaveClass('nut-checkbox-self-disabled')
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

建议完善组合状态的测试覆盖

当前测试用例只验证了禁用状态,但根据测试名称,应该同时验证 disabledindeterminate 两种状态。建议取消注释并完善测试断言。

建议修改为:

  expect(container.querySelector('.nut-checkbox-self-disabled')).toBeTruthy()
-  // expect(
-  //   container.querySelector('.nut-checkbox-self-indeterminate')
-  // ).toHaveClass('nut-checkbox-self-disabled')
+  expect(container.querySelector('.nut-checkbox-self-indeterminate')).toBeTruthy()
📝 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
expect(container.querySelector('.nut-checkbox-self-disabled')).toBeTruthy()
// expect(
// container.querySelector('.nut-checkbox-self-indeterminate')
// ).toHaveClass('nut-checkbox-self-disabled')
expect(container.querySelector('.nut-checkbox-self-disabled')).toBeTruthy()
expect(container.querySelector('.nut-checkbox-self-indeterminate')).toBeTruthy()

expect(
container.querySelector('.nut-checkbox-icon-indeterminate')
).toBeTruthy()
expect(container.querySelector('.nut-checkbox-self-disabled')).toBeTruthy()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

测试用例与测试名称不符

该测试用例命名为测试 indeterminate 状态,但实际上在验证 disabled 状态。建议修改测试用例以确保正确验证 indeterminate 状态。

建议修改为:

-  expect(container.querySelector('.nut-checkbox-self-disabled')).toBeTruthy()
+  expect(container.querySelector('.nut-checkbox-self-indeterminate')).toBeTruthy()
📝 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
expect(container.querySelector('.nut-checkbox-self-disabled')).toBeTruthy()
expect(container.querySelector('.nut-checkbox-self-indeterminate')).toBeTruthy()

@oasis-cloud
Copy link
Collaborator Author

等待Icon,所以转 Draft

@oasis-cloud oasis-cloud marked this pull request as draft December 5, 2024 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants