Skip to content

[ISSUE #1952] Actions support custom tooltip - #1973

Open
jay666mnj wants to merge 11 commits into
ant-design:mainfrom
jay666mnj:fix-actions-custom-tooltip
Open

[ISSUE #1952] Actions support custom tooltip#1973
jay666mnj wants to merge 11 commits into
ant-design:mainfrom
jay666mnj:fix-actions-custom-tooltip

Conversation

@jay666mnj

@jay666mnj jay666mnj commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

🤔 This is a ...

  • 🆕 New feature
  • 🐞 Bug fix
  • 📝 Site / documentation improvement
  • 📽️ Demo improvement
  • 💄 Component style improvement
  • 🤖 TypeScript definition improvement
  • 📦 Bundle size optimization
  • ⚡️ Performance optimization
  • ⭐️ Feature enhancement
  • 🌐 Internationalization
  • 🛠 Refactoring
  • 🎨 Code style optimization
  • ✅ Test Case
  • 🔀 Branch merge
  • ⏩ Workflow
  • ⌨️ Accessibility improvement
  • ❓ Other (about what?)

🔗 Related Issues

Close #1952

💡 Background and Solution

Actions currently uses label as the tooltip content by default, but each action item cannot customize or disable its own tooltip.

This PR adds a tooltip?: string | TooltipProps | false option for Actions items and Actions.Item.

  • string: use custom tooltip title
  • TooltipProps: pass custom Tooltip props
  • false: disable tooltip
  • undefined: keep existing behavior and use label

📝 Change Log

Language Changelog
🇺🇸 English Actions supports customizing or disabling tooltip for each action item.
🇨🇳 Chinese Actions 支持为每个操作项自定义或禁用 Tooltip。

Summary by CodeRabbit

  • 新功能
    • 动作项新增 tooltip:支持 string、完整 Tooltip 参数(含 placement),或通过 tooltip: false 禁用提示;未配置时默认使用 label
    • Tooltip 渲染逻辑统一处理,并在移动端不展示带提示的 Tooltip。
  • 文档
    • 更新中英文 API 文档:补充 ItemType/Actions.Itemtooltip 类型、默认值与禁用说明。
  • 测试
    • 扩展 Tooltip 行为用例:字符串/对象/禁用/未传/空值,并覆盖边界如 title: 0 等。
  • 示例
    • 示例动作配置补充 tooltip(含禁用)用于展示效果。

@dosubot dosubot Bot added documentation Improvements or additions to documentation enhancement New feature or request labels Jul 13, 2026
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Actions 新增 tooltip 配置,支持字符串、TooltipPropsfalse。渲染逻辑统一处理自定义标题、属性透传、禁用和空标题场景,并补充测试、示例及中英文文档。

Changes

Actions Tooltip 自定义

Layer / File(s) Summary
Tooltip 类型与统一渲染
packages/x/components/actions/interface.ts, packages/x/components/actions/tooltip.tsx, packages/x/components/actions/ActionsItem.tsx, packages/x/components/actions/Item.tsx
Actions 项支持 stringTooltipPropsfalse;统一渲染函数根据配置、label 和移动端状态决定是否渲染 Tooltip。
Tooltip 行为验证
packages/x/components/actions/__tests__/*
新增 Tooltip mock,并覆盖字符串、对象配置、false、空值、title=0、移动端及基础渲染场景。
示例与 API 文档
packages/x/components/actions/demo/basic.tsx, packages/x/components/actions/index.en-US.md, packages/x/components/actions/index.zh-CN.md
示例加入编辑 Tooltip 和禁用复制 Tooltip,文档补充属性类型、默认值及禁用说明。

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ActionConfig
  participant ActionsItem
  participant Item
  participant renderWithTooltip
  participant Tooltip
  ActionConfig->>ActionsItem: 提供 tooltip 配置
  ActionsItem->>renderWithTooltip: 传入节点、tooltip、label 和移动端状态
  Item->>renderWithTooltip: 传入图标、item.tooltip、label 和移动端状态
  renderWithTooltip->>Tooltip: 使用标题或 TooltipProps 包装节点
  Tooltip-->>ActionsItem: 返回带 Tooltip 的操作项节点
Loading

Possibly related PRs

  • ant-design/x#1945:同样调整 ActionsItem.tsxItem.tsx 的 Tooltip 渲染行为。
  • ant-design/x#1977:实现相同的 Actions Tooltip 配置、渲染和测试更新。

Suggested labels: javascript

Poem

小兔竖起耳朵尖,
Tooltip 配置更周全。
字符串来标题现,
false 一到提示眠。
Actions 蹦跳向前!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题简洁且准确概括了本次为 Actions 增加自定义 Tooltip 的核心改动。
Linked Issues check ✅ Passed 实现了每个 Actions 项的 tooltip 自定义/禁用,并补充了 demo、单测与中英文档。
Out of Scope Changes check ✅ Passed 新增的工具函数、示例、测试和文档都围绕 Tooltip 自定义能力展开,未见明显无关改动。
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for a custom tooltip prop in the ActionsItem and Item components, allowing users to customize tooltips with a string, a TooltipProps object, or disable them entirely by passing false. It also includes corresponding updates to documentation, TypeScript interfaces, demos, and unit tests. The review feedback highlights a potential runtime issue where typeof tooltip === 'object' evaluates to true when tooltip is null, which could lead to spreading null into the Tooltip component. Additionally, the reviewer suggests avoiding wrapping elements in an empty Tooltip when both tooltip and label are undefined to prevent unnecessary DOM overhead.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +147 to +153
const tooltipProps = typeof tooltip === 'object' ? tooltip : { title: tooltip ?? label };

return isMobile ? innerNode : <Tooltip title={label}>{innerNode}</Tooltip>;
return isMobile || tooltip === false ? (
innerNode
) : (
<Tooltip {...tooltipProps}>{innerNode}</Tooltip>
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

In JavaScript, typeof null is 'object'. If tooltip is passed as null, typeof tooltip === 'object' evaluates to true, and tooltipProps becomes null. Spreading null in <Tooltip {...tooltipProps}> can cause runtime errors or TypeScript issues.

Additionally, if both tooltip and label are undefined, wrapping the element in a <Tooltip> with an undefined title is unnecessary and adds extra virtual DOM overhead. We can refine this by checking if tooltip is a non-null object and ensuring we only render the Tooltip when there is a valid tooltip title or configuration.

  const tooltipProps = typeof tooltip === 'object' && tooltip !== null ? tooltip : { title: tooltip ?? label };
  const hasTooltip =
    !isMobile &&
    tooltip !== false &&
    (typeof tooltip === 'object' && tooltip !== null ? true : !!(tooltip ?? label));

  return hasTooltip ? (
    <Tooltip {...tooltipProps}>{innerNode}</Tooltip>
  ) : (
    innerNode
  );

Comment thread packages/x/components/actions/Item.tsx Outdated
Comment on lines +32 to +39
const tooltipProps =
typeof item.tooltip === 'object' ? item.tooltip : { title: item.tooltip ?? item.label };
const mergedIconElement =
isMobile || item.tooltip === false ? (
iconElement
) : (
<Tooltip {...tooltipProps}>{iconElement}</Tooltip>
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Similar to ActionsItem.tsx, typeof item.tooltip === 'object' will evaluate to true if item.tooltip is null. Spreading null into <Tooltip> can cause issues. Also, if both item.tooltip and item.label are undefined, we should avoid wrapping the icon in an empty Tooltip to prevent unnecessary DOM and event listener overhead.

We can optimize this by checking for a non-null object and ensuring a tooltip is only rendered when there is a valid title or configuration.

  const tooltipProps =
    typeof item.tooltip === 'object' && item.tooltip !== null
      ? item.tooltip
      : { title: item.tooltip ?? item.label };
  const hasTooltip =
    !isMobile &&
    item.tooltip !== false &&
    (typeof item.tooltip === 'object' && item.tooltip !== null ? true : !!(item.tooltip ?? item.label));
  const mergedIconElement = hasTooltip ? (
    <Tooltip {...tooltipProps}>{iconElement}</Tooltip>
  ) : (
    iconElement
  );

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/x/components/actions/__tests__/action-item.test.tsx (1)

5-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

补充 TooltipProps 对象类型的测试用例。

当前测试覆盖了 stringfalse 两种情况,但缺少 tooltipTooltipProps 对象(如 { title: 'Edit', placement: 'bottom' })的用例。Demo 中已展示此用法,建议补充测试确保对象透传行为正确。

💚 建议补充的测试用例
+  it('supports tooltip with TooltipProps object', () => {
+    const { getByText } = render(
+      <ActionsItem
+        defaultIcon="default-icon"
+        label="Default Tooltip"
+        tooltip={{ title: 'Object Tooltip', placement: 'bottom' }}
+      />,
+    );
+
+    expect(
+      getByText('default-icon').closest('[data-tooltip-title="Object Tooltip"]'),
+    ).toBeInTheDocument();
+  });

Also applies to: 15-20, 22-30, 32-37

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/x/components/actions/__tests__/action-item.test.tsx` around lines 5
- 13, 在 action-item 测试中补充 tooltip 传入 TooltipProps 对象的用例,例如包含 title 和 placement
的配置,验证对象形式能正确透传并渲染标题,同时保留现有 string 与 false 场景覆盖。
packages/x/components/actions/ActionsItem.tsx (1)

147-153: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Tooltip 渲染逻辑在两个组件中重复。

ActionsItem.tsxItem.tsxtooltipProps 的计算和条件渲染逻辑完全一致,共享同一根因。建议提取为共享辅助函数,避免后续维护时两处逻辑产生分歧。

  • packages/x/components/actions/ActionsItem.tsx#L147-L153: 将 tooltipProps 计算和条件渲染提取为共享函数。
  • packages/x/components/actions/Item.tsx#L32-L39: 同样使用提取的共享函数替换内联逻辑。
♻️ 建议提取共享辅助函数
+// packages/x/components/actions/utils.ts
+import type { TooltipProps } from 'antd';
+
+export function getTooltipProps(
+  tooltip: string | TooltipProps | false | undefined,
+  label?: string,
+): TooltipProps {
+  return typeof tooltip === 'object' ? tooltip : { title: tooltip ?? label };
+}
+
+export function shouldRenderTooltip(
+  isMobile: boolean,
+  tooltip: string | TooltipProps | false | undefined,
+): boolean {
+  return !isMobile && tooltip !== false;
+}

ActionsItem.tsx 复用:

- const tooltipProps = typeof tooltip === 'object' ? tooltip : { title: tooltip ?? label };
-
- return isMobile || tooltip === false ? (
-   innerNode
- ) : (
-   <Tooltip {...tooltipProps}>{innerNode}</Tooltip>
- );
+ const tooltipProps = getTooltipProps(tooltip, label);
+ return shouldRenderTooltip(isMobile, tooltip) ? (
+   <Tooltip {...tooltipProps}>{innerNode}</Tooltip>
+ ) : (
+   innerNode
+ );

Item.tsx 复用:

- const tooltipProps =
-   typeof item.tooltip === 'object' ? item.tooltip : { title: item.tooltip ?? item.label };
- const mergedIconElement =
-   isMobile || item.tooltip === false ? (
-     iconElement
-   ) : (
-     <Tooltip {...tooltipProps}>{iconElement}</Tooltip>
-   );
+ const tooltipProps = getTooltipProps(item.tooltip, item.label);
+ const mergedIconElement = shouldRenderTooltip(isMobile, item.tooltip) ? (
+   <Tooltip {...tooltipProps}>{iconElement}</Tooltip>
+ ) : (
+   iconElement
+ );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/x/components/actions/ActionsItem.tsx` around lines 147 - 153,
提取共享辅助函数,统一封装 ActionsItem.tsx 中 tooltipProps 的计算及 isMobile 或 tooltip === false
时直接返回 innerNode、否则渲染 Tooltip 的逻辑;在
packages/x/components/actions/ActionsItem.tsx:147-153 和
packages/x/components/actions/Item.tsx:32-39 两处改为调用该辅助函数,保持现有行为一致。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/x/components/actions/__tests__/action-item.test.tsx`:
- Around line 5-13: 在 action-item 测试中补充 tooltip 传入 TooltipProps 对象的用例,例如包含 title
和 placement 的配置,验证对象形式能正确透传并渲染标题,同时保留现有 string 与 false 场景覆盖。

In `@packages/x/components/actions/ActionsItem.tsx`:
- Around line 147-153: 提取共享辅助函数,统一封装 ActionsItem.tsx 中 tooltipProps 的计算及
isMobile 或 tooltip === false 时直接返回 innerNode、否则渲染 Tooltip 的逻辑;在
packages/x/components/actions/ActionsItem.tsx:147-153 和
packages/x/components/actions/Item.tsx:32-39 两处改为调用该辅助函数,保持现有行为一致。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2af2238c-0606-4c08-a50b-6b3b6c256b86

📥 Commits

Reviewing files that changed from the base of the PR and between 04a3b32 and 06ee396.

📒 Files selected for processing (8)
  • packages/x/components/actions/ActionsItem.tsx
  • packages/x/components/actions/Item.tsx
  • packages/x/components/actions/__tests__/action-item.test.tsx
  • packages/x/components/actions/__tests__/index.test.tsx
  • packages/x/components/actions/demo/basic.tsx
  • packages/x/components/actions/index.en-US.md
  • packages/x/components/actions/index.zh-CN.md
  • packages/x/components/actions/interface.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/x/components/actions/tooltip.tsx (1)

11-16: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议重命名参数以提升语义明确性

该参数名为 disabled,极易与组件或操作项自身的 disabled(不可交互)状态混淆。而实际上,上游调用方(如 Item.tsxActionsItem.tsx)传入的均是 isMobile 变量以在移动端屏蔽 Tooltip。建议将其重命名为 isMobiledisableTooltip

💡 建议修改为 disableTooltip
 export function renderWithTooltip(
   node: React.ReactElement,
   tooltip: ActionTooltip,
   label?: string,
-  disabled?: boolean,
+  disableTooltip?: boolean,
 ) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/x/components/actions/tooltip.tsx` around lines 11 - 16, Rename the
disabled parameter in renderWithTooltip to disableTooltip (or an equivalent
tooltip-specific name), and update its internal references plus all callers such
as Item.tsx and ActionsItem.tsx to use the new name while preserving the mobile
Tooltip-suppression behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/x/components/actions/tooltip.tsx`:
- Around line 23-25: Update the guard in the tooltip rendering logic to treat
only absent or nullish tooltipProps.title values as missing, while preserving
rendering for valid falsy ReactNodes such as 0. Keep returning node for
genuinely missing titles and retain the existing Tooltip path for all provided
titles.

---

Nitpick comments:
In `@packages/x/components/actions/tooltip.tsx`:
- Around line 11-16: Rename the disabled parameter in renderWithTooltip to
disableTooltip (or an equivalent tooltip-specific name), and update its internal
references plus all callers such as Item.tsx and ActionsItem.tsx to use the new
name while preserving the mobile Tooltip-suppression behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 260401f0-9628-4cbb-9937-faa304909882

📥 Commits

Reviewing files that changed from the base of the PR and between 06ee396 and 693d92a.

📒 Files selected for processing (5)
  • packages/x/components/actions/ActionsItem.tsx
  • packages/x/components/actions/Item.tsx
  • packages/x/components/actions/__tests__/action-item.test.tsx
  • packages/x/components/actions/__tests__/index.test.tsx
  • packages/x/components/actions/tooltip.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/x/components/actions/tests/index.test.tsx
  • packages/x/components/actions/Item.tsx
  • packages/x/components/actions/ActionsItem.tsx

Comment thread packages/x/components/actions/tooltip.tsx Outdated
@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 8 bytes (0.0%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
antdx-array-push 2.11MB 8 bytes (0.0%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: antdx-array-push

Assets Changed:

Asset Name Size Change Total Size Change (%)
antdx.min.js 8 bytes 2.11MB 0.0%

@kimteayon kimteayon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

合法的 TooltipProps.overlay 会被静默忽略
tooltip.tsx:23 仅检查 title。但当前 antd 的 TooltipProps 仍支持 overlay,例如 tooltip={{ overlay: '说明' }} 类型合法且原生 Tooltip 可以展示,此处却直接返回未包装节点。建议同时检查 overlay,或让 antd 自行处理空内容,并补充对应测试。

@jay666mnj
jay666mnj requested a review from kimteayon July 23, 2026 10:39
@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.07%. Comparing base (13afbf4) to head (deba1f2).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1973   +/-   ##
=======================================
  Coverage   97.06%   97.07%           
=======================================
  Files         159      160    +1     
  Lines        5766     5775    +9     
  Branches     1712     1707    -5     
=======================================
+ Hits         5597     5606    +9     
  Misses        167      167           
  Partials        2        2           

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

@jay666mnj

Copy link
Copy Markdown
Contributor Author

@kimteayon over thank you~

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

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Good First Issue] Actions 支持自定义每个操作项的 Tooltip

2 participants