mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-09 02:49:18 +08:00
feat[Segmented]: add tooltip to segmented option item (#54273)
* feat: add tooltip to segmented option item * feat[segmented]: add demo, and tooltip can be configured as an object * docs: change tooltip type * test: update snap * feat: change itemRender of SegmentedProps * feat: tooltipProps remove children * feat: delete ?. * feat: add if to tooltipProps * feat: not inline return * docs: custom * Update components/segmented/__tests__/index.test.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: thinkasany <480968828@qq.com> * Update components/segmented/demo/custom.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: thinkasany <480968828@qq.com> * Update components/segmented/demo/custom.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: thinkasany <480968828@qq.com> * docs: link tooltip api * docs: lint tooltip us * test: update snap --------- Signed-off-by: thinkasany <480968828@qq.com> Co-authored-by: 刘欢 <lh01217311@antgroup.com> Co-authored-by: thinkasany <480968828@qq.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`renders components/segmented/demo/basic.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
@@ -488,6 +488,7 @@ exports[`renders components/segmented/demo/custom.tsx extend context correctly 1
|
||||
class="ant-segmented-group"
|
||||
>
|
||||
<label
|
||||
aria-describedby="test-id"
|
||||
class="ant-segmented-item ant-segmented-item-selected"
|
||||
>
|
||||
<input
|
||||
@@ -517,7 +518,28 @@ exports[`renders components/segmented/demo/custom.tsx extend context correctly 1
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-gold css-var-test-id ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
id="test-id"
|
||||
role="tooltip"
|
||||
>
|
||||
hello user1
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label
|
||||
aria-describedby="test-id"
|
||||
class="ant-segmented-item"
|
||||
>
|
||||
<input
|
||||
@@ -550,7 +572,28 @@ exports[`renders components/segmented/demo/custom.tsx extend context correctly 1
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-pink css-var-test-id ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
id="test-id"
|
||||
role="tooltip"
|
||||
>
|
||||
hello user2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label
|
||||
aria-describedby="test-id"
|
||||
class="ant-segmented-item"
|
||||
>
|
||||
<input
|
||||
@@ -596,6 +639,26 @@ exports[`renders components/segmented/demo/custom.tsx extend context correctly 1
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-geekblue css-var-test-id ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
id="test-id"
|
||||
role="tooltip"
|
||||
>
|
||||
hello user3
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`renders components/segmented/demo/basic.tsx correctly 1`] = `
|
||||
<div
|
||||
@@ -478,6 +478,7 @@ exports[`renders components/segmented/demo/custom.tsx correctly 1`] = `
|
||||
class="ant-segmented-group"
|
||||
>
|
||||
<label
|
||||
aria-describedby="test-id"
|
||||
class="ant-segmented-item ant-segmented-item-selected"
|
||||
>
|
||||
<input
|
||||
@@ -508,6 +509,7 @@ exports[`renders components/segmented/demo/custom.tsx correctly 1`] = `
|
||||
</div>
|
||||
</label>
|
||||
<label
|
||||
aria-describedby="test-id"
|
||||
class="ant-segmented-item"
|
||||
>
|
||||
<input
|
||||
@@ -541,6 +543,7 @@ exports[`renders components/segmented/demo/custom.tsx correctly 1`] = `
|
||||
</div>
|
||||
</label>
|
||||
<label
|
||||
aria-describedby="test-id"
|
||||
class="ant-segmented-item"
|
||||
>
|
||||
<input
|
||||
|
||||
@@ -3,7 +3,7 @@ import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
|
||||
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import { fireEvent, render, waitFor } from '../../../tests/utils';
|
||||
import type { SegmentedValue } from '../index';
|
||||
import Segmented from '../index';
|
||||
|
||||
@@ -414,4 +414,31 @@ describe('Segmented', () => {
|
||||
expect(container.querySelector<HTMLDivElement>('.ant-segmented-vertical')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('toolTip for optionItem ', () => {
|
||||
it('Configuring tooltip in the options should display the corresponding information', async () => {
|
||||
const { container } = render(
|
||||
<Segmented
|
||||
orientation="vertical"
|
||||
options={[
|
||||
{ label: 'Daily', value: 'Daily', tooltip: 'hello Daily' },
|
||||
'Weekly',
|
||||
{ label: 'Monthly', value: 'Monthly', tooltip: 'hello Monthly' },
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
const itemList = container.querySelectorAll('.ant-segmented-item');
|
||||
fireEvent.mouseEnter(itemList[0]);
|
||||
fireEvent.mouseEnter(itemList[1]);
|
||||
fireEvent.mouseEnter(itemList[2]);
|
||||
await waitFor(() => {
|
||||
const tooltipList = document.querySelectorAll('.ant-tooltip');
|
||||
expect(tooltipList).toHaveLength(2);
|
||||
const tooltipInnerList = document.querySelectorAll('.ant-tooltip-inner');
|
||||
expect(tooltipInnerList).toHaveLength(2);
|
||||
expect(tooltipInnerList[0]?.textContent).toBe('hello Daily');
|
||||
expect(tooltipInnerList[1]?.textContent).toBe('hello Monthly');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
使用 ReactNode 自定义渲染每一个 Segmented Item。
|
||||
自定义渲染每一个 Segmented Item。
|
||||
|
||||
## en-US
|
||||
|
||||
Custom each Segmented Item by ReactNode.
|
||||
Custom each Segmented Item.
|
||||
|
||||
@@ -14,6 +14,7 @@ const App: React.FC = () => (
|
||||
</div>
|
||||
),
|
||||
value: 'user1',
|
||||
tooltip: { title: 'hello user1', color: 'gold' },
|
||||
},
|
||||
{
|
||||
label: (
|
||||
@@ -23,6 +24,7 @@ const App: React.FC = () => (
|
||||
</div>
|
||||
),
|
||||
value: 'user2',
|
||||
tooltip: { title: 'hello user2', color: 'pink' },
|
||||
},
|
||||
{
|
||||
label: (
|
||||
@@ -32,6 +34,7 @@ const App: React.FC = () => (
|
||||
</div>
|
||||
),
|
||||
value: 'user3',
|
||||
tooltip: { title: 'hello user3', color: 'geekblue' },
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -57,13 +57,14 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
|
||||
### SegmentedItemType
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --------- | -------------------------------- | ---------------- | ------- | ------- |
|
||||
| label | Display text for Segmented item | ReactNode | - | |
|
||||
| value | Value for Segmented item | string \| number | - | |
|
||||
| icon | Display icon for Segmented item | ReactNode | - | |
|
||||
| disabled | Disabled state of segmented item | boolean | false | |
|
||||
| className | The additional css class | string | - | |
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| disabled | Disabled state of segmented item | boolean | false | |
|
||||
| className | The additional css class | string | - | |
|
||||
| icon | Display icon for Segmented item | ReactNode | - | |
|
||||
| label | Display text for Segmented item | ReactNode | - | |
|
||||
| tooltip | tooltip for Segmented item | string \| [TooltipProps](../tooltip/index.en-US.md#api) | - | |
|
||||
| value | Value for Segmented item | string \| number | - | |
|
||||
|
||||
## Semantic DOM
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import type {
|
||||
} from '@rc-component/segmented';
|
||||
import RcSegmented from '@rc-component/segmented';
|
||||
import useId from '@rc-component/util/lib/hooks/useId';
|
||||
import { Tooltip, TooltipProps } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import useOrientation from '../_util/hooks/useOrientation';
|
||||
@@ -18,9 +19,11 @@ import useStyle from './style';
|
||||
|
||||
export type { SegmentedValue } from '@rc-component/segmented';
|
||||
export type SemanticName = 'root' | 'icon' | 'label' | 'item';
|
||||
|
||||
interface SegmentedLabeledOptionWithoutIcon<ValueType = RcSegmentedValue>
|
||||
extends RcSegmentedLabeledOption<ValueType> {
|
||||
label: RcSegmentedLabeledOption['label'];
|
||||
tooltip?: string | Omit<TooltipProps, 'children'>;
|
||||
}
|
||||
|
||||
interface SegmentedLabeledOptionWithIcon<ValueType = RcSegmentedValue>
|
||||
@@ -28,6 +31,7 @@ interface SegmentedLabeledOptionWithIcon<ValueType = RcSegmentedValue>
|
||||
label?: RcSegmentedLabeledOption['label'];
|
||||
/** Set icon for Segmented item */
|
||||
icon: React.ReactNode;
|
||||
tooltip?: string | Omit<TooltipProps, 'children'>;
|
||||
}
|
||||
|
||||
function isSegmentedLabeledOptionWithIcon(
|
||||
@@ -43,7 +47,7 @@ export type SegmentedLabeledOption<ValueType = RcSegmentedValue> =
|
||||
export type SegmentedOptions<T = SegmentedRawOption> = (T | SegmentedLabeledOption<T>)[];
|
||||
|
||||
export interface SegmentedProps<ValueType = RcSegmentedValue>
|
||||
extends Omit<RCSegmentedProps<ValueType>, 'size' | 'options'> {
|
||||
extends Omit<RCSegmentedProps<ValueType>, 'size' | 'options' | 'itemRender'> {
|
||||
rootClassName?: string;
|
||||
options: SegmentedOptions<ValueType>;
|
||||
/** Option to fit width to its parent's width */
|
||||
@@ -59,7 +63,6 @@ export interface SegmentedProps<ValueType = RcSegmentedValue>
|
||||
|
||||
const InternalSegmented = React.forwardRef<HTMLDivElement, SegmentedProps>((props, ref) => {
|
||||
const defaultName = useId();
|
||||
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
@@ -151,6 +154,16 @@ const InternalSegmented = React.forwardRef<HTMLDivElement, SegmentedProps>((prop
|
||||
...style,
|
||||
};
|
||||
|
||||
const itemRender = (node: React.ReactNode, { item }: { item: SegmentedLabeledOption }) => {
|
||||
if (!item.tooltip) {
|
||||
return node;
|
||||
}
|
||||
|
||||
const tooltipProps: TooltipProps =
|
||||
typeof item.tooltip === 'object' ? item.tooltip : { title: item.tooltip };
|
||||
return <Tooltip {...tooltipProps}>{node}</Tooltip>;
|
||||
};
|
||||
|
||||
return (
|
||||
<RcSegmented
|
||||
{...restProps}
|
||||
@@ -165,6 +178,7 @@ const InternalSegmented = React.forwardRef<HTMLDivElement, SegmentedProps>((prop
|
||||
item: { ...contextStyles.item, ...styles?.item },
|
||||
label: { ...contextStyles.label, ...styles?.label },
|
||||
}}
|
||||
itemRender={itemRender}
|
||||
options={extendedOptions}
|
||||
ref={ref}
|
||||
prefixCls={prefixCls}
|
||||
|
||||
@@ -60,13 +60,14 @@ demo:
|
||||
|
||||
### SegmentedItemType
|
||||
|
||||
| 属性 | 描述 | 类型 | 默认值 | 版本 |
|
||||
| --------- | ---------------- | ---------------- | ------ | ---- |
|
||||
| label | 分段项的显示文本 | ReactNode | - | |
|
||||
| value | 分段项的值 | string \| number | - | |
|
||||
| icon | 分段项的显示图标 | ReactNode | - | |
|
||||
| disabled | 分段项的禁用状态 | boolean | false | |
|
||||
| className | 自定义类名 | string | - | |
|
||||
| 属性 | 描述 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| className | 自定义类名 | string | - | |
|
||||
| disabled | 分段项的禁用状态 | boolean | false | |
|
||||
| icon | 分段项的显示图标 | ReactNode | - | |
|
||||
| label | 分段项的显示文本 | ReactNode | - | |
|
||||
| tooltip | 分段项的工具提示 | string \| [TooltipProps](../tooltip/index.zh-CN.md#api) | - | |
|
||||
| value | 分段项的值 | string \| number | - | |
|
||||
|
||||
## Semantic DOM
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"@rc-component/progress": "~1.0.1",
|
||||
"@rc-component/qrcode": "~1.0.0",
|
||||
"@rc-component/resize-observer": "^1.0.0",
|
||||
"@rc-component/segmented": "~1.1.0",
|
||||
"@rc-component/segmented": "~1.2.1",
|
||||
"@rc-component/select": "~1.1.2",
|
||||
"@rc-component/steps": "~1.2.1",
|
||||
"@rc-component/switch": "~1.0.0",
|
||||
|
||||
Reference in New Issue
Block a user