mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-24 02:59:58 +08:00
feat: Avatar.Group adding max props (#49131)
* feat: Avatar.Group adding max props * feat: update * feat: update * feat: update test case * feat: update docs * Update components/avatar/index.en-US.md Co-authored-by: afc163 <afc163@gmail.com> Signed-off-by: Wanpan <wanpan96@163.com> * feat: update docs * feat: update * feat: update snap * feat: delete default value --------- Signed-off-by: Wanpan <wanpan96@163.com> Co-authored-by: afc163 <afc163@gmail.com>
This commit is contained in:
parent
ab7ac623cb
commit
8875ca7043
@ -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(
|
||||
<Avatar.Group maxCount={2} maxStyle={{ color: 'blue' }} maxPopoverPlacement="bottom">
|
||||
<Avatar>A</Avatar>
|
||||
<Avatar>B</Avatar>
|
||||
<Avatar>C</Avatar>
|
||||
<Avatar>D</Avatar>
|
||||
</Avatar.Group>,
|
||||
);
|
||||
|
||||
const avatars = container?.querySelectorAll<HTMLSpanElement>('.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(
|
||||
<Avatar.Group
|
||||
max={{
|
||||
count: 2,
|
||||
popover: {
|
||||
placement: 'bottomRight',
|
||||
overlayClassName: 'wanpan-111',
|
||||
overlayStyle: { background: 'red' },
|
||||
content: 'Avatar.Group',
|
||||
open: true,
|
||||
},
|
||||
style: {
|
||||
color: 'blue',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Avatar>A</Avatar>
|
||||
<Avatar>B</Avatar>
|
||||
<Avatar>C</Avatar>
|
||||
<Avatar>D</Avatar>
|
||||
</Avatar.Group>,
|
||||
);
|
||||
|
||||
/* 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');
|
||||
});
|
||||
});
|
||||
|
@ -7,7 +7,7 @@ demoTest('avatar');
|
||||
rootPropsTest(
|
||||
'avatar',
|
||||
(Avatar, props) => (
|
||||
<Avatar.Group {...props} maxCount={1}>
|
||||
<Avatar.Group {...props} max={{ count: 1 }}>
|
||||
<Avatar>Bamboo</Avatar>
|
||||
<Avatar>Light</Avatar>
|
||||
</Avatar.Group>
|
||||
|
@ -28,7 +28,12 @@ const App: React.FC = () => (
|
||||
</Avatar>
|
||||
</Space>
|
||||
<Space>
|
||||
<Avatar.Group maxCount={2} maxStyle={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>
|
||||
<Avatar.Group
|
||||
max={{
|
||||
count: 2,
|
||||
style: { color: '#f56a00', backgroundColor: '#fde3cf' },
|
||||
}}
|
||||
>
|
||||
<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=2" />
|
||||
<Avatar style={{ backgroundColor: '#f56a00' }}>K</Avatar>
|
||||
<Tooltip title="Ant User" placement="top">
|
||||
|
@ -15,7 +15,12 @@ const App: React.FC = () => (
|
||||
<Avatar style={{ backgroundColor: '#1677ff' }} icon={<AntDesignOutlined />} />
|
||||
</Avatar.Group>
|
||||
<Divider />
|
||||
<Avatar.Group maxCount={2} maxStyle={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>
|
||||
<Avatar.Group
|
||||
max={{
|
||||
count: 2,
|
||||
style: { color: '#f56a00', backgroundColor: '#fde3cf' },
|
||||
}}
|
||||
>
|
||||
<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=2" />
|
||||
<Avatar style={{ backgroundColor: '#f56a00' }}>K</Avatar>
|
||||
<Tooltip title="Ant User" placement="top">
|
||||
@ -25,9 +30,11 @@ const App: React.FC = () => (
|
||||
</Avatar.Group>
|
||||
<Divider />
|
||||
<Avatar.Group
|
||||
maxCount={2}
|
||||
size="large"
|
||||
maxStyle={{ color: '#f56a00', backgroundColor: '#fde3cf' }}
|
||||
max={{
|
||||
count: 2,
|
||||
style: { color: '#f56a00', backgroundColor: '#fde3cf' },
|
||||
}}
|
||||
>
|
||||
<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=3" />
|
||||
<Avatar style={{ backgroundColor: '#f56a00' }}>K</Avatar>
|
||||
@ -38,10 +45,12 @@ const App: React.FC = () => (
|
||||
</Avatar.Group>
|
||||
<Divider />
|
||||
<Avatar.Group
|
||||
maxCount={2}
|
||||
maxPopoverTrigger="click"
|
||||
size="large"
|
||||
maxStyle={{ color: '#f56a00', backgroundColor: '#fde3cf', cursor: 'pointer' }}
|
||||
max={{
|
||||
count: 2,
|
||||
style: { color: '#f56a00', backgroundColor: '#fde3cf', cursor: 'pointer' },
|
||||
popover: { trigger: 'click' },
|
||||
}}
|
||||
>
|
||||
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
|
||||
<Avatar style={{ backgroundColor: '#f56a00' }}>K</Avatar>
|
||||
|
@ -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<GroupProps> = (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<GroupProps> = (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(
|
||||
<Popover
|
||||
key="avatar-popover-key"
|
||||
content={childrenHidden}
|
||||
trigger={maxPopoverTrigger}
|
||||
placement={maxPopoverPlacement}
|
||||
overlayClassName={`${groupPrefixCls}-popover`}
|
||||
destroyTooltipOnHide
|
||||
>
|
||||
<Avatar style={maxStyle}>{`+${numOfChildren - maxCount}`}</Avatar>
|
||||
<Popover key="avatar-popover-key" destroyTooltipOnHide {...mergeProps}>
|
||||
<Avatar style={mergeStyle}>{`+${numOfChildren - mergeCount}`}</Avatar>
|
||||
</Popover>,
|
||||
);
|
||||
|
||||
return wrapCSSVar(
|
||||
<AvatarContextProvider shape={shape} size={size}>
|
||||
<div className={cls} style={style}>
|
||||
|
@ -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 |
|
||||
|
||||
|
@ -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 |
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user