diff --git a/components/avatar/__tests__/Avatar.test.tsx b/components/avatar/__tests__/Avatar.test.tsx index 26f2cb1c7e..dfbdf9f8a5 100644 --- a/components/avatar/__tests__/Avatar.test.tsx +++ b/components/avatar/__tests__/Avatar.test.tsx @@ -3,7 +3,7 @@ import React, { useState } from 'react'; import Avatar from '..'; import mountTest from '../../../tests/shared/mountTest'; import rtlTest from '../../../tests/shared/rtlTest'; -import { fireEvent, render } from '../../../tests/utils'; +import { fireEvent, render, waitFakeTimer } from '../../../tests/utils'; import ConfigProvider from '../../config-provider'; import useBreakpoint from '../../grid/hooks/useBreakpoint'; @@ -222,4 +222,83 @@ describe('Avatar Render', () => { expect(container.querySelector('.ant-avatar-sm')).toBeTruthy(); expect(container.querySelector('.ant-avatar-lg')).toBeTruthy(); }); + + it('Avatar.Group support max series props and prompt to deprecated', async () => { + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.useFakeTimers(); + const { container } = render( + + A + B + C + D + , + ); + + const avatars = container?.querySelectorAll('.ant-avatar-group .ant-avatar'); + fireEvent.mouseEnter(avatars?.[2]); + await waitFakeTimer(); + + /* check style */ + expect(container.querySelector('.ant-popover-open')).toBeTruthy(); + expect(container.querySelector('.ant-popover-open')).toHaveStyle('color: blue'); + + /* check count */ + expect(avatars.length).toBe(3); + + /* check popover */ + const popover = container.querySelector('.ant-avatar-group-popover'); + expect(popover).toBeTruthy(); + expect(popover).toHaveClass('ant-popover-placement-bottom'); + + expect(errSpy).toHaveBeenNthCalledWith( + 1, + 'Warning: [antd: Avatar.Group] `maxCount` is deprecated. Please use `max={{ count: number }}` instead.', + ); + expect(errSpy).toHaveBeenNthCalledWith( + 2, + 'Warning: [antd: Avatar.Group] `maxStyle` is deprecated. Please use `max={{ style: CSSProperties }}` instead.', + ); + expect(errSpy).toHaveBeenNthCalledWith( + 3, + 'Warning: [antd: Avatar.Group] `maxPopoverPlacement` is deprecated. Please use `max={{ popover: PopoverProps }}` instead.', + ); + }); + it('Avatar.Group support max object props', () => { + const { container } = render( + + A + B + C + D + , + ); + + /* check count */ + expect(container.querySelectorAll('.ant-avatar-group .ant-avatar').length).toBe(3); + + /* check popover */ + const popover = container.querySelector('.ant-avatar-group-popover'); + expect(popover).toBeTruthy(); + expect(popover).toHaveStyle('background: red'); + expect(popover).toHaveClass('wanpan-111 ant-popover-placement-bottomRight'); + expect(container.querySelector('.ant-popover-inner-content')).toHaveTextContent('Avatar.Group'); + + /* check style */ + expect(container.querySelector('.ant-popover-open')).toHaveStyle('color: blue'); + }); }); diff --git a/components/avatar/__tests__/demo.test.tsx b/components/avatar/__tests__/demo.test.tsx index 469cd66226..313f94e1f2 100644 --- a/components/avatar/__tests__/demo.test.tsx +++ b/components/avatar/__tests__/demo.test.tsx @@ -7,7 +7,7 @@ demoTest('avatar'); rootPropsTest( 'avatar', (Avatar, props) => ( - + Bamboo Light diff --git a/components/avatar/demo/component-token.tsx b/components/avatar/demo/component-token.tsx index 8216387378..1028101cc2 100644 --- a/components/avatar/demo/component-token.tsx +++ b/components/avatar/demo/component-token.tsx @@ -28,7 +28,12 @@ const App: React.FC = () => ( - + K diff --git a/components/avatar/demo/group.tsx b/components/avatar/demo/group.tsx index 9f56c44cc7..06f2b17c67 100644 --- a/components/avatar/demo/group.tsx +++ b/components/avatar/demo/group.tsx @@ -15,7 +15,12 @@ const App: React.FC = () => ( } /> - + K @@ -25,9 +30,11 @@ const App: React.FC = () => ( K @@ -38,10 +45,12 @@ const App: React.FC = () => ( K diff --git a/components/avatar/group.tsx b/components/avatar/group.tsx index 936164a404..cccae8c40d 100644 --- a/components/avatar/group.tsx +++ b/components/avatar/group.tsx @@ -3,8 +3,10 @@ import classNames from 'classnames'; import toArray from 'rc-util/lib/Children/toArray'; import { cloneElement } from '../_util/reactNode'; +import { devUseWarning } from '../_util/warning'; import { ConfigContext } from '../config-provider'; import useCSSVarCls from '../config-provider/hooks/useCSSVarCls'; +import type { PopoverProps } from '../popover'; import Popover from '../popover'; import Avatar from './avatar'; import AvatarContext from './AvatarContext'; @@ -32,10 +34,19 @@ export interface GroupProps { children?: React.ReactNode; style?: React.CSSProperties; prefixCls?: string; + /** @deprecated Please use `max={{ count: number }}` */ maxCount?: number; + /** @deprecated Please use `max={{ style: CSSProperties }}` */ maxStyle?: React.CSSProperties; + /** @deprecated Please use `max={{ popover: PopoverProps }}` */ maxPopoverPlacement?: 'top' | 'bottom'; + /** @deprecated Please use `max={{ popover: PopoverProps }}` */ maxPopoverTrigger?: 'hover' | 'focus' | 'click'; + max?: { + count?: number; + style?: React.CSSProperties; + popover?: PopoverProps; + }; /* * Size of avatar, options: `large`, `small`, `default` * or a custom number size @@ -55,11 +66,24 @@ const Group: React.FC = (props) => { maxStyle, size, shape, - maxPopoverPlacement = 'top', - maxPopoverTrigger = 'hover', + maxPopoverPlacement, + maxPopoverTrigger, children, + max, } = props; + if (process.env.NODE_ENV !== 'production') { + const warning = devUseWarning('Avatar.Group'); + warning.deprecated(!maxCount, 'maxCount', 'max={{ count: number }}'); + warning.deprecated(!maxStyle, 'maxStyle', 'max={{ style: CSSProperties }}'); + warning.deprecated( + !maxPopoverPlacement, + 'maxPopoverPlacement', + 'max={{ popover: PopoverProps }}', + ); + warning.deprecated(!maxPopoverTrigger, 'maxPopoverTrigger', 'max={{ popover: PopoverProps }}'); + } + const prefixCls = getPrefixCls('avatar', customizePrefixCls); const groupPrefixCls = `${prefixCls}-group`; const rootCls = useCSSVarCls(prefixCls); @@ -81,22 +105,30 @@ const Group: React.FC = (props) => { cloneElement(child, { key: `avatar-key-${index}` }), ); + const mergeCount = max?.count || maxCount; const numOfChildren = childrenWithProps.length; - if (maxCount && maxCount < numOfChildren) { - const childrenShow = childrenWithProps.slice(0, maxCount); - const childrenHidden = childrenWithProps.slice(maxCount, numOfChildren); + if (mergeCount && mergeCount < numOfChildren) { + const childrenShow = childrenWithProps.slice(0, mergeCount); + const childrenHidden = childrenWithProps.slice(mergeCount, numOfChildren); + + const mergeStyle = max?.style || maxStyle; + const mergePopoverTrigger = max?.popover?.trigger || maxPopoverTrigger || 'hover'; + const mergePopoverPlacement = max?.popover?.placement || maxPopoverPlacement || 'top'; + + const mergeProps = { + content: childrenHidden, + ...max?.popover, + overlayClassName: classNames(`${groupPrefixCls}-popover`, max?.popover?.overlayClassName), + placement: mergePopoverPlacement, + trigger: mergePopoverTrigger, + }; + childrenShow.push( - - {`+${numOfChildren - maxCount}`} + + {`+${numOfChildren - mergeCount}`} , ); + return wrapCSSVar(
diff --git a/components/avatar/index.en-US.md b/components/avatar/index.en-US.md index ef62abcf62..e8ece462c3 100644 --- a/components/avatar/index.en-US.md +++ b/components/avatar/index.en-US.md @@ -49,10 +49,7 @@ Common props ref:[Common props](/docs/react/common-props) | Property | Description | Type | Default | Version | | --- | --- | --- | --- | --- | -| maxCount | Max avatars to show | number | - | | -| maxPopoverPlacement | The placement of excess avatar Popover | `top` \| `bottom` | `top` | | -| maxPopoverTrigger | Set the trigger of excess avatar Popover | `hover` \| `focus` \| `click` | `hover` | 4.17.0 | -| maxStyle | The style of excess avatar style | CSSProperties | - | | +| max | Set maximum display related configurations, Before `5.18.0` you can use [parameters](https://github.com/ant-design/ant-design/blob/9d134859becbdae5b9ce276f6d9af4264691d81f/components/avatar/group.tsx#L35-L38) | `{ count?: number; style?: CSSProperties; popover?: PopoverProps }` | - | 5.18.0 | | size | The size of the avatar | number \| `large` \| `small` \| `default` \| { xs: number, sm: number, ...} | `default` | 4.8.0 | | shape | The shape of the avatar | `circle` \| `square` | `circle` | 5.8.0 | diff --git a/components/avatar/index.zh-CN.md b/components/avatar/index.zh-CN.md index 78ad873607..1b8b9630f3 100644 --- a/components/avatar/index.zh-CN.md +++ b/components/avatar/index.zh-CN.md @@ -54,10 +54,7 @@ group: | 参数 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | -| maxCount | 显示的最大头像个数 | number | - | | -| maxPopoverPlacement | 多余头像气泡弹出位置 | `top` \| `bottom` | `top` | | -| maxPopoverTrigger | 设置多余头像 Popover 的触发方式 | `hover` \| `focus` \| `click` | `hover` | 4.17.0 | -| maxStyle | 多余头像样式 | CSSProperties | - | | +| max | 设置最多显示相关配置,`5.18.0` 前可使用 [参数](https://github.com/ant-design/ant-design/blob/9d134859becbdae5b9ce276f6d9af4264691d81f/components/avatar/group.tsx#L35-L38) | `{ count?: number; style?: CSSProperties; popover?: PopoverProps }` | - | 5.18.0 | | size | 设置头像的大小 | number \| `large` \| `small` \| `default` \| { xs: number, sm: number, ...} | `default` | 4.8.0 | | shape | 设置头像的形状 | `circle` \| `square` | `circle` | 5.8.0 |