Skip to content

Commit 437fdda

Browse files
authored
feat[cssvar]: Avatar & Badge support cssvar (#8327)
1 parent 2d3f40a commit 437fdda

File tree

11 files changed

+428
-190
lines changed

11 files changed

+428
-190
lines changed

components/avatar/Avatar.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import ResizeObserver from '../vc-resize-observer';
1212
import eagerComputed from '../_util/eagerComputed';
1313
import useStyle from './style';
1414
import { useAvatarInjectContext } from './AvatarContext';
15+
import useCSSVarCls from '../config-provider/hooks/useCssVarCls';
1516

1617
export type AvatarSize = 'large' | 'small' | 'default' | number | ScreenSizeMap;
1718

@@ -55,7 +56,8 @@ const Avatar = defineComponent({
5556
const avatarNodeRef = shallowRef<HTMLElement>(null);
5657

5758
const { prefixCls } = useConfigInject('avatar', props);
58-
const [wrapSSR, hashId] = useStyle(prefixCls);
59+
const rootCls = useCSSVarCls(prefixCls);
60+
const [wrapSSR, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
5961
const avatarCtx = useAvatarInjectContext();
6062
const size = computed(() => {
6163
return props.size === 'default' ? avatarCtx.size : props.size;
@@ -146,6 +148,8 @@ const Avatar = defineComponent({
146148
[`${pre}-${mergeShape}`]: true,
147149
[`${pre}-image`]: src && isImgExist.value,
148150
[`${pre}-icon`]: icon,
151+
[cssVarCls.value]: true,
152+
[rootCls.value]: true,
149153
[hashId.value]: true,
150154
};
151155

@@ -175,7 +179,7 @@ const Avatar = defineComponent({
175179
} else if (icon) {
176180
childrenToRender = icon;
177181
} else if (isMounted.value || scale.value !== 1) {
178-
const transformString = `scale(${scale.value}) translateX(-50%)`;
182+
const transformString = `scale(${scale.value})`;
179183
const childrenStyle: CSSProperties = {
180184
msTransform: transformString,
181185
WebkitTransform: transformString,

components/avatar/Group.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { PropType, ExtractPropTypes, CSSProperties } from 'vue';
66
import { computed, defineComponent, watchEffect } from 'vue';
77
import { flattenChildren, getPropsSlot } from '../_util/props-util';
88
import useConfigInject from '../config-provider/hooks/useConfigInject';
9+
import useCSSVarCls from '../config-provider/hooks/useCssVarCls';
910
import useStyle from './style';
1011
import { useAvatarProviderContext } from './AvatarContext';
1112

@@ -36,7 +37,8 @@ const Group = defineComponent({
3637
setup(props, { slots, attrs }) {
3738
const { prefixCls, direction } = useConfigInject('avatar', props);
3839
const groupPrefixCls = computed(() => `${prefixCls.value}-group`);
39-
const [wrapSSR, hashId] = useStyle(prefixCls);
40+
const rootCls = useCSSVarCls(prefixCls);
41+
const [wrapSSR, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
4042
watchEffect(() => {
4143
const context = { size: props.size, shape: props.shape };
4244
useAvatarProviderContext(context);
@@ -54,6 +56,8 @@ const Group = defineComponent({
5456
[groupPrefixCls.value]: true,
5557
[`${groupPrefixCls.value}-rtl`]: direction.value === 'rtl',
5658
[`${attrs.class}`]: !!attrs.class,
59+
[cssVarCls.value]: true,
60+
[rootCls.value]: true,
5761
[hashId.value]: true,
5862
};
5963

components/avatar/style/index.ts

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
import { unit } from '../../_util/cssinjs';
12
import type { CSSObject } from '../../_util/cssinjs';
2-
import type { FullToken, GenerateStyle } from '../../theme/internal';
3-
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
3+
44
import { resetComponent } from '../../style';
5+
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
6+
import { genStyleHooks, mergeToken } from '../../theme/internal';
57

68
export interface ComponentToken {
79
/**
8-
* @desc 头像背景色
9-
* @descEN Background color of Avatar
10+
* @desc 头像尺寸
11+
* @descEN Size of Avatar
1012
*/
1113
containerSize: number;
1214
/**
@@ -51,10 +53,14 @@ export interface ComponentToken {
5153
groupBorderColor: string;
5254
}
5355

56+
/**
57+
* @desc Avatar 组件的 Token
58+
* @descEN Token for Avatar component
59+
*/
5460
type AvatarToken = FullToken<'Avatar'> & {
61+
avatarBgColor: string;
5562
avatarBg: string;
5663
avatarColor: string;
57-
avatarBgColor: string;
5864
};
5965

6066
const genBaseStyle: GenerateStyle<AvatarToken> = token => {
@@ -81,22 +87,12 @@ const genBaseStyle: GenerateStyle<AvatarToken> = token => {
8187
const avatarSizeStyle = (size: number, fontSize: number, radius: number): CSSObject => ({
8288
width: size,
8389
height: size,
84-
lineHeight: `${size - lineWidth * 2}px`,
8590
borderRadius: '50%',
8691

8792
[`&${componentCls}-square`]: {
8893
borderRadius: radius,
8994
},
9095

91-
[`${componentCls}-string`]: {
92-
position: 'absolute',
93-
left: {
94-
_skip_check_: true,
95-
value: '50%',
96-
},
97-
transformOrigin: '0 center',
98-
},
99-
10096
[`&${componentCls}-icon`]: {
10197
fontSize,
10298
[`> ${iconCls}`]: {
@@ -109,16 +105,18 @@ const genBaseStyle: GenerateStyle<AvatarToken> = token => {
109105
[componentCls]: {
110106
...resetComponent(token),
111107
position: 'relative',
112-
display: 'inline-block',
108+
display: 'inline-flex',
109+
justifyContent: 'center',
110+
alignItems: 'center',
113111
overflow: 'hidden',
114112
color: avatarColor,
115113
whiteSpace: 'nowrap',
116114
textAlign: 'center',
117115
verticalAlign: 'middle',
118116
background: avatarBg,
119-
border: `${lineWidth}px ${lineType} transparent`,
117+
border: `${unit(lineWidth)} ${lineType} transparent`,
120118

121-
[`&-image`]: {
119+
'&-image': {
122120
background: 'transparent',
123121
},
124122

@@ -128,11 +126,11 @@ const genBaseStyle: GenerateStyle<AvatarToken> = token => {
128126

129127
...avatarSizeStyle(containerSize, textFontSize, borderRadius),
130128

131-
[`&-lg`]: {
129+
'&-lg': {
132130
...avatarSizeStyle(containerSizeLG, textFontSizeLG, borderRadiusLG),
133131
},
134132

135-
[`&-sm`]: {
133+
'&-sm': {
136134
...avatarSizeStyle(containerSizeSM, textFontSizeSM, borderRadiusSM),
137135
},
138136

@@ -153,11 +151,11 @@ const genGroupStyle: GenerateStyle<AvatarToken> = token => {
153151
[`${componentCls}-group`]: {
154152
display: 'inline-flex',
155153

156-
[`${componentCls}`]: {
154+
[componentCls]: {
157155
borderColor: groupBorderColor,
158156
},
159157

160-
[`> *:not(:first-child)`]: {
158+
'> *:not(:first-child)': {
161159
marginInlineStart: groupOverlapping,
162160
},
163161
},
@@ -169,7 +167,33 @@ const genGroupStyle: GenerateStyle<AvatarToken> = token => {
169167
};
170168
};
171169

172-
export default genComponentStyleHook(
170+
export const prepareComponentToken: GetDefaultToken<'Avatar'> = token => {
171+
const {
172+
controlHeight,
173+
controlHeightLG,
174+
controlHeightSM,
175+
fontSize,
176+
fontSizeLG,
177+
fontSizeXL,
178+
fontSizeHeading3,
179+
marginXS,
180+
marginXXS,
181+
colorBorderBg,
182+
} = token;
183+
return {
184+
containerSize: controlHeight,
185+
containerSizeLG: controlHeightLG,
186+
containerSizeSM: controlHeightSM,
187+
textFontSize: Math.round((fontSizeLG + fontSizeXL) / 2),
188+
textFontSizeLG: fontSizeHeading3,
189+
textFontSizeSM: fontSize,
190+
groupSpace: marginXXS,
191+
groupOverlapping: -marginXS,
192+
groupBorderColor: colorBorderBg,
193+
};
194+
};
195+
196+
export default genStyleHooks(
173197
'Avatar',
174198
token => {
175199
const { colorTextLightSolid, colorTextPlaceholder } = token;
@@ -179,33 +203,5 @@ export default genComponentStyleHook(
179203
});
180204
return [genBaseStyle(avatarToken), genGroupStyle(avatarToken)];
181205
},
182-
token => {
183-
const {
184-
controlHeight,
185-
controlHeightLG,
186-
controlHeightSM,
187-
188-
fontSize,
189-
fontSizeLG,
190-
fontSizeXL,
191-
fontSizeHeading3,
192-
193-
marginXS,
194-
marginXXS,
195-
colorBorderBg,
196-
} = token;
197-
return {
198-
containerSize: controlHeight,
199-
containerSizeLG: controlHeightLG,
200-
containerSizeSM: controlHeightSM,
201-
202-
textFontSize: Math.round((fontSizeLG + fontSizeXL) / 2),
203-
textFontSizeLG: fontSizeHeading3,
204-
textFontSizeSM: fontSize,
205-
206-
groupSpace: marginXXS,
207-
groupOverlapping: -marginXS,
208-
groupBorderColor: colorBorderBg,
209-
};
210-
},
206+
prepareComponentToken,
211207
);

components/badge/Badge.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { defineComponent, computed, ref, watch, Transition } from 'vue';
99
import Ribbon from './Ribbon';
1010
import useConfigInject from '../config-provider/hooks/useConfigInject';
1111
import isNumeric from '../_util/isNumeric';
12+
import useCSSVarCls from '../config-provider/hooks/useCssVarCls';
1213
import useStyle from './style';
1314
import type { PresetColorKey } from '../theme/interface';
1415
import type { LiteralUnion, CustomSlotsType } from '../_util/type';
@@ -49,7 +50,8 @@ export default defineComponent({
4950
}>,
5051
setup(props, { slots, attrs }) {
5152
const { prefixCls, direction } = useConfigInject('badge', props);
52-
const [wrapSSR, hashId] = useStyle(prefixCls);
53+
const rootCls = useCSSVarCls(prefixCls);
54+
const [wrapSSR, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
5355

5456
// ================================ Misc ================================
5557
const numberedDisplayCount = computed(() => {
@@ -189,6 +191,8 @@ export default defineComponent({
189191
[`${pre}-rtl`]: direction.value === 'rtl',
190192
},
191193
attrs.class,
194+
cssVarCls.value,
195+
rootCls.value,
192196
hashId.value,
193197
);
194198

components/badge/Ribbon.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { CustomSlotsType, LiteralUnion } from '../_util/type';
22
import type { PresetColorType } from '../_util/colors';
3-
import useStyle from './style';
3+
import useCSSVarCls from '../config-provider/hooks/useCssVarCls';
4+
import useStyle from './style/ribbon';
45
import { isPresetColor } from '../_util/colors';
56
import type { CSSProperties, PropType, ExtractPropTypes } from 'vue';
67
import { defineComponent, computed } from 'vue';
@@ -27,7 +28,8 @@ export default defineComponent({
2728
}>,
2829
setup(props, { attrs, slots }) {
2930
const { prefixCls, direction } = useConfigInject('ribbon', props);
30-
const [wrapSSR, hashId] = useStyle(prefixCls);
31+
const rootCls = useCSSVarCls(prefixCls);
32+
const [wrapSSR, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
3133
const colorInPreset = computed(() => isPresetColor(props.color, false));
3234
const ribbonCls = computed(() => [
3335
prefixCls.value,
@@ -46,7 +48,10 @@ export default defineComponent({
4648
cornerColorStyle.color = props.color;
4749
}
4850
return wrapSSR(
49-
<div class={`${prefixCls.value}-wrapper ${hashId.value}`} {...restAttrs}>
51+
<div
52+
class={`${prefixCls.value}-wrapper ${cssVarCls.value} ${rootCls.value} ${hashId.value}`}
53+
{...restAttrs}
54+
>
5055
{slots.default?.()}
5156
<div
5257
class={[ribbonCls.value, className, hashId.value]}

0 commit comments

Comments
 (0)