feat(badge): Support better customization with semantic classNames/styles as function (#54977)

* feat(badge): Support better customization with semantic classNames/styles as function

* update demo and snap

* update docs

* feat(badge): Support better customization with semantic classNames/styles as function

* update demo and snap

* update docs

* chore: update demo and snap

* chore: update demo

* chore: update demo

---------

Co-authored-by: thinkasany <480968828@qq.com>
This commit is contained in:
遇见同学
2025-10-01 00:27:52 +08:00
committed by GitHub
parent 4afd480fba
commit c279a4b112
10 changed files with 565 additions and 44 deletions

View File

@@ -4,6 +4,8 @@ import classNames from 'classnames';
import type { PresetColorType } from '../_util/colors';
import { isPresetColor } from '../_util/colors';
import type { LiteralUnion } from '../_util/type';
import useMergeSemantic from '../_util/hooks/useMergeSemantic';
import type { SemanticClassNamesType, SemanticStylesType } from '../_util/hooks/useMergeSemantic';
import useStyle from './style/ribbon';
import { useComponentConfig } from '../config-provider/context';
@@ -11,6 +13,9 @@ type RibbonPlacement = 'start' | 'end';
type SemanticName = 'root' | 'content' | 'indicator';
export type RibbonClassNamesType = SemanticClassNamesType<RibbonProps, SemanticName>;
export type RibbonStylesType = SemanticStylesType<RibbonProps, SemanticName>;
export interface RibbonProps {
className?: string;
prefixCls?: string;
@@ -20,8 +25,8 @@ export interface RibbonProps {
children?: React.ReactNode;
placement?: RibbonPlacement;
rootClassName?: string;
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
classNames?: RibbonClassNamesType;
styles?: RibbonStylesType;
}
const Ribbon: React.FC<RibbonProps> = (props) => {
@@ -50,6 +55,20 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
const wrapperCls = `${prefixCls}-wrapper`;
const [hashId, cssVarCls] = useStyle(prefixCls, wrapperCls);
// =========== Merged Props for Semantic ===========
const mergedProps: RibbonProps = {
...props,
placement,
};
const [mergedClassNames, mergedStyles] = useMergeSemantic<
RibbonClassNamesType,
RibbonStylesType,
RibbonProps
>([contextClassNames, ribbonClassNames], [contextStyles, styles], undefined, {
props: mergedProps,
});
const colorInPreset = isPresetColor(color, false);
const ribbonCls = classNames(
prefixCls,
@@ -60,8 +79,7 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
},
className,
contextClassName,
contextClassNames.indicator,
ribbonClassNames?.indicator,
mergedClassNames.indicator,
);
const colorStyle: React.CSSProperties = {};
@@ -72,34 +90,22 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
}
return (
<div
className={classNames(
wrapperCls,
rootClassName,
hashId,
cssVarCls,
ribbonClassNames?.root,
contextClassNames.root,
)}
style={{ ...contextStyles.root, ...styles?.root }}
className={classNames(wrapperCls, rootClassName, hashId, cssVarCls, mergedClassNames.root)}
style={mergedStyles.root}
>
{children}
<div
className={classNames(ribbonCls, hashId)}
style={{
...colorStyle,
...contextStyles.indicator,
...mergedStyles.indicator,
...contextStyle,
...styles?.indicator,
...style,
}}
>
<span
className={classNames(
`${prefixCls}-content`,
ribbonClassNames?.content,
contextClassNames.content,
)}
style={{ ...contextStyles.content, ...styles?.content }}
className={classNames(`${prefixCls}-content`, mergedClassNames.content)}
style={mergedStyles.content}
>
{text}
</span>

View File

@@ -3060,6 +3060,173 @@ Array [
exports[`renders components/badge/demo/status.tsx extend context correctly 2`] = `[]`;
exports[`renders components/badge/demo/style-class.tsx extend context correctly 1`] = `
<div
class="ant-space ant-space-vertical ant-space-gap-row-large ant-space-gap-col-large css-var-test-id"
>
<div
class="ant-space-item"
>
<div
class="ant-flex css-var-test-id ant-flex-gap-middle"
>
<span
class="ant-badge css-var-test-id"
style="background-color: rgb(240, 240, 240);"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square css-var-test-id ant-avatar-css-var"
>
<span
class="ant-avatar-string"
style="-webkit-transform: scale(1); transform: scale(1);"
/>
</span>
<sup
class="ant-scroll-number acss-9c7r58 ant-badge-count ant-badge-count-sm"
data-show="true"
title="5"
>
<bdi>
<span
class="ant-scroll-number-only"
style="transition: none;"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</bdi>
</sup>
</span>
<span
class="ant-badge css-var-test-id"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square css-var-test-id ant-avatar-css-var"
>
<span
class="ant-avatar-string"
style="-webkit-transform: scale(1); transform: scale(1);"
/>
</span>
<sup
class="ant-scroll-number acss-9c7r58 ant-badge-count"
data-show="true"
style="font-size: 14px; background-color: rgb(105, 111, 199);"
title="5"
>
<bdi>
<span
class="ant-scroll-number-only"
style="transition: none;"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</bdi>
</sup>
</span>
</div>
</div>
<div
class="ant-space-item"
>
<div
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-middle ant-flex-vertical"
>
<div
class="ant-ribbon-wrapper css-var-test-id acss-19a7de9"
>
<div
class="ant-card ant-card-bordered ant-card-small css-var-test-id"
>
<div
class="ant-card-head"
>
<div
class="ant-card-head-wrapper"
>
<div
class="ant-card-head-title"
>
Card with custom ribbon
</div>
</div>
</div>
<div
class="ant-card-body"
>
This card has a customized ribbon with semantic classNames and styles.
</div>
</div>
<div
class="ant-ribbon ant-ribbon-placement-end"
style="box-shadow: 0 2px 4px rgba(0,0,0,0.1);"
>
<span
class="ant-ribbon-content"
>
Custom Ribbon
</span>
<div
class="ant-ribbon-corner"
/>
</div>
</div>
<div
class="ant-ribbon-wrapper css-var-test-id acss-19a7de9"
>
<div
class="ant-card ant-card-bordered ant-card-small css-var-test-id"
>
<div
class="ant-card-head"
>
<div
class="ant-card-head-wrapper"
>
<div
class="ant-card-head-title"
>
Card with custom ribbon
</div>
</div>
</div>
<div
class="ant-card-body"
>
This card has a customized ribbon with semantic classNames and styles.
</div>
</div>
<div
class="ant-ribbon ant-ribbon-placement-end"
style="background: rgb(105, 111, 199); box-shadow: 0 2px 4px rgba(0,0,0,0.1);"
>
<span
class="ant-ribbon-content"
style="font-weight: bold;"
>
Custom Ribbon
</span>
<div
class="ant-ribbon-corner"
style="color: rgb(105, 111, 199);"
/>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders components/badge/demo/style-class.tsx extend context correctly 2`] = `[]`;
exports[`renders components/badge/demo/title.tsx extend context correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-large ant-space-gap-col-large css-var-test-id"

View File

@@ -3030,6 +3030,171 @@ Array [
]
`;
exports[`renders components/badge/demo/style-class.tsx correctly 1`] = `
<div
class="ant-space ant-space-vertical ant-space-gap-row-large ant-space-gap-col-large css-var-test-id"
>
<div
class="ant-space-item"
>
<div
class="ant-flex css-var-test-id ant-flex-gap-middle"
>
<span
class="ant-badge css-var-test-id"
style="background-color:#f0f0f0"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square css-var-test-id ant-avatar-css-var"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number acss-9c7r58 ant-badge-count ant-badge-count-sm"
data-show="true"
title="5"
>
<bdi>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</bdi>
</sup>
</span>
<span
class="ant-badge css-var-test-id"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square css-var-test-id ant-avatar-css-var"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number acss-9c7r58 ant-badge-count"
data-show="true"
style="font-size:14px;background-color:#696FC7"
title="5"
>
<bdi>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</bdi>
</sup>
</span>
</div>
</div>
<div
class="ant-space-item"
>
<div
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-middle ant-flex-vertical"
>
<div
class="ant-ribbon-wrapper css-var-test-id acss-19a7de9"
>
<div
class="ant-card ant-card-bordered ant-card-small css-var-test-id"
>
<div
class="ant-card-head"
>
<div
class="ant-card-head-wrapper"
>
<div
class="ant-card-head-title"
>
Card with custom ribbon
</div>
</div>
</div>
<div
class="ant-card-body"
>
This card has a customized ribbon with semantic classNames and styles.
</div>
</div>
<div
class="ant-ribbon ant-ribbon-placement-end"
style="box-shadow:0 2px 4px rgba(0,0,0,0.1)"
>
<span
class="ant-ribbon-content"
>
Custom Ribbon
</span>
<div
class="ant-ribbon-corner"
/>
</div>
</div>
<div
class="ant-ribbon-wrapper css-var-test-id acss-19a7de9"
>
<div
class="ant-card ant-card-bordered ant-card-small css-var-test-id"
>
<div
class="ant-card-head"
>
<div
class="ant-card-head-wrapper"
>
<div
class="ant-card-head-title"
>
Card with custom ribbon
</div>
</div>
</div>
<div
class="ant-card-body"
>
This card has a customized ribbon with semantic classNames and styles.
</div>
</div>
<div
class="ant-ribbon ant-ribbon-placement-end"
style="background:#696FC7;box-shadow:0 2px 4px rgba(0,0,0,0.1)"
>
<span
class="ant-ribbon-content"
style="font-weight:bold"
>
Custom Ribbon
</span>
<div
class="ant-ribbon-corner"
style="color:#696FC7"
/>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders components/badge/demo/title.tsx correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-large ant-space-gap-col-large css-var-test-id"

View File

@@ -272,4 +272,33 @@ describe('Badge', () => {
backgroundColor: 'rgb(0, 0, 255)',
});
});
it('should support function-based semantic classNames and styles', () => {
const { container } = render(
<Badge
count={5}
size="small"
classNames={({ props }) => ({
root: `badge-${props.size}`,
indicator: 'indicator-small',
})}
styles={({ props }) => ({
root: { padding: props.size === 'small' ? '2px' : '4px' },
indicator: { fontSize: '10px' },
})}
>
test
</Badge>,
);
const element = container.querySelector<HTMLSpanElement>('.ant-badge');
// function-based classNames
expect(element).toHaveClass('badge-small');
expect(element?.querySelector<HTMLElement>('sup')).toHaveClass('indicator-small');
// function-based styles
expect(element).toHaveStyle({ padding: '2px' });
expect(element?.querySelector<HTMLElement>('sup')).toHaveStyle({ fontSize: '10px' });
});
});

View File

@@ -113,4 +113,40 @@ describe('Ribbon', () => {
expect(indicatorElement.style.color).toBe('green');
expect(contentElement.style.color).toBe('yellow');
});
it('should support function-based classNames and styles', () => {
const { container } = render(
<Badge.Ribbon
text="Test"
color="blue"
placement="start"
classNames={({ props }) => ({
root: `ribbon-${props.placement}`,
indicator: 'ribbon-indicator',
content: 'ribbon-content',
})}
styles={({ props }) => ({
root: { border: props.placement === 'start' ? '1px solid red' : '1px solid blue' },
indicator: { opacity: '0.8' },
content: { fontWeight: 'bold' },
})}
>
<div>Test content</div>
</Badge.Ribbon>,
);
const rootElement = container.querySelector('.ant-ribbon-wrapper') as HTMLElement;
const indicatorElement = container.querySelector('.ant-ribbon') as HTMLElement;
const contentElement = container.querySelector('.ant-ribbon-content') as HTMLElement;
// check function-based classNames
expect(rootElement.classList).toContain('ribbon-start');
expect(indicatorElement.classList).toContain('ribbon-indicator');
expect(contentElement.classList).toContain('ribbon-content');
// check function-based styles
expect(rootElement.style.border).toBe('1px solid red');
expect(indicatorElement.style.opacity).toBe('0.8');
expect(contentElement.style.fontWeight).toBe('bold');
});
});

View File

@@ -0,0 +1,7 @@
## zh-CN
通过 `classNames``styles` 传入对象/函数可以自定义 Badge 的[语义化结构](#semantic-dom)样式。
## en-US
You can customize the [semantic dom](#semantic-dom) style of Badge by passing objects/functions through `classNames` and `styles`.

View File

@@ -0,0 +1,94 @@
import React from 'react';
import { Avatar, Badge, Card, Flex, Space } from 'antd';
import type { BadgeProps } from 'antd';
import { createStyles } from 'antd-style';
import type { RibbonProps } from 'antd/es/badge/Ribbon';
const useStylesBadge = createStyles(() => ({
indicator: {
fontSize: 10,
},
}));
const useStylesRibbon = createStyles(() => ({
root: {
width: 400,
border: '1px solid #d9d9d9',
borderRadius: 10,
},
}));
const App: React.FC = () => {
const { styles: badgeClassNames } = useStylesBadge();
const { styles: ribbonClassNames } = useStylesRibbon();
const badgeStyles: BadgeProps['styles'] = {
root: {
backgroundColor: '#f0f0f0',
},
};
const badgeStylesFn: BadgeProps['styles'] = (info) => {
if (info.props.size === 'default') {
return {
indicator: {
fontSize: 14,
backgroundColor: '#696FC7',
},
};
}
return {};
};
const ribbonStyles: RibbonProps['styles'] = {
indicator: {
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
},
};
const ribbonStylesFn: RibbonProps['styles'] = (info) => {
if (info.props.color === '#696FC7') {
return {
content: {
fontWeight: 'bold',
},
indicator: {
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
},
};
}
return {};
};
return (
<Space size="large" vertical>
<Flex gap="middle">
<Badge size="small" count={5} classNames={badgeClassNames} styles={badgeStyles}>
<Avatar shape="square" size="large" />
</Badge>
<Badge count={5} classNames={badgeClassNames} styles={badgeStylesFn}>
<Avatar shape="square" size="large" />
</Badge>
</Flex>
<Flex vertical gap="middle">
<Badge.Ribbon text="Custom Ribbon" classNames={ribbonClassNames} styles={ribbonStyles}>
<Card title="Card with custom ribbon" size="small">
This card has a customized ribbon with semantic classNames and styles.
</Card>
</Badge.Ribbon>
<Badge.Ribbon
text="Custom Ribbon"
color="#696FC7"
classNames={ribbonClassNames}
styles={ribbonStylesFn}
>
<Card title="Card with custom ribbon" size="small">
This card has a customized ribbon with semantic classNames and styles.
</Card>
</Badge.Ribbon>
</Flex>
</Space>
);
};
export default App;

View File

@@ -27,6 +27,7 @@ Badge normally appears in proximity to notifications or user avatars with eye-ca
<code src="./demo/status.tsx">Status</code>
<code src="./demo/colorful.tsx">Colorful Badge</code>
<code src="./demo/ribbon.tsx">Ribbon</code>
<code src="./demo/style-class.tsx" version="6.0.0">Custom semantic dom styling</code>
<code src="./demo/ribbon-debug.tsx" debug>Ribbon Debug</code>
<code src="./demo/mix.tsx" debug>Mixed usage</code>
<code src="./demo/title.tsx" debug>Title</code>
@@ -43,14 +44,14 @@ Common props ref[Common props](/docs/react/common-props)
| --- | --- | --- | --- | --- |
| color | Customize Badge dot color | string | - | |
| count | Number to show in badge | ReactNode | - | |
| classNames | Semantic DOM class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.7.0 |
| classNames | Customize class for each semantic structure inside the component. Supports object or function. | Record<[SemanticDOM](#semantic-dom), string> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), string> | - | |
| dot | Whether to display a red dot instead of `count` | boolean | false | |
| offset | Set offset of the badge dot | \[number, number] | - | |
| overflowCount | Max count to show | number | 99 | |
| showZero | Whether to show badge when `count` is zero | boolean | false | |
| size | If `count` is set, `size` sets the size of badge | `default` \| `small` | - | - |
| status | Set Badge as a status dot | `success` \| `processing` \| `default` \| `error` \| `warning` | - | |
| styles | Semantic DOM style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.7.0 |
| styles | Customize inline style for each semantic structure inside the component. Supports object or function. | Record<[SemanticDOM](#semantic-dom), CSSProperties> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), CSSProperties> | - | |
| text | If `status` is set, `text` sets the display text of the status `dot` | ReactNode | - | |
| title | Text to show when hovering over the badge | string | - | |
@@ -58,8 +59,10 @@ Common props ref[Common props](/docs/react/common-props)
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| classNames | Customize class for each semantic structure inside the component. Supports object or function. | Record<[SemanticDOM](#semantic-dom), string> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), string> | - | |
| color | Customize Ribbon color | string | - | |
| placement | The placement of the Ribbon, `start` and `end` follow text direction (RTL or LTR) | `start` \| `end` | `end` | |
| styles | Customize inline style for each semantic structure inside the component. Supports object or function. | Record<[SemanticDOM](#semantic-dom), CSSProperties> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), CSSProperties> | - | |
| text | Content inside the Ribbon | ReactNode | - | |
## Semantic DOM

View File

@@ -8,6 +8,8 @@ import { isPresetColor } from '../_util/colors';
import { cloneElement } from '../_util/reactNode';
import type { LiteralUnion } from '../_util/type';
import type { PresetColorKey } from '../theme/internal';
import useMergeSemantic from '../_util/hooks/useMergeSemantic';
import type { SemanticClassNamesType, SemanticStylesType } from '../_util/hooks/useMergeSemantic';
import Ribbon from './Ribbon';
import ScrollNumber from './ScrollNumber';
import useStyle from './style';
@@ -16,6 +18,10 @@ import { useComponentConfig } from '../config-provider/context';
export type { ScrollNumberProps } from './ScrollNumber';
type SemanticName = 'root' | 'indicator';
export type BadgeClassNamesType = SemanticClassNamesType<BadgeProps, SemanticName>;
export type BadgeStylesType = SemanticStylesType<BadgeProps, SemanticName>;
export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
/** Number to show in badge */
count?: React.ReactNode;
@@ -36,8 +42,8 @@ export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
offset?: [number | string, number | string];
title?: string;
children?: React.ReactNode;
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
classNames?: BadgeClassNamesType;
styles?: BadgeStylesType;
}
const InternalBadge = React.forwardRef<HTMLSpanElement, BadgeProps>((props, ref) => {
@@ -74,6 +80,21 @@ const InternalBadge = React.forwardRef<HTMLSpanElement, BadgeProps>((props, ref)
const [hashId, cssVarCls] = useStyle(prefixCls);
// =========== Merged Props for Semantic ===========
const mergedProps: BadgeProps = {
...props,
overflowCount,
size,
dot,
showZero,
};
const [mergedClassNames, mergedStyles] = useMergeSemantic<
BadgeClassNamesType,
BadgeStylesType,
BadgeProps
>([contextClassNames, classNames], [contextStyles, styles], undefined, { props: mergedProps });
// ================================ Misc ================================
const numberedDisplayCount = (
(count as number) > (overflowCount as number) ? `${overflowCount}+` : count
@@ -162,7 +183,7 @@ const InternalBadge = React.forwardRef<HTMLSpanElement, BadgeProps>((props, ref)
const isInternalColor = isPresetColor(color, false);
// Shared styles
const statusCls = classnames(classNames?.indicator, contextClassNames.indicator, {
const statusCls = classnames(mergedClassNames.indicator, {
[`${prefixCls}-status-dot`]: hasStatus,
[`${prefixCls}-status-${status}`]: !!status,
[`${prefixCls}-color-${color}`]: isInternalColor,
@@ -184,8 +205,7 @@ const InternalBadge = React.forwardRef<HTMLSpanElement, BadgeProps>((props, ref)
className,
rootClassName,
contextClassName,
contextClassNames.root,
classNames?.root,
mergedClassNames.root,
hashId,
cssVarCls,
);
@@ -197,12 +217,9 @@ const InternalBadge = React.forwardRef<HTMLSpanElement, BadgeProps>((props, ref)
<span
{...restProps}
className={badgeClassName}
style={{ ...styles?.root, ...contextStyles.root, ...mergedStyle }}
style={{ ...mergedStyles.root, ...mergedStyle }}
>
<span
className={statusCls}
style={{ ...styles?.indicator, ...contextStyles.indicator, ...statusStyle }}
/>
<span className={statusCls} style={{ ...mergedStyles.indicator, ...statusStyle }} />
{showStatusTextNode && (
<span style={{ color: statusTextColor }} className={`${prefixCls}-status-text`}>
{text}
@@ -213,12 +230,7 @@ const InternalBadge = React.forwardRef<HTMLSpanElement, BadgeProps>((props, ref)
}
return (
<span
ref={ref}
{...restProps}
className={badgeClassName}
style={{ ...contextStyles.root, ...styles?.root }}
>
<span ref={ref} {...restProps} className={badgeClassName} style={mergedStyles.root}>
{children}
<CSSMotion
visible={!isHidden}
@@ -234,7 +246,7 @@ const InternalBadge = React.forwardRef<HTMLSpanElement, BadgeProps>((props, ref)
const isDot = isDotRef.current;
const scrollNumberCls = classnames(classNames?.indicator, contextClassNames.indicator, {
const scrollNumberCls = classnames(mergedClassNames.indicator, {
[`${prefixCls}-dot`]: isDot,
[`${prefixCls}-count`]: !isDot,
[`${prefixCls}-count-sm`]: size === 'small',
@@ -245,8 +257,7 @@ const InternalBadge = React.forwardRef<HTMLSpanElement, BadgeProps>((props, ref)
});
let scrollNumberStyle: React.CSSProperties = {
...styles?.indicator,
...contextStyles.indicator,
...mergedStyles.indicator,
...mergedStyle,
};

View File

@@ -28,6 +28,7 @@ group: 数据展示
<code src="./demo/status.tsx">状态点</code>
<code src="./demo/colorful.tsx">多彩徽标</code>
<code src="./demo/ribbon.tsx">缎带</code>
<code src="./demo/style-class.tsx" version="6.0.0">自定义各种语义结构的样式和类</code>
<code src="./demo/ribbon-debug.tsx" debug>Ribbon Debug</code>
<code src="./demo/mix.tsx" debug>各种混用的情况</code>
<code src="./demo/title.tsx" debug>自定义标题</code>
@@ -44,14 +45,14 @@ group: 数据展示
| --- | --- | --- | --- | --- |
| color | 自定义小圆点的颜色 | string | - | |
| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | ReactNode | - | |
| classNames | 语义化结构 class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.7.0 |
| classNames | 用于自定义组件内部各语义化结构 class,支持对象或函数 | Record<[SemanticDOM](#semantic-dom), string> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), string> | - | |
| dot | 不展示数字,只有一个小红点 | boolean | false | |
| offset | 设置状态点的位置偏移 | \[number, number] | - | |
| overflowCount | 展示封顶的数字值 | number | 99 | |
| showZero | 当数值为 0 时,是否展示 Badge | boolean | false | |
| size | 在设置了 `count` 的前提下有效,设置小圆点的大小 | `default` \| `small` | - | - |
| status | 设置 Badge 为状态点 | `success` \| `processing` \| `default` \| `error` \| `warning` | - | |
| styles | 语义化结构 style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.7.0 |
| styles | 用于自定义组件内部各语义化结构的行内 style,支持对象或函数 | Record<[SemanticDOM](#semantic-dom), CSSProperties> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), CSSProperties> | - | |
| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | ReactNode | - | |
| title | 设置鼠标放在状态点上时显示的文字 | string | - | |
@@ -59,8 +60,10 @@ group: 数据展示
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| classNames | 用于自定义组件内部各语义化结构的 class支持对象或函数 | Record<[SemanticDOM](#semantic-dom), string> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), string> | - | |
| color | 自定义缎带的颜色 | string | - | |
| placement | 缎带的位置,`start``end` 随文字方向RTL 或 LTR变动 | `start` \| `end` | `end` | |
| styles | 用于自定义组件内部各语义化结构的行内 style支持对象或函数 | Record<[SemanticDOM](#semantic-dom), CSSProperties> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), CSSProperties> | - | |
| text | 缎带中填入的内容 | ReactNode | - | |
## Semantic DOM