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/actions #238

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Feat/actions #238

wants to merge 3 commits into from

Conversation

disturbwe
Copy link

@disturbwe disturbwe commented Nov 25, 2024

Summary by CodeRabbit

  • 新功能
    • 引入了 ActionMenu 组件,支持渲染带有操作项的下拉菜单。
    • 新增 Actions 组件,用于渲染一组操作项,并支持可选的工具提示。
    • 新增多个 Demo 组件,展示不同的操作项和用法。
  • 文档
    • 添加了中英文文档,涵盖 Actions 组件及其用法。
    • 更新了 basic.mdsub.md 文件,增加了中英文支持。
  • 测试
    • findItem 函数和 Actions 组件添加了单元测试,确保功能正常。

Copy link
Contributor

coderabbitai bot commented Nov 25, 2024

📝 Walkthrough

Walkthrough

此次更改引入了多个新的 React 组件和相关的测试、文档以及样式配置,主要集中在 Actions 组件及其功能上。新增的 ActionMenu 组件提供了一个可自定义的下拉菜单,支持不同语言的文档更新。同时,添加了针对 findItem 函数和 Actions 组件的单元测试,确保其功能的正确性。文档部分也增加了中英文支持,以便于多语言用户的使用。

Changes

文件路径 更改摘要
components/actions/ActionMenu.tsx 新增 ActionMenu 组件,包含 findItem 函数,用于根据键路径查找动作项。
components/actions/tests/actionMenu.test.tsx findItem 函数新增测试套件,验证其在不同场景下的功能。
components/actions/tests/actions.test.tsx Actions 组件新增单元测试,验证渲染、点击处理和子菜单的功能。
components/actions/demo/basic.md basic.md 文件中新增中英文使用说明。
components/actions/demo/basic.tsx 新增 Demo 组件,展示基本的动作项和点击处理。
components/actions/demo/sub.md sub.md 文件中新增中英文使用说明。
components/actions/demo/sub.tsx 新增 Demo 组件,展示包含嵌套子项的动作项。
components/actions/demo/variant.md variant.md 文件中新增中英文使用说明。
components/actions/demo/variant.tsx 新增 Demo 组件,展示变体功能的动作项。
components/actions/index.en-US.md 新增英文文档,全面介绍 Actions 组件的使用和 API。
components/actions/index.tsx 新增 Actions 组件及其类型 ActionsProps 的导出。
components/actions/index.zh-CN.md 新增中文文档,全面介绍 Actions 组件的使用和 API。
components/actions/interface.ts 新增多个 TypeScript 接口和类型,定义动作项的结构。
components/actions/style/index.ts 新增样式逻辑,定义 Actions 组件的样式生成函数。
components/index.ts index.ts 文件中新增 Actions 组件的导出。
components/theme/components.ts ComponentTokenMap 接口中新增 Actions 属性。
components/x-provider/context.ts XComponentsConfig 接口中新增 actions 属性。

Suggested reviewers

  • MadCcc

🐰 在草地上跳跃欢快,
新组件如花绽放开。
菜单多样任你选,
多语言助你无碍。
代码美丽如春天,
祝贺更新乐开怀! 🌼


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

github-actions bot commented Nov 25, 2024

Preview is ready

Copy link

size-limit report 📦

Path Size
dist/antdx.min.js 41.08 KB (+602 B 🔺)

Copy link
Contributor

@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: 14

🧹 Outside diff range and nitpick comments (17)
components/actions/demo/basic.tsx (1)

6-17: 建议实现国际化支持

当前的文本标签是硬编码的中文字符串。建议使用国际化解决方案来支持多语言。

建议按照以下方式修改:

+import { useIntl } from '@ant-design/x';
+
+const Demo: React.FC = () => {
+  const intl = useIntl();
+
 const actionItems = [
   {
     key: 'retry',
     icon: <RedoOutlined />,
-    label: '重试',
+    label: intl.formatMessage({ id: 'actions.retry' }),
   },
   {
     key: 'copy',
     icon: <CopyOutlined />,
-    label: '复制',
+    label: intl.formatMessage({ id: 'actions.copy' }),
   },
 ];
components/actions/demo/variant.tsx (1)

1-4: 建议添加类型导入以增强类型安全性

建议从 @ant-design/x 中显式导入 ActionsItem 类型,以便更好地定义 actionItems 的类型。

 import { CopyOutlined, RedoOutlined } from '@ant-design/icons';
-import { Actions, ActionsProps } from '@ant-design/x';
+import { Actions, ActionsProps, ActionsItem } from '@ant-design/x';
 import { message } from 'antd';
 import React from 'react';
components/actions/demo/sub.tsx (1)

1-10: 建议对导入进行分组整理

建议将导入按照以下顺序分组:

  1. React 相关
  2. 第三方库(antd)
  3. 组件和图标
  4. 类型定义
+import React from 'react';
+
+import { message } from 'antd';
+import { Actions, ActionsProps } from '@ant-design/x';
+
 import {
   CopyOutlined,
   DeleteOutlined,
   RedoOutlined,
   ReloadOutlined,
   ShareAltOutlined,
 } from '@ant-design/icons';
-import { Actions, ActionsProps } from '@ant-design/x';
-import { message } from 'antd';
-import React from 'react';
components/actions/__tests__/actionMenu.test.tsx (2)

1-4: 清理未使用的导入并更新注释

代码中存在以下问题:

  1. 导入了未使用的 fireEvent
  2. 代码注释显示对文件结构存在不确定性

建议应用以下修改:

-import { fireEvent, render } from '@testing-library/react';
+import { render } from '@testing-library/react';
 import React from 'react';
-import ActionMenu, { findItem } from '../ActionMenu'; // Adjust the import according to your file structure
+import ActionMenu, { findItem } from '../ActionMenu';
 import { ActionItemType } from '../interface';

20-43: 建议增加测试用例覆盖更多边界情况

当前的测试用例覆盖了基本场景,但建议添加以下测试场景:

  1. 处理 children 属性为 undefined 的情况
  2. 处理 items 参数为空数组的情况
  3. 处理 items 参数为 undefined 的情况

是否需要我提供这些额外测试用例的实现代码?

components/actions/ActionMenu.tsx (2)

25-31: 建议添加属性验证

组件的关键属性(如 itemonClick)缺少运行时验证。建议添加 PropTypes 或运行时检查以提早发现问题。

建议添加以下验证:

if (!item) {
  throw new Error('ActionMenu: item prop is required');
}

60-62: 重新考虑 displayName 的设置时机

当前代码仅在生产环境设置 displayName,这与通常的做法相反。displayName 在开发环境下更有用,因为它有助于调试。

建议修改为:

-if (process.env.NODE_ENV === 'production') {
+if (process.env.NODE_ENV !== 'production') {
   ActionMenu.displayName = 'ActionMenu';
 }
components/actions/__tests__/actions.test.tsx (2)

5-20: 建议添加类型定义并清理测试间谍

以下几点建议:

  1. 为测试数据添加类型定义
  2. afterEach 中清理 console spy

建议添加以下代码:

+import { ActionItem } from '../types';  // 假设类型定义在这个位置

 describe('Actions Component', () => {
   const consoleSpy = jest.spyOn(console, 'log');
   const mockOnClick = jest.fn();
-  const items = [
+  const items: ActionItem[] = [
     // ... existing items ...
   ];

+  afterEach(() => {
+    consoleSpy.mockRestore();
+    mockOnClick.mockReset();
+  });

22-46: 建议增加错误场景测试

当前测试用例主要覆盖了正常流程,建议添加以下场景的测试:

  1. 空数据处理
  2. 禁用状态的项目点击
  3. 嵌套子菜单的多层级点击

需要我为这些场景生成测试代码吗?

components/actions/style/index.ts (1)

73-82: 建议添加必要的代码注释

为了提高代码的可维护性,建议为以下部分添加注释:

  1. prepareComponentToken 函数的用途和未来扩展计划
  2. mergeToken 的合并策略说明
  3. 样式钩子的使用说明

建议添加如下注释:

+// 准备组件令牌,预留扩展空间用于未来自定义主题
 export const prepareComponentToken: GetDefaultToken<'Prompts'> = () => ({});

 export default genStyleHooks(
   'Actions',
   (token) => {
+    // 合并组件级别的主题令牌
     const compToken = mergeToken<ActionsToken>(token, {});
     return [genActionsStyle(compToken)];
   },
   prepareComponentToken,
 );
components/actions/index.en-US.md (4)

1-12: 建议添加更具体的排序信息

在 frontmatter 中,建议为组件本身添加 order 属性,以便更好地控制组件在文档中的显示顺序。这样可以确保组件在导航中的位置更加合理。

 ---
 category: Components
 group:
   title: Common
   order: 0
 title: Actions
+order: 1
 description: Used for quickly configuring required action buttons or features in some AI scenarios.

14-16: 建议扩充使用场景说明

"When to Use" 部分的说明过于简单。建议添加以下内容:

  • 具体的使用场景示例
  • 与其他类似组件的对比
  • 最佳实践建议

18-23: 建议为示例添加简短描述

为了帮助用户更好地理解每个示例的用途,建议在每个示例链接下方添加简短的说明文字,解释该示例演示的具体功能和使用场景。

 <code src="./demo/basic.tsx">Basic</code>
+基础用法示例,展示 Actions 组件的基本功能和配置方式。
 <code src="./demo/sub.tsx">More Menu Items</code>
+展示如何配置带有子菜单的 Actions 组件。
 <code src="./demo/variant.tsx">Using Variants</code>
+展示不同的样式变体,包括无边框和带边框的显示方式。

25-62: 建议添加类型使用示例

API 文档的结构清晰,但对于复杂类型(如 ActionItemType)建议添加具体的代码示例,以帮助开发者更好地理解如何使用这些类型。

同时,建议在 onClick 回调函数的参数说明中添加更详细的类型定义。

建议添加如下示例代码:

// ActionItemType 使用示例
const actionItems: ActionItemType[] = [
  {
    label: '编辑',
    key: 'edit',
    icon: <EditIcon />,
    onClick: () => console.log('编辑被点击')
  },
  {
    label: '更多',
    key: 'more',
    icon: <MoreIcon />,
    children: [
      {
        label: '删除',
        key: 'delete',
        onClick: () => console.log('删除被点击')
      }
    ]
  }
];
components/actions/interface.ts (2)

4-47: 建议对类型定义进行优化

建议进行以下改进:

  1. 建议将 variant 的类型定义提取为单独的类型常量,以提高可维护性和重用性
  2. onClick 回调函数的类型可以更具体化,便于使用者理解

建议应用以下改动:

+export type ActionVariant = 'borderless' | 'border';
+
+export type OnClickCallback = (menuInfo: {
+  item: ActionItemType;
+  key: string;
+  keyPath: string[];
+  domEvent: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>;
+}) => void;
+
 export interface ActionsProps {
   // ... other properties ...
-  onClick?: (menuInfo: {
-    item: ActionItemType;
-    key: string;
-    keyPath: string[];
-    domEvent: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>;
-  }) => void;
+  onClick?: OnClickCallback;
   // ... other properties ...
-  variant?: 'borderless' | 'border';
+  variant?: ActionVariant;
 }

49-70: 建议增强 key 属性的类型安全性

当前 key 属性使用 string 类型可能过于宽松,建议考虑使用更严格的类型定义来防止潜在的错误。

建议考虑以下改进:

+export type ActionKey = string;
+
 export interface ItemType extends Pick<MenuItemProps, 'danger'> {
   // ... other properties ...
-  key: string;
+  key: ActionKey;
   // ... other properties ...
 }
components/actions/index.tsx (1)

13-44: 建议改进类型安全性和样式合并逻辑

当前实现可以通过以下方式优化:

  1. rootClassName 的默认值类型应该更明确
  2. 样式合并逻辑可以更简洁

建议应用以下改进:

- rootClassName = {},
+ rootClassName = '',
- const mergedStyle = {
-   ...style,
-   ...contextConfig.style,
- };
+ const mergedStyle = { ...contextConfig.style, ...style };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d218f8a and 13f1209.

⛔ Files ignored due to path filters (1)
  • components/actions/__tests__/__snapshots__/demo.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (17)
  • components/actions/ActionMenu.tsx (1 hunks)
  • components/actions/__tests__/actionMenu.test.tsx (1 hunks)
  • components/actions/__tests__/actions.test.tsx (1 hunks)
  • components/actions/demo/basic.md (1 hunks)
  • components/actions/demo/basic.tsx (1 hunks)
  • components/actions/demo/sub.md (1 hunks)
  • components/actions/demo/sub.tsx (1 hunks)
  • components/actions/demo/variant.md (1 hunks)
  • components/actions/demo/variant.tsx (1 hunks)
  • components/actions/index.en-US.md (1 hunks)
  • components/actions/index.tsx (1 hunks)
  • components/actions/index.zh-CN.md (1 hunks)
  • components/actions/interface.ts (1 hunks)
  • components/actions/style/index.ts (1 hunks)
  • components/index.ts (1 hunks)
  • components/theme/components.ts (2 hunks)
  • components/x-provider/context.ts (2 hunks)
✅ Files skipped from review due to trivial changes (3)
  • components/actions/demo/basic.md
  • components/actions/demo/sub.md
  • components/actions/demo/variant.md
🧰 Additional context used
🪛 LanguageTool
components/actions/index.zh-CN.md

[uncategorized] ~23-~23: A punctuation mark might be missing here.
Context: ... 更多菜单项 使用变体</co...

(AI_EN_LECTOR_MISSING_PUNCTUATION)

🔇 Additional comments (17)
components/actions/demo/basic.tsx (2)

1-4: 导入声明看起来很好!

导入声明简洁明了,包含了所有必要的依赖项。


26-26: 导出语句正确!

组件导出方式符合 React 规范。

components/actions/demo/variant.tsx (1)

26-26: 导出语句正确且符合最佳实践

默认导出符合组件命名规范。

components/theme/components.ts (2)

1-1: 导入语句的位置符合字母顺序规范!

新增的 ActionsComponentToken 导入语句正确地放置在了按字母顺序排列的导入列表的开头。


20-20: 验证 Actions 组件的主题令牌定义

新增的 Actions 属性扩展了组件主题定制能力,建议确认相关的样式令牌是否完整定义。

✅ Verification successful

Let me gather more information about the Actions component and its style definitions.


Let me check for the Actions component implementation and its style definitions.


Actions 组件的主题令牌定义已完整实现

从代码分析结果来看,Actions 组件的样式令牌已在 components/actions/style/index.ts 中完整定义:

  • 定义了 ActionsToken 接口继承自 FullToken<'Prompts'>
  • 实现了 genActionsStyle 样式生成函数
  • 通过 mergeToken 正确处理了组件令牌
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 描述:验证 Actions 组件的样式令牌定义是否完整

# 检查 actions/style 中的样式令牌定义
rg -A 10 "export interface ComponentToken" "../actions/style"

# 检查是否有其他组件在使用 Actions 的样式令牌
rg "ActionsComponentToken" --type ts

Length of output: 333


Script:

#!/bin/bash
# Search for Actions style related files
fd -e ts -e tsx actions/style

# Search for Actions component token definitions
rg -g '*.ts' -g '*.tsx' "interface.*Token.*Actions" -A 5

# Check imports of Actions style tokens
rg -g '*.ts' -g '*.tsx' "from.*actions/style"

Length of output: 250


Script:

#!/bin/bash
# Search for Actions component and its style implementation
fd -e ts -e tsx actions

# Check for any Actions related style or token definitions
rg -g '*.ts' -g '*.tsx' "Actions.*Token|Token.*Actions" -B 2 -A 5

# Look for Actions component implementation
ast-grep --pattern 'interface Actions {
  $$$
}'

Length of output: 2166

components/index.ts (2)

38-40: 导出结构符合规范!

新增的 Actions 组件导出遵循了文件中既有的模式,包括:

  • 组件默认导出和类型导出配对
  • 保持了适当的空行间距
  • 维持了字母顺序排序

39-40: 建议验证 Actions 组件的依赖关系

为确保组件能够正常工作,建议验证 Actions 组件的所有必要依赖是否都已正确导出。

✅ Verification successful

Actions 组件依赖关系验证完成

经过验证,Actions 组件的依赖关系完整且正确:

  • 所有必要的类型和组件都已在 actions 目录中正确导出,包括 ActionsProps 接口和主组件
  • 组件被其他模块正常引用,包括示例代码和测试
  • 组件结构完整,包含了必要的样式、接口定义和测试文件
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 描述:验证 Actions 组件的依赖关系

# 检查 actions 目录中的导出
rg -t typescript "export" ./components/actions/

# 检查是否有其他组件依赖 Actions
rg -t typescript "import.*Actions.*from" -g '!index.ts'

Length of output: 175


Script:

#!/bin/bash
# 检查 actions 目录中的导出
rg "export" ./components/actions/

# 检查是否有其他组件依赖 Actions
rg "import.*Actions.*from" -g '!index.ts'

# 查找 actions 相关文件
fd actions ./components/

# 检查 actions 目录的内容
ls -la ./components/actions/ 2>/dev/null || echo "Directory not found"

Length of output: 3124

components/actions/__tests__/actionMenu.test.tsx (1)

7-18: 测试数据结构设计合理

测试数据结构完整,包含了根级别项目和嵌套项目,能够覆盖各种测试场景。

components/x-provider/context.ts (2)

4-4: 导入语句正确且符合规范!

新增的 ActionsProps 类型导入遵循了现有的导入模式,并且与其他组件类型导入保持一致。


37-37: 配置接口扩展合理!

新增的 actions 配置属性:

  • 遵循了现有的组件配置模式
  • 正确使用了 ComponentStyleConfig 泛型类型
  • 保持了可选属性的一致性
components/actions/ActionMenu.tsx (2)

46-58: 代码实现规范,符合最佳实践

组件渲染逻辑清晰,正确使用了 Ant Design 的 Dropdown 组件,并保持了良好的样式命名规范。


1-64: 建议增加测试用例覆盖

该组件包含复杂的业务逻辑,建议添加以下测试场景:

  1. 菜单项点击事件处理
  2. 空值处理
  3. 自定义触发行为
  4. 样式类名生成

运行以下脚本检查现有测试覆盖情况:

components/actions/__tests__/actions.test.tsx (1)

1-4: 导入语句看起来不错!

导入了必要的测试工具和组件,结构清晰。

components/actions/style/index.ts (1)

1-8: 导入和接口定义看起来合理!

接口定义清晰,类型继承关系正确。空的 ComponentToken 接口为后续扩展预留了空间。

components/actions/interface.ts (2)

1-2: 导入声明看起来没有问题!

类型导入清晰明确,符合组件的需求。


100-100: 联合类型定义合理!

ActionItemType 的联合类型定义清晰且符合需求。

components/actions/index.tsx (1)

1-11: 导入语句组织良好!

导入声明按照类型分组,包括第三方库、React 核心、内部工具和本地模块,结构清晰。

Comment on lines +19 to +24
const Demo: React.FC = () => {
const onClick: ActionsProps['onClick'] = ({ key, keyPath, item }) => {
message.success(`you click ${keyPath.join(',')}`);
};
return <Actions items={actionItems} onClick={onClick} />;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

需要改进的几个方面

  1. 成功提示消息使用英文,而界面标签使用中文,存在语言不一致的问题
  2. 缺少错误处理机制

建议按照以下方式修改:

 const Demo: React.FC = () => {
+  const intl = useIntl();
+
   const onClick: ActionsProps['onClick'] = ({ key, keyPath, item }) => {
-    message.success(`you click ${keyPath.join(',')}`);
+    try {
+      // 处理点击事件的逻辑
+      message.success(intl.formatMessage(
+        { id: 'actions.clicked' },
+        { path: keyPath.join(',') }
+      ));
+    } catch (error) {
+      message.error(intl.formatMessage({ id: 'actions.error' }));
+    }
   };
   return <Actions items={actionItems} onClick={onClick} />;
 };

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

Comment on lines +19 to +24
const Demo: React.FC = () => {
const onClick: ActionsProps['onClick'] = ({ key, keyPath, item }) => {
message.success(`you click ${keyPath.join(',')}`);
};
return <Actions items={actionItems} onClick={onClick} variant="border" />;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

建议完善错误处理和国际化支持

  1. 建议添加错误处理机制
  2. 成功提示信息需要支持国际化
  3. 考虑添加 loading 状态处理
 const Demo: React.FC = () => {
   const onClick: ActionsProps['onClick'] = ({ key, keyPath, item }) => {
-    message.success(`you click ${keyPath.join(',')}`);
+    try {
+      // 处理点击逻辑
+      message.success(t('actions.clickSuccess', { path: keyPath.join(',') }));
+    } catch (error) {
+      message.error(t('actions.clickError'));
+      console.error('Action click error:', error);
+    }
   };
   return <Actions items={actionItems} onClick={onClick} variant="border" />;
 };

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

Comment on lines +6 to +17
const actionItems = [
{
key: 'retry',
icon: <RedoOutlined />,
label: '重试',
},
{
key: 'copy',
icon: <CopyOutlined />,
label: '复制',
},
];
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

建议增加国际化支持并添加类型注解

  1. 建议使用国际化文案配置,而不是硬编码的中文文案
  2. actionItems 添加明确的类型注解
-const actionItems = [
+const actionItems: ActionsItem[] = [
   {
     key: 'retry',
     icon: <RedoOutlined />,
-    label: '重试',
+    label: t('actions.retry'),
   },
   {
     key: 'copy',
     icon: <CopyOutlined />,
-    label: '复制',
+    label: t('actions.copy'),
   },
 ];

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

Comment on lines +12 to +45
const actionItems: ActionsProps['items'] = [
{
key: 'retry',
label: '重试',
icon: <RedoOutlined />,
},
{
key: 'copy',
label: '复制',
icon: <CopyOutlined />,
},
{
key: 'more',
// icon: <EllipsisOutlined />, // 不传使用默认的icon
children: [
{
key: 'share',
label: '分享',
icon: <ShareAltOutlined />,
children: [
{ key: 'qq', label: 'QQ' },
{ key: 'wechat', label: '微信' },
],
},
{ key: 'import', label: '引用' },
{ key: 'delete', label: '删除', icon: <DeleteOutlined />, onClick: () => {}, danger: true },
],
},
{
key: 'clear',
label: '清空',
icon: <ReloadOutlined />,
},
];
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

需要改进的几个关键点

  1. 建议移除注释掉的代码(第25行)
  2. 删除操作的 onClick 处理器为空,可能会导致意外操作
  3. 建议添加国际化支持
  4. 建议为危险操作添加确认机制

建议进行如下修改:

 const actionItems: ActionsProps['items'] = [
   {
     key: 'retry',
-    label: '重试',
+    label: t('actions.retry'),
     icon: <RedoOutlined />,
   },
   // ... other items
   {
     key: 'delete',
     label: '删除',
     icon: <DeleteOutlined />,
-    onClick: () => {},
+    onClick: () => {
+      Modal.confirm({
+        title: t('actions.deleteConfirmTitle'),
+        content: t('actions.deleteConfirmContent'),
+        onOk: () => {
+          // 处理删除逻辑
+        },
+      });
+    },
     danger: true
   },
 ];

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

Comment on lines +47 to +54
const Demo: React.FC = () => {
const onClick: ActionsProps['onClick'] = ({ key, keyPath, item }) => {
message.success(`you click ${keyPath}`);
};
return <Actions items={actionItems} onClick={onClick} />;
};

export default Demo;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

建议增强组件的健壮性和类型安全性

  1. 建议为不同的操作添加不同的处理逻辑
  2. 建议添加错误处理
  3. 建议使用更具体的类型定义
-const Demo: React.FC = () => {
+interface ActionHandler {
+  key: string;
+  handler: () => Promise<void>;
+}
+
+const Demo: React.FC = () => {
+  const handleAction = async ({ key, keyPath, item }: ActionsProps['onClick']) => {
+    try {
+      switch (key) {
+        case 'retry':
+          await handleRetry();
+          message.success(t('actions.retrySuccess'));
+          break;
+        case 'delete':
+          await handleDelete();
+          message.success(t('actions.deleteSuccess'));
+          break;
+        default:
+          message.success(`${keyPath} ${t('actions.actionSuccess')}`);
+      }
+    } catch (error) {
+      message.error(t('actions.actionError'));
+      console.error(error);
+    }
+  };
+
-  const onClick: ActionsProps['onClick'] = ({ key, keyPath, item }) => {
-    message.success(`you click ${keyPath}`);
-  };
-  return <Actions items={actionItems} onClick={onClick} />;
+  return <Actions items={actionItems} onClick={handleAction} />;
 };

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

Comment on lines +13 to +71
return {
[componentCls]: {
[`${componentCls}-list`]: {
display: 'inline-flex',
flexDirection: 'row',
gap: token.paddingXS,
color: '#8c8c8c',

'&-item, &-sub-item': {
cursor: 'pointer',
padding: token.paddingXXS,
borderRadius: token.borderRadius,
height: token.controlHeightSM,
width: token.controlHeightSM,
boxSizing: 'border-box',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',

'&-icon': {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: token.fontSize,
width: '100%',
height: '100%',
},

'&:hover': {
background: '#F6F6F6',
},
},
},
'& .border': {
padding: `${token.paddingXS} ${token.paddingSM}`,
gap: token.paddingSM,
borderRadius: calc(token.borderRadiusLG).mul(1.5).equal(),
backgroundColor: '#F7F7F7',
color: token.colorTextSecondary,

[`${componentCls}-list-item, ${componentCls}-list-sub-item`]: {
padding: 0,
lineHeight: token.lineHeight,

'&-icon': {
fontSize: token.fontSizeLG,
},

'&:hover': {
opacity: 0.8,
},
},
},
'& .block': {
display: 'flex',
},
},
};
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

建议使用主题令牌系统替代硬编码的颜色值

当前实现中存在以下需要优化的地方:

  1. 硬编码的颜色值应该使用主题令牌:

    • #8c8c8c 建议使用 token.colorTextSecondary
    • #F6F6F6 建议使用 token.colorBgTextHover
    • #F7F7F7 建议使用 token.colorFillTertiary
  2. 建议将重复的样式属性抽取为公共变量,提高可维护性。

建议按照以下方式修改:

 [componentCls]: {
   [`${componentCls}-list`]: {
     display: 'inline-flex',
     flexDirection: 'row',
     gap: token.paddingXS,
-    color: '#8c8c8c',
+    color: token.colorTextSecondary,

     '&-item, &-sub-item': {
       // ... other properties ...
       '&:hover': {
-        background: '#F6F6F6',
+        background: token.colorBgTextHover,
       },
     },
   },
   '& .border': {
     // ... other properties ...
-    backgroundColor: '#F7F7F7',
+    backgroundColor: token.colorFillTertiary,
   }
 }
📝 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 {
[componentCls]: {
[`${componentCls}-list`]: {
display: 'inline-flex',
flexDirection: 'row',
gap: token.paddingXS,
color: '#8c8c8c',
'&-item, &-sub-item': {
cursor: 'pointer',
padding: token.paddingXXS,
borderRadius: token.borderRadius,
height: token.controlHeightSM,
width: token.controlHeightSM,
boxSizing: 'border-box',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
'&-icon': {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: token.fontSize,
width: '100%',
height: '100%',
},
'&:hover': {
background: '#F6F6F6',
},
},
},
'& .border': {
padding: `${token.paddingXS} ${token.paddingSM}`,
gap: token.paddingSM,
borderRadius: calc(token.borderRadiusLG).mul(1.5).equal(),
backgroundColor: '#F7F7F7',
color: token.colorTextSecondary,
[`${componentCls}-list-item, ${componentCls}-list-sub-item`]: {
padding: 0,
lineHeight: token.lineHeight,
'&-icon': {
fontSize: token.fontSizeLG,
},
'&:hover': {
opacity: 0.8,
},
},
},
'& .block': {
display: 'flex',
},
},
};
};
return {
[componentCls]: {
[`${componentCls}-list`]: {
display: 'inline-flex',
flexDirection: 'row',
gap: token.paddingXS,
color: token.colorTextSecondary,
'&-item, &-sub-item': {
cursor: 'pointer',
padding: token.paddingXXS,
borderRadius: token.borderRadius,
height: token.controlHeightSM,
width: token.controlHeightSM,
boxSizing: 'border-box',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
'&-icon': {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: token.fontSize,
width: '100%',
height: '100%',
},
'&:hover': {
background: token.colorBgTextHover,
},
},
},
'& .border': {
padding: `${token.paddingXS} ${token.paddingSM}`,
gap: token.paddingSM,
borderRadius: calc(token.borderRadiusLG).mul(1.5).equal(),
backgroundColor: token.colorFillTertiary,
color: token.colorTextSecondary,
[`${componentCls}-list-item, ${componentCls}-list-sub-item`]: {
padding: 0,
lineHeight: token.lineHeight,
'&-icon': {
fontSize: token.fontSizeLG,
},
'&:hover': {
opacity: 0.8,
},
},
},
'& .block': {
display: 'flex',
},
},
};
};

Comment on lines +72 to +99
export interface SubItemType {
/**
* @desc 自定义操作的唯一标识
* @descEN Unique identifier for the custom action.
*/
key: string;
/**
* @desc 自定义操作的显示标签
* @descEN Display label for the custom action.
*/
label?: string;
/**
* @desc 自定义操作的图标
* @descEN Icon for the custom action.
*/
icon?: ReactNode;
/**
* @desc 子操作项
* @descEN Child action items.
*/
children?: ActionItemType[];
triggerSubMenuAction?: MenuProps['triggerSubMenuAction'];
/**
* @desc 点击自定义操作按钮时的回调函数
* @descEN Callback function when the custom action button is clicked.
*/
onClick?: () => void;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

需要解决类型继承和一致性问题

SubItemTypeItemType 有大量重复的属性定义,这可能导致维护困难和不一致性。建议通过类型继承来优化结构。

建议应用以下改进:

-export interface SubItemType {
-  key: string;
-  label?: string;
-  icon?: ReactNode;
-  children?: ActionItemType[];
-  triggerSubMenuAction?: MenuProps['triggerSubMenuAction'];
-  onClick?: () => void;
+export interface SubItemType extends Omit<ItemType, 'danger'> {
+  children?: ActionItemType[];
+  triggerSubMenuAction?: MenuProps['triggerSubMenuAction'];
 }

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

Comment on lines +104 to +108
if (process.env.NODE_ENV === 'production') {
Actions.displayName = 'Actions';
}

export default Actions;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

修复 displayName 的环境判断逻辑

当前实现中 displayName 的设置逻辑似乎反了。通常我们希望在开发环境中设置 displayName 以便调试,而不是在生产环境。

建议修改为:

- if (process.env.NODE_ENV === 'production') {
+ if (process.env.NODE_ENV !== 'production') {
    Actions.displayName = 'Actions';
  }
📝 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
if (process.env.NODE_ENV === 'production') {
Actions.displayName = 'Actions';
}
export default Actions;
if (process.env.NODE_ENV !== 'production') {
Actions.displayName = 'Actions';
}
export default Actions;

Comment on lines +57 to +72
const handleItemClick = (
key: string,
item: ActionItemType,
domEvent: React.MouseEvent<HTMLElement, MouseEvent>,
) => {
if (item.onClick) {
item.onClick();
return;
}
onClick?.({
key,
item,
keyPath: [key],
domEvent,
});
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

优化事件处理函数的实现

handleItemClick 函数的实现可以更加优雅:

  1. 事件类型可以更具体
  2. 可以使用早期返回模式简化逻辑

建议按照以下方式重构:

  const handleItemClick = (
    key: string,
    item: ActionItemType,
-   domEvent: React.MouseEvent<HTMLElement, MouseEvent>,
+   domEvent: React.MouseEvent<HTMLDivElement>,
  ) => {
-   if (item.onClick) {
-     item.onClick();
-     return;
-   }
-   onClick?.({
+   item.onClick?.();
+   onClick?.({
      key,
      item,
      keyPath: [key],
      domEvent,
    });
  };

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

Comment on lines +74 to +101
const renderSingleItem = (item: ItemType) => {
const { icon, label, key } = item;

return (
<div
className={classnames(`${prefixCls}-list-item`)}
onClick={(domEvent) => handleItemClick(key, item, domEvent)}
key={key}
>
{getTooltipNode(<div className={`${prefixCls}-list-item-icon`}>{icon}</div>, label)}
</div>
);
};

return wrapCSSVar(
<div className={mergedCls} style={mergedStyle}>
<div className={classnames(`${prefixCls}-list`, variant, block)}>
{items.map((item) => {
if ('children' in item) {
return (
<ActionMenu key={item.key} item={item} prefixCls={prefixCls} onClick={onClick} />
);
}
return renderSingleItem(item);
})}
</div>
</div>,
);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

提升组件的可访问性和代码组织

渲染逻辑需要以下改进:

  1. 缺少必要的 ARIA 属性
  2. 可以提取一些 JSX 常量
  3. 建议添加键盘交互支持

建议进行以下改进:

  <div
    className={classnames(`${prefixCls}-list-item`)}
    onClick={(domEvent) => handleItemClick(key, item, domEvent)}
    key={key}
+   role="button"
+   tabIndex={0}
+   aria-label={label}
+   onKeyDown={(e) => {
+     if (e.key === 'Enter' || e.key === ' ') {
+       e.preventDefault();
+       handleItemClick(key, item, e as unknown as React.MouseEvent<HTMLDivElement>);
+     }
+   }}
  >
📝 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
const renderSingleItem = (item: ItemType) => {
const { icon, label, key } = item;
return (
<div
className={classnames(`${prefixCls}-list-item`)}
onClick={(domEvent) => handleItemClick(key, item, domEvent)}
key={key}
>
{getTooltipNode(<div className={`${prefixCls}-list-item-icon`}>{icon}</div>, label)}
</div>
);
};
return wrapCSSVar(
<div className={mergedCls} style={mergedStyle}>
<div className={classnames(`${prefixCls}-list`, variant, block)}>
{items.map((item) => {
if ('children' in item) {
return (
<ActionMenu key={item.key} item={item} prefixCls={prefixCls} onClick={onClick} />
);
}
return renderSingleItem(item);
})}
</div>
</div>,
);
const renderSingleItem = (item: ItemType) => {
const { icon, label, key } = item;
return (
<div
className={classnames(`${prefixCls}-list-item`)}
onClick={(domEvent) => handleItemClick(key, item, domEvent)}
key={key}
role="button"
tabIndex={0}
aria-label={label}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleItemClick(key, item, e as unknown as React.MouseEvent<HTMLDivElement>);
}
}}
>
{getTooltipNode(<div className={`${prefixCls}-list-item-icon`}>{icon}</div>, label)}
</div>
);
};
return wrapCSSVar(
<div className={mergedCls} style={mergedStyle}>
<div className={classnames(`${prefixCls}-list`, variant, block)}>
{items.map((item) => {
if ('children' in item) {
return (
<ActionMenu key={item.key} item={item} prefixCls={prefixCls} onClick={onClick} />
);
}
return renderSingleItem(item);
})}
</div>
</div>,
);

display: 'inline-flex',
flexDirection: 'row',
gap: token.paddingXS,
color: '#8c8c8c',
Copy link
Collaborator

Choose a reason for hiding this comment

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

同类建议:最好不写固定颜色,比如在暗色主题下会存在显示问题

这个颜色看起来比较像 token.colorTextDescription ?

- color: '#8c8c8c',
+ color: token.colorTextDescription,

},

'&:hover': {
background: '#F6F6F6',
Copy link
Collaborator

Choose a reason for hiding this comment

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

同类建议:最好不写固定颜色,比如在暗色主题下会存在显示问题

这个颜色看起来比较像 token.colorBgTextHover ?

- color: '#F6F6F6',
+ color: token.colorBgTextHover,

padding: `${token.paddingXS} ${token.paddingSM}`,
gap: token.paddingSM,
borderRadius: calc(token.borderRadiusLG).mul(1.5).equal(),
backgroundColor: '#F7F7F7',
Copy link
Collaborator

Choose a reason for hiding this comment

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

同类建议:最好不写固定颜色,比如在暗色主题下会存在显示问题

可以试试这几个:
image

};
};

export const prepareComponentToken: GetDefaultToken<'Prompts'> = () => ({});
Copy link
Collaborator

Choose a reason for hiding this comment

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

Prompts -> Actions


const mergedStyle = {
...style,
...contextConfig.style,
Copy link
Collaborator

Choose a reason for hiding this comment

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

这里顺序需要调整下,组件传入的 style 覆盖 contextConfig.style

import useXComponentConfig from '../_util/hooks/use-x-component-config';
import { useXProviderContext } from '../x-provider';
import ActionMenu from './ActionMenu';
import { ActionItemType, ActionsProps, ItemType } from './interface';
Copy link
Collaborator

Choose a reason for hiding this comment

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

import type { ActionItemType, ActionsProps, ItemType } from './interface';

import { ActionItemType, ActionsProps, ItemType } from './interface';
import useStyle from './style';

export { ActionsProps } from './interface';
Copy link
Collaborator

Choose a reason for hiding this comment

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

可以将两个同文件的引用合并下


export { ActionsProps } from './interface';

const Actions = (props: ActionsProps) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

const Actions: React.FC<ActionsProps> = (props) => {...}

import type { MenuItemProps, MenuProps } from 'antd';
import type { ReactNode } from 'react';

export interface ActionsProps {
Copy link
Collaborator

Choose a reason for hiding this comment

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

这里需要对 html 标签的属性进行继承,HTMLDivElement 取决于该组件的最外层容器的标签。

interface ActionsProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onClick'> {...}

block = false,
onClick,
items = [],
} = props;
Copy link
Collaborator

Choose a reason for hiding this comment

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

需要对 html 标签属性进行支持,可以参考下:/components/conversations/index.tsx [line: 98~105]

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