Skip to content

Commit cfd4aad

Browse files
authored
feat(Avatar): group add shape & synch demo (#6822)
1 parent 38dd977 commit cfd4aad

13 files changed

+240
-160
lines changed

components/avatar/Avatar.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import useConfigInject from '../config-provider/hooks/useConfigInject';
1111
import ResizeObserver from '../vc-resize-observer';
1212
import eagerComputed from '../_util/eagerComputed';
1313
import useStyle from './style';
14-
import { useInjectSize } from './SizeContext';
14+
import { useAvatarInjectContext } from './AvatarContext';
1515

1616
export type AvatarSize = 'large' | 'small' | 'default' | number | ScreenSizeMap;
1717

@@ -56,9 +56,9 @@ const Avatar = defineComponent({
5656

5757
const { prefixCls } = useConfigInject('avatar', props);
5858
const [wrapSSR, hashId] = useStyle(prefixCls);
59-
const groupSize = useInjectSize();
59+
const avatarCtx = useAvatarInjectContext();
6060
const size = computed(() => {
61-
return props.size === 'default' ? groupSize.value : props.size;
61+
return props.size === 'default' ? avatarCtx.size : props.size;
6262
});
6363
const screens = useBreakpoint();
6464
const responsiveSize = eagerComputed(() => {
@@ -135,14 +135,15 @@ const Avatar = defineComponent({
135135

136136
return () => {
137137
const { shape, src, alt, srcset, draggable, crossOrigin } = props;
138+
const mergeShape = avatarCtx.shape ?? shape;
138139
const icon = getPropsSlot(slots, props, 'icon');
139140
const pre = prefixCls.value;
140141
const classString = {
141142
[`${attrs.class}`]: !!attrs.class,
142143
[pre]: true,
143144
[`${pre}-lg`]: size.value === 'large',
144145
[`${pre}-sm`]: size.value === 'small',
145-
[`${pre}-${shape}`]: shape,
146+
[`${pre}-${mergeShape}`]: true,
146147
[`${pre}-image`]: src && isImgExist.value,
147148
[`${pre}-icon`]: icon,
148149
[hashId.value]: true,

components/avatar/AvatarContext.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { InjectionKey } from 'vue';
2+
import { inject, provide } from 'vue';
3+
import type { ScreenSizeMap } from '../_util/responsiveObserve';
4+
export type AvatarSize = 'large' | 'small' | 'default' | number | ScreenSizeMap;
5+
export interface AvatarContextType {
6+
size?: AvatarSize;
7+
shape?: 'circle' | 'square';
8+
}
9+
const AvatarContextKey: InjectionKey<AvatarContextType> = Symbol('AvatarContextKey');
10+
11+
export const useAvatarInjectContext = () => {
12+
return inject(AvatarContextKey, {});
13+
};
14+
export const useAvatarProviderContext = (context: AvatarContextType) => {
15+
return provide(AvatarContextKey, context);
16+
};

components/avatar/Group.tsx

+9-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import type { AvatarSize } from './Avatar';
33
import Avatar from './Avatar';
44
import Popover from '../popover';
55
import type { PropType, ExtractPropTypes, CSSProperties } from 'vue';
6-
import { computed, defineComponent } from 'vue';
6+
import { computed, defineComponent, watchEffect } from 'vue';
77
import { flattenChildren, getPropsSlot } from '../_util/props-util';
88
import useConfigInject from '../config-provider/hooks/useConfigInject';
99
import useStyle from './style';
10-
import { useProviderSize } from './SizeContext';
10+
import { useAvatarProviderContext } from './AvatarContext';
1111

1212
export const groupProps = () => ({
1313
prefixCls: String,
@@ -23,6 +23,7 @@ export const groupProps = () => ({
2323
type: [Number, String, Object] as PropType<AvatarSize>,
2424
default: 'default' as AvatarSize,
2525
},
26+
shape: { type: String as PropType<'circle' | 'square'>, default: 'circle' },
2627
});
2728

2829
export type AvatarGroupProps = Partial<ExtractPropTypes<ReturnType<typeof groupProps>>>;
@@ -36,13 +37,17 @@ const Group = defineComponent({
3637
const { prefixCls, direction } = useConfigInject('avatar', props);
3738
const groupPrefixCls = computed(() => `${prefixCls.value}-group`);
3839
const [wrapSSR, hashId] = useStyle(prefixCls);
39-
useProviderSize(computed(() => props.size));
40+
watchEffect(() => {
41+
const context = { size: props.size, shape: props.shape };
42+
useAvatarProviderContext(context);
43+
});
4044
return () => {
4145
const {
4246
maxPopoverPlacement = 'top',
4347
maxCount,
4448
maxStyle,
4549
maxPopoverTrigger = 'hover',
50+
shape,
4651
} = props;
4752

4853
const cls = {
@@ -72,7 +77,7 @@ const Group = defineComponent({
7277
placement={maxPopoverPlacement}
7378
overlayClassName={`${groupPrefixCls.value}-popover`}
7479
>
75-
<Avatar style={maxStyle}>{`+${numOfChildren - maxCount}`}</Avatar>
80+
<Avatar style={maxStyle} shape={shape}>{`+${numOfChildren - maxCount}`}</Avatar>
7681
</Popover>,
7782
);
7883
return wrapSSR(

components/avatar/SizeContext.ts

-17
This file was deleted.

components/avatar/demo/badge.vue

+2-11
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,20 @@ Usually used for reminders and notifications.
1616
</docs>
1717

1818
<template>
19-
<span style="margin-right: 24px">
19+
<a-space :size="24">
2020
<a-badge :count="1">
2121
<a-avatar shape="square">
2222
<template #icon><UserOutlined /></template>
2323
</a-avatar>
2424
</a-badge>
25-
</span>
26-
<span>
2725
<a-badge dot>
2826
<a-avatar shape="square">
2927
<template #icon><UserOutlined /></template>
3028
</a-avatar>
3129
</a-badge>
32-
</span>
30+
</a-space>
3331
</template>
3432

3533
<script lang="ts" setup>
3634
import { UserOutlined } from '@ant-design/icons-vue';
3735
</script>
38-
39-
<style scoped>
40-
#components-avatar-demo-badge .ant-avatar {
41-
margin-top: 0;
42-
margin-right: 0;
43-
}
44-
</style>

components/avatar/demo/basic.vue

+30-25
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,36 @@ Three sizes and two shapes are available.
1616
</docs>
1717

1818
<template>
19-
<a-avatar :size="64">
20-
<template #icon><UserOutlined /></template>
21-
</a-avatar>
22-
<a-avatar size="large">
23-
<template #icon><UserOutlined /></template>
24-
</a-avatar>
25-
<a-avatar>
26-
<template #icon><UserOutlined /></template>
27-
</a-avatar>
28-
<a-avatar size="small">
29-
<template #icon><UserOutlined /></template>
30-
</a-avatar>
31-
<br />
32-
<a-avatar shape="square" :size="64">
33-
<template #icon><UserOutlined /></template>
34-
</a-avatar>
35-
<a-avatar shape="square" size="large">
36-
<template #icon><UserOutlined /></template>
37-
</a-avatar>
38-
<a-avatar shape="square">
39-
<template #icon><UserOutlined /></template>
40-
</a-avatar>
41-
<a-avatar shape="square" size="small">
42-
<template #icon><UserOutlined /></template>
43-
</a-avatar>
19+
<a-space direction="vertical" :size="32">
20+
<a-space wrap :size="16">
21+
<a-avatar :size="64">
22+
<template #icon><UserOutlined /></template>
23+
</a-avatar>
24+
<a-avatar size="large">
25+
<template #icon><UserOutlined /></template>
26+
</a-avatar>
27+
<a-avatar>
28+
<template #icon><UserOutlined /></template>
29+
</a-avatar>
30+
<a-avatar size="small">
31+
<template #icon><UserOutlined /></template>
32+
</a-avatar>
33+
</a-space>
34+
<a-space wrap :size="16">
35+
<a-avatar shape="square" :size="64">
36+
<template #icon><UserOutlined /></template>
37+
</a-avatar>
38+
<a-avatar shape="square" size="large">
39+
<template #icon><UserOutlined /></template>
40+
</a-avatar>
41+
<a-avatar shape="square">
42+
<template #icon><UserOutlined /></template>
43+
</a-avatar>
44+
<a-avatar shape="square" size="small">
45+
<template #icon><UserOutlined /></template>
46+
</a-avatar>
47+
</a-space>
48+
</a-space>
4449
</template>
4550

4651
<script lang="ts" setup>

components/avatar/demo/dynamic.vue

+16-14
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,22 @@ title:
88

99
## zh-CN
1010

11-
对于字符型的头像,当字符串较长时,字体大小可以根据头像宽度自动调整。
11+
对于字符型的头像,当字符串较长时,字体大小可以根据头像宽度自动调整。也可使用 `gap`` 来设置字符距离左右两侧边界单位像素。
1212

1313
## en-US
1414

15-
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar.
15+
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar. You can also use `gap` to set the unit distance between left and right sides.
1616
</docs>
1717

1818
<template>
19-
<a-avatar
20-
shape="square"
21-
size="large"
22-
:style="{ backgroundColor: color, verticalAlign: 'middle' }"
23-
>
19+
<a-avatar size="large" :style="{ backgroundColor: color, verticalAlign: 'middle' }" :gap="gap">
2420
{{ avatarValue }}
2521
</a-avatar>
26-
<a-button
27-
size="small"
28-
:style="{ marginLeft: '16px', verticalAlign: 'middle' }"
29-
@click="changeValue"
30-
>
31-
改变
22+
<a-button size="small" :style="{ margin: '0 16px', verticalAlign: 'middle' }" @click="changeUser">
23+
ChangeUser
24+
</a-button>
25+
<a-button size="small" :style="{ verticalAlign: 'middle' }" @click="changeGap">
26+
ChangeGap
3227
</a-button>
3328
</template>
3429

@@ -39,9 +34,16 @@ const UserList = ['U', 'Lucy', 'Tom', 'Edward'];
3934
const colorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
4035
const avatarValue = ref(UserList[0]);
4136
const color = ref(colorList[0]);
42-
const changeValue = () => {
37+
const changeUser = () => {
4338
const index = UserList.indexOf(avatarValue.value);
4439
avatarValue.value = index < UserList.length - 1 ? UserList[index + 1] : UserList[0];
4540
color.value = index < colorList.length - 1 ? colorList[index + 1] : colorList[0];
4641
};
42+
43+
const GapList = [4, 3, 2, 1];
44+
const gap = ref(GapList[0]);
45+
const changeGap = () => {
46+
const index = GapList.indexOf(gap.value);
47+
gap.value = index < GapList.length - 1 ? GapList[index + 1] : GapList[0];
48+
};
4749
</script>

components/avatar/demo/group.vue

+41-8
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,30 @@ Avatar group display.
1717

1818
<template>
1919
<a-avatar-group>
20-
<a-avatar src="https://joeschmoe.io/api/v1/random" />
21-
<a-avatar style="background-color: #f56a00">K</a-avatar>
20+
<a-avatar src="https://xsgames.co/randomusers/avatar.php?g=pixel&key=1" />
21+
<a href="https://www.antdv.com">
22+
<a-avatar style="background-color: #f56a00">K</a-avatar>
23+
</a>
2224
<a-tooltip title="Ant User" placement="top">
2325
<a-avatar style="background-color: #87d068">
2426
<template #icon><UserOutlined /></template>
2527
</a-avatar>
2628
</a-tooltip>
2729
<a-avatar style="background-color: #1890ff">
28-
<template #icon><UserOutlined /></template>
30+
<template #icon><AntDesignOutlined /></template>
2931
</a-avatar>
3032
</a-avatar-group>
3133
<a-divider />
3234
<a-avatar-group :max-count="2" :max-style="{ color: '#f56a00', backgroundColor: '#fde3cf' }">
33-
<a-avatar src="https://joeschmoe.io/api/v1/random" />
35+
<a-avatar src="https://xsgames.co/randomusers/avatar.php?g=pixel&key=2" />
3436
<a-avatar style="background-color: #1890ff">K</a-avatar>
3537
<a-tooltip title="Ant User" placement="top">
3638
<a-avatar style="background-color: #87d068">
3739
<template #icon><UserOutlined /></template>
3840
</a-avatar>
3941
</a-tooltip>
4042
<a-avatar style="background-color: #1890ff">
41-
<template #icon><UserOutlined /></template>
43+
<template #icon><AntDesignOutlined /></template>
4244
</a-avatar>
4345
</a-avatar-group>
4446
<a-divider />
@@ -50,19 +52,50 @@ Avatar group display.
5052
backgroundColor: '#fde3cf',
5153
}"
5254
>
53-
<a-avatar src="https://joeschmoe.io/api/v1/random" />
55+
<a-avatar src="https://xsgames.co/randomusers/avatar.php?g=pixel&key=3" />
5456
<a-avatar style="background-color: #1890ff">K</a-avatar>
5557
<a-tooltip title="Ant User" placement="top">
5658
<a-avatar style="background-color: #87d068">
5759
<template #icon><UserOutlined /></template>
5860
</a-avatar>
5961
</a-tooltip>
6062
<a-avatar style="background-color: #1890ff">
61-
<template #icon><UserOutlined /></template>
63+
<template #icon><AntDesignOutlined /></template>
64+
</a-avatar>
65+
</a-avatar-group>
66+
<a-divider />
67+
<a-avatar-group
68+
:max-count="2"
69+
max-popover-trigger="click"
70+
size="large"
71+
:max-style="{ color: '#f56a00', backgroundColor: '#fde3cf', cursor: 'pointer' }"
72+
>
73+
<a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
74+
<a-avatar style="background-color: #f56a00">K</a-avatar>
75+
<a-tooltip title="Ant User" placement="top">
76+
<a-avatar style="background-color: #87d068">
77+
<template #icon><UserOutlined /></template>
78+
</a-avatar>
79+
</a-tooltip>
80+
<a-avatar style="background-color: #1890ff">
81+
<template #icon><AntDesignOutlined /></template>
82+
</a-avatar>
83+
</a-avatar-group>
84+
<a-divider />
85+
<a-avatar-group shape="square">
86+
<a-avatar style="background-color: #fde3cf">A</a-avatar>
87+
<a-avatar style="background-color: #f56a00">K</a-avatar>
88+
<a-tooltip title="Ant User" placement="top">
89+
<a-avatar style="background-color: #87d068">
90+
<template #icon><UserOutlined /></template>
91+
</a-avatar>
92+
</a-tooltip>
93+
<a-avatar style="background-color: #1890ff">
94+
<template #icon><AntDesignOutlined /></template>
6295
</a-avatar>
6396
</a-avatar-group>
6497
</template>
6598

6699
<script lang="ts" setup>
67-
import { UserOutlined } from '@ant-design/icons-vue';
100+
import { UserOutlined, AntDesignOutlined } from '@ant-design/icons-vue';
68101
</script>

components/avatar/demo/index.vue

-7
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,3 @@ export default defineComponent({
3636
},
3737
});
3838
</script>
39-
40-
<style>
41-
[id^='components-avatar-demo-'] .ant-avatar {
42-
margin-top: 16px;
43-
margin-right: 16px;
44-
}
45-
</style>

0 commit comments

Comments
 (0)