diff --git a/build/config.js b/build/config.js
index 452a79999..ddbb5d3d1 100644
--- a/build/config.js
+++ b/build/config.js
@@ -1,5 +1,5 @@
module.exports = {
dev: {
- componentName: 'back-top', // dev components
+ componentName: 'badge', // dev components
},
};
diff --git a/components/badge/Badge.jsx b/components/badge/Badge.jsx
index 7041cacd0..0ae40a38e 100644
--- a/components/badge/Badge.jsx
+++ b/components/badge/Badge.jsx
@@ -1,5 +1,6 @@
import PropTypes from '../_util/vue-types';
import ScrollNumber from './ScrollNumber';
+import { PresetColorTypes } from '../_util/colors';
import classNames from 'classnames';
import {
initDefaultProps,
@@ -23,12 +24,15 @@ export const BadgeProps = {
prefixCls: PropTypes.string,
scrollNumberPrefixCls: PropTypes.string,
status: PropTypes.oneOf(['success', 'processing', 'default', 'error', 'warning']),
+ color: PropTypes.string,
text: PropTypes.string,
offset: PropTypes.array,
numberStyle: PropTypes.object.def({}),
title: PropTypes.string,
};
-
+function isPresetColor(color) {
+ return PresetColorTypes.indexOf(color) !== -1;
+}
export default {
name: 'ABadge',
props: initDefaultProps(BadgeProps, {
@@ -40,35 +44,6 @@ export default {
configProvider: { default: () => ConfigConsumerProps },
},
methods: {
- getBadgeClassName(prefixCls) {
- const { status } = this.$props;
- const children = filterEmpty(this.$slots.default);
- return classNames(prefixCls, {
- [`${prefixCls}-status`]: !!status,
- [`${prefixCls}-not-a-wrapper`]: !children.length,
- });
- },
-
- isZero() {
- const numberedDispayCount = this.getNumberedDispayCount();
- return numberedDispayCount === '0' || numberedDispayCount === 0;
- },
-
- isDot() {
- const { dot, status } = this.$props;
- const isZero = this.isZero();
- return (dot && !isZero) || status;
- },
-
- isHidden() {
- const { showZero } = this.$props;
- const displayCount = this.getDispayCount();
- const isZero = this.isZero();
- const isDot = this.isDot();
- const isEmpty = displayCount === null || displayCount === undefined || displayCount === '';
- return (isEmpty || (isZero && !showZero)) && !isDot;
- },
-
getNumberedDispayCount() {
const { overflowCount } = this.$props;
const count = this.badgeCount;
@@ -104,6 +79,37 @@ export default {
}
: numberStyle;
},
+ getBadgeClassName(prefixCls) {
+ const { status } = this.$props;
+ const children = filterEmpty(this.$slots.default);
+ return classNames(prefixCls, {
+ [`${prefixCls}-status`]: !!status,
+ [`${prefixCls}-not-a-wrapper`]: !children.length,
+ });
+ },
+ hasStatus() {
+ const { status, color } = this.$props;
+ return !!status || !!color;
+ },
+ isZero() {
+ const numberedDispayCount = this.getNumberedDispayCount();
+ return numberedDispayCount === '0' || numberedDispayCount === 0;
+ },
+
+ isDot() {
+ const { dot, status } = this.$props;
+ const isZero = this.isZero();
+ return (dot && !isZero) || this.hasStatus();
+ },
+
+ isHidden() {
+ const { showZero } = this.$props;
+ const displayCount = this.getDispayCount();
+ const isZero = this.isZero();
+ const isDot = this.isDot();
+ const isEmpty = displayCount === null || displayCount === undefined || displayCount === '';
+ return (isEmpty || (isZero && !showZero)) && !isDot;
+ },
renderStatusText(prefixCls) {
const { text } = this.$props;
@@ -134,7 +140,7 @@ export default {
[`${prefixCls}-count`]: !isDot,
[`${prefixCls}-multiple-words`]:
!isDot && count && count.toString && count.toString().length > 1,
- [`${prefixCls}-status-${status}`]: !!status,
+ [`${prefixCls}-status-${status}`]: this.hasStatus(),
};
return hidden ? null : (
@@ -159,6 +165,7 @@ export default {
scrollNumberPrefixCls: customizeScrollNumberPrefixCls,
status,
text,
+ color,
$slots,
} = this;
@@ -175,20 +182,28 @@ export default {
const scrollNumber = this.renderBadgeNumber(prefixCls, scrollNumberPrefixCls);
const statusText = this.renderStatusText(prefixCls);
const statusCls = classNames({
- [`${prefixCls}-status-dot`]: !!status,
+ [`${prefixCls}-status-dot`]: this.hasStatus(),
[`${prefixCls}-status-${status}`]: !!status,
+ [`${prefixCls}-status-${color}`]: isPresetColor(color),
});
-
+ const statusStyle = {};
+ if (color && !isPresetColor(color)) {
+ statusStyle.background = color;
+ }
//
- if (!children.length && status) {
+ if (!children.length && this.hasStatus()) {
+ const styleWithOffset = this.getStyleWithOffset();
+ const statusTextColor = styleWithOffset && styleWithOffset.color;
return (
-
- {text}
+
+
+ {text}
+
);
}
diff --git a/components/badge/ScrollNumber.jsx b/components/badge/ScrollNumber.jsx
index e4d661f4e..fec3615f8 100644
--- a/components/badge/ScrollNumber.jsx
+++ b/components/badge/ScrollNumber.jsx
@@ -12,7 +12,10 @@ function getNumberArray(num) {
.toString()
.split('')
.reverse()
- .map(i => Number(i))
+ .map(i => {
+ const current = Number(i);
+ return isNaN(current) ? i : current;
+ })
: [];
}
@@ -38,42 +41,38 @@ export default {
};
},
watch: {
- count(val) {
- if (this.sCount !== val) {
- this.lastCount = this.sCount;
- // 复原数字初始位置
- this.setState(
- {
- animateStarted: true,
- },
- () => {
- // 等待数字位置复原完毕
- // 开始设置完整的数字
- setTimeout(() => {
- this.setState(
- {
- animateStarted: false,
- sCount: val,
- },
- () => {
- this.$emit('animated');
- },
- );
- }, 5);
- },
- );
- }
+ count() {
+ this.lastCount = this.sCount;
+ this.setState({
+ animateStarted: true,
+ });
},
},
+ updated() {
+ const { animateStarted, count } = this;
+ if (animateStarted) {
+ this.setState(
+ {
+ animateStarted: false,
+ sCount: count,
+ },
+ this.onAnimated,
+ );
+ }
+ },
methods: {
getPositionByNum(num, i) {
+ const { sCount } = this;
+ const currentCount = Math.abs(Number(sCount));
+ const lastCount = Math.abs(Number(this.lastCount));
+ const currentDigit = Math.abs(getNumberArray(sCount)[i]);
+ const lastDigit = Math.abs(getNumberArray(this.lastCount)[i]);
+
if (this.animateStarted) {
return 10 + num;
}
- const currentDigit = getNumberArray(this.sCount)[i];
- const lastDigit = getNumberArray(this.lastCount)[i];
// 同方向则在同一侧切换数字
- if (this.sCount > this.lastCount) {
+ if (currentCount > lastCount) {
if (currentDigit >= lastDigit) {
return 10 + num;
}
@@ -84,6 +83,10 @@ export default {
}
return num;
},
+ onAnimated() {
+ this.$emit('animated');
+ },
+
renderNumberList(position) {
const childrenToReturn = [];
for (let i = 0; i < 30; i++) {
@@ -94,22 +97,29 @@ export default {
,
);
}
+
return childrenToReturn;
},
-
renderCurrentNumber(prefixCls, num, i) {
- const position = this.getPositionByNum(num, i);
- const removeTransition =
- this.animateStarted || getNumberArray(this.lastCount)[i] === undefined;
- const style = {
- transition: removeTransition ? 'none' : undefined,
- msTransform: `translateY(${-position * 100}%)`,
- WebkitTransform: `translateY(${-position * 100}%)`,
- transform: `translateY(${-position * 100}%)`,
- };
+ if (typeof num === 'number') {
+ const position = this.getPositionByNum(num, i);
+ const removeTransition =
+ this.animateStarted || getNumberArray(this.lastCount)[i] === undefined;
+ const style = {
+ transition: removeTransition ? 'none' : undefined,
+ msTransform: `translateY(${-position * 100}%)`,
+ WebkitTransform: `translateY(${-position * 100}%)`,
+ transform: `translateY(${-position * 100}%)`,
+ };
+ return (
+
+ {this.renderNumberList(position)}
+
+ );
+ }
return (
-
- {this.renderNumberList(position)}
+
+ {num}
);
},
diff --git a/components/badge/__tests__/__snapshots__/demo.test.js.snap b/components/badge/__tests__/__snapshots__/demo.test.js.snap
index 75c640c23..7b1d2ec17 100644
--- a/components/badge/__tests__/__snapshots__/demo.test.js.snap
+++ b/components/badge/__tests__/__snapshots__/demo.test.js.snap
@@ -16,6 +16,29 @@ exports[`renders ./components/badge/demo/change.md correctly 1`] = `
`;
+exports[`renders ./components/badge/demo/colors.md correctly 1`] = `
+
+
Presets:
+
+
pink
+
red
+
yellow
+
orange
+
cyan
+
green
+
blue
+
purple
+
geekblue
+
magenta
+
volcano
+
gold
+
lime
+
+
Custom:
+
#f50
#2db7f5
#87d068
#108ee9
+
+`;
+
exports[`renders ./components/badge/demo/dot.md correctly 1`] = ``;
exports[`renders ./components/badge/demo/link.md correctly 1`] = `0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
`;
diff --git a/components/badge/__tests__/__snapshots__/index.test.js.snap b/components/badge/__tests__/__snapshots__/index.test.js.snap
index 63783d156..e5457550f 100644
--- a/components/badge/__tests__/__snapshots__/index.test.js.snap
+++ b/components/badge/__tests__/__snapshots__/index.test.js.snap
@@ -4,6 +4,8 @@ exports[`Badge badge should support float number 1`] = `"3.5"`;
exports[`Badge badge should support float number 2`] = `3.5`;
+exports[`Badge render correct with negative number 1`] = `-0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
-0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
`;
+
exports[`Badge should be compatible with borderColor style 1`] = `0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
`;
exports[`Badge should render when count is changed 1`] = `0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
`;
@@ -16,4 +18,4 @@ exports[`Badge should render when count is changed 4`] = `0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
`;
-exports[`Badge should support offset when count is a ReactNode 1`] = ``;
+exports[`Badge should support offset when count is a VueNode 1`] = `head`;
diff --git a/components/badge/__tests__/index.test.js b/components/badge/__tests__/index.test.js
index 8768a4e0f..ac1361d47 100644
--- a/components/badge/__tests__/index.test.js
+++ b/components/badge/__tests__/index.test.js
@@ -109,16 +109,32 @@ describe('Badge', () => {
});
// https://github.com/ant-design/ant-design/issues/13694
- it('should support offset when count is a ReactNode', () => {
+ it('should support offset when count is a VueNode', () => {
const wrapper = mount({
render() {
return (
} offset={[10, 20]}>
-
+
+ head
+
);
},
});
expect(wrapper.html()).toMatchSnapshot();
});
+ // https://github.com/ant-design/ant-design/issues/15799
+ it('render correct with negative number', () => {
+ const wrapper = mount({
+ render() {
+ return (
+
+
+
+
+ );
+ },
+ });
+ expect(wrapper.html()).toMatchSnapshot();
+ });
});
diff --git a/components/badge/demo/colors.md b/components/badge/demo/colors.md
new file mode 100644
index 000000000..17f882cd3
--- /dev/null
+++ b/components/badge/demo/colors.md
@@ -0,0 +1,56 @@
+
+#### 多彩徽标
+1.5.0 后新增。我们添加了多种预设色彩的徽标样式,用作不同场景使用。如果预设值不能满足你的需求,可以设置为具体的色值。
+
+
+
+#### Colorful Badge
+New feature after 3.16.0. We preset a series of colorful Badge styles for use in different situations. You can also set it to a hex color string for custom color.
+
+
+```tpl
+
+
+
Presets:
+
+
Custom:
+
+
+
+
+```
diff --git a/components/badge/demo/index.vue b/components/badge/demo/index.vue
index 52d0151d1..d81ed6905 100644
--- a/components/badge/demo/index.vue
+++ b/components/badge/demo/index.vue
@@ -6,6 +6,7 @@ import Change from './change';
import Overflow from './overflow';
import Status from './status';
import Title from './title';
+import Colors from './colors';
import CN from './../index.zh-CN.md';
import US from './../index.en_US.md';
@@ -42,6 +43,7 @@ export default {
+
diff --git a/components/badge/index.en_US.md b/components/badge/index.en_US.md
index 2494012cd..72dc6f3c8 100644
--- a/components/badge/index.en_US.md
+++ b/components/badge/index.en_US.md
@@ -10,14 +10,15 @@
```
-| Property | Description | Type | Default |
-| --- | --- | --- | --- |
-| count | Number to show in badge | number\|string \| slot | |
-| dot | Whether to display a red dot instead of `count` | boolean | `false` |
-| offset | set offset of the badge dot, like [x, y] | [number\|string, number\|string] | - |
-| overflowCount | Max count to show | number | 99 |
-| showZero | Whether to show badge when `count` is zero | boolean | `false` |
-| status | Set Badge as a status dot | `success` \| `processing` \| `default` \| `error` \| `warning` | `''` |
-| text | If `status` is set, `text` sets the display text of the status `dot` | string | `''` |
-| numberStyle | sets the display style of the status `dot` | object | '' |
-| title | Text to show when hovering over the badge | string | `count` |
+| Property | Description | Type | Default | Version |
+| --- | --- | --- | --- | --- |
+| color | Customize Badge dot color | string | - | 1.5.0 |
+| count | Number to show in badge | number\|string \| slot | | |
+| dot | Whether to display a red dot instead of `count` | boolean | `false` | |
+| offset | set offset of the badge dot, like [x, y] | [number\|string, number\|string] | - | |
+| overflowCount | Max count to show | number | 99 | |
+| showZero | Whether to show badge when `count` is zero | boolean | `false` | |
+| status | Set Badge as a status dot | `success` \| `processing` \| `default` \| `error` \| `warning` | `''` | |
+| text | If `status` is set, `text` sets the display text of the status `dot` | string | `''` | |
+| numberStyle | sets the display style of the status `dot` | object | '' | |
+| title | Text to show when hovering over the badge | string | `count` | |
diff --git a/components/badge/index.zh-CN.md b/components/badge/index.zh-CN.md
index 10d20d80c..f4fcb665e 100644
--- a/components/badge/index.zh-CN.md
+++ b/components/badge/index.zh-CN.md
@@ -10,14 +10,15 @@
```
-| 参数 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | number \| string \| slot | |
-| dot | 不展示数字,只有一个小红点 | boolean | false |
-| offset | 设置状态点的位置偏移,格式为 [x, y] | [number\|string, number\|string] | - |
-| overflowCount | 展示封顶的数字值 | number | 99 |
-| showZero | 当数值为 0 时,是否展示 Badge | boolean | false |
-| status | 设置 Badge 为状态点 | Enum{ 'success', 'processing, 'default', 'error', 'warning' } | '' |
-| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | string | '' |
-| numberStyle | 设置状态点的样式 | object | '' |
-| title | 设置鼠标放在状态点上时显示的文字 | string | `count` |
+| 参数 | 说明 | 类型 | 默认值 | 版本 |
+| --- | --- | --- | --- | --- |
+| color | 自定义小圆点的颜色 | string | - | 1.5.0 |
+| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | number \| string \| slot | | |
+| dot | 不展示数字,只有一个小红点 | boolean | false | |
+| offset | 设置状态点的位置偏移,格式为 [x, y] | [number\|string, number\|string] | - | |
+| overflowCount | 展示封顶的数字值 | number | 99 | |
+| showZero | 当数值为 0 时,是否展示 Badge | boolean | false | |
+| status | 设置 Badge 为状态点 | Enum{ 'success', 'processing, 'default', 'error', 'warning' } | '' | |
+| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | string | '' | |
+| numberStyle | 设置状态点的样式 | object | '' | |
+| title | 设置鼠标放在状态点上时显示的文字 | string | `count` | |