diff --git a/components/_util/colors.ts b/components/_util/colors.ts
new file mode 100644
index 0000000000..acac6caec6
--- /dev/null
+++ b/components/_util/colors.ts
@@ -0,0 +1,18 @@
+import { tuple } from './type';
+
+export const PresetColorTypes = tuple(
+ 'pink',
+ 'red',
+ 'yellow',
+ 'orange',
+ 'cyan',
+ 'green',
+ 'blue',
+ 'purple',
+ 'geekblue',
+ 'magenta',
+ 'volcano',
+ 'gold',
+ 'lime'
+);
+export type PresetColorType = (typeof PresetColorTypes)[number];
diff --git a/components/badge/__tests__/__snapshots__/demo.test.js.snap b/components/badge/__tests__/__snapshots__/demo.test.js.snap
index fbf8fc85f9..ed6f89e39c 100644
--- a/components/badge/__tests__/__snapshots__/demo.test.js.snap
+++ b/components/badge/__tests__/__snapshots__/demo.test.js.snap
@@ -475,6 +475,262 @@ exports[`renders ./components/badge/demo/change.md correctly 1`] = `
`;
+exports[`renders ./components/badge/demo/colorful.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`] = `
+ Presets:
+
+ {colors.map((color) => (
+
+
+
+ ))}
+
+ Custom:
+
+
+
+
+
+
+
+
+
+ ,
+ mountNode
+);
+````
+
+````css
+.ant-tag {
+ margin-bottom: 8px;
+}
+````
diff --git a/components/badge/index.en-US.md b/components/badge/index.en-US.md
index 84981843d4..a337cf256b 100644
--- a/components/badge/index.en-US.md
+++ b/components/badge/index.en-US.md
@@ -22,13 +22,14 @@ Badge normally appears in proximity to notifications or user avatars with eye-ca
```
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| count | Number to show in badge | ReactNode | |
-| dot | Whether to display a red dot instead of `count` | boolean | `false` |
-| offset | set offset of the badge dot, like`[x, y]` | `[number, number]` | - |
-| 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 | `''` |
-| title | Text to show when hovering over the badge | string | `count` |
+| Property | Description | Type | Default | Version |
+| -------- | ----------- | ---- | ------- | ------- |
+| color | Customize Badge dot color | string | - | 3.16.0 |
+| count | Number to show in badge | ReactNode | | |
+| dot | Whether to display a red dot instead of `count` | boolean | `false` | |
+| offset | set offset of the badge dot, like`[x, y]` | `[number, number]` | - | |
+| 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 | `''` | |
+| title | Text to show when hovering over the badge | string | `count` | |
diff --git a/components/badge/index.tsx b/components/badge/index.tsx
index 381bf72453..2c5060c924 100644
--- a/components/badge/index.tsx
+++ b/components/badge/index.tsx
@@ -3,6 +3,7 @@ import * as PropTypes from 'prop-types';
import Animate from 'rc-animate';
import classNames from 'classnames';
import ScrollNumber from './ScrollNumber';
+import { PresetColorTypes } from '../_util/colors';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
export { ScrollNumberProps } from './ScrollNumber';
@@ -20,11 +21,16 @@ export interface BadgeProps {
scrollNumberPrefixCls?: string;
className?: string;
status?: 'success' | 'processing' | 'default' | 'error' | 'warning';
+ color?: string;
text?: React.ReactNode;
offset?: [number | string, number | string];
title?: string;
}
+function isPresetColor(color?: string): boolean {
+ return (PresetColorTypes as any[]).indexOf(color) !== -1;
+}
+
export default class Badge extends React.Component {
static defaultProps = {
count: null,
@@ -41,22 +47,27 @@ export default class Badge extends React.Component {
};
getBadgeClassName(prefixCls: string) {
- const { className, status, children } = this.props;
+ const { className, children } = this.props;
return classNames(className, prefixCls, {
- [`${prefixCls}-status`]: !!status,
+ [`${prefixCls}-status`]: this.hasStatus(),
[`${prefixCls}-not-a-wrapper`]: !children,
}) as string;
}
+ hasStatus(): boolean {
+ 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 { dot } = this.props;
const isZero = this.isZero();
- return (dot && !isZero) || status;
+ return (dot && !isZero) || this.hasStatus();
}
isHidden() {
@@ -124,7 +135,7 @@ export default class Badge extends React.Component {
}
renderBadgeNumber(prefixCls: string, scrollNumberPrefixCls: string) {
- const { count, status } = this.props;
+ const { status, count } = this.props;
const displayCount = this.getDispayCount();
const isDot = this.isDot();
@@ -135,7 +146,7 @@ export default class Badge extends React.Component {
[`${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 : (
@@ -167,6 +178,7 @@ export default class Badge extends React.Component {
text,
offset,
title,
+ color,
...restProps
} = this.props;
@@ -177,17 +189,22 @@ export default class Badge extends React.Component {
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: React.CSSProperties = {};
+ if (color && !isPresetColor(color)) {
+ statusStyle.background = color;
+ }
//
- if (!children && status) {
+ if (!children && this.hasStatus()) {
const styleWithOffset = this.getStyleWithOffset();
const statusTextColor = styleWithOffset && styleWithOffset.color;
return (
-
+
{text}
diff --git a/components/badge/index.zh-CN.md b/components/badge/index.zh-CN.md
index 967b78b66c..18f70c7ed9 100644
--- a/components/badge/index.zh-CN.md
+++ b/components/badge/index.zh-CN.md
@@ -23,13 +23,14 @@ title: Badge
```
-| 参数 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | ReactNode | |
-| dot | 不展示数字,只有一个小红点 | boolean | false |
-| offset | 设置状态点的位置偏移,格式为 `[x, y]` | `[number, number]` | - |
-| overflowCount | 展示封顶的数字值 | number | 99 |
-| showZero | 当数值为 0 时,是否展示 Badge | boolean | false |
-| status | 设置 Badge 为状态点 | Enum{ 'success', 'processing, 'default', 'error', 'warning' } | '' |
-| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | string | '' |
-| title | 设置鼠标放在状态点上时显示的文字 | string | `count` |
+| 参数 | 说明 | 类型 | 默认值 | 版本 |
+| --- | --- | --- | --- | --- |
+| color | 自定义小圆点的颜色 | string | - | 3.16.0 |
+| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | ReactNode | | |
+| dot | 不展示数字,只有一个小红点 | boolean | false | |
+| offset | 设置状态点的位置偏移,格式为 `[x, y]` | `[number, number]` | - | |
+| overflowCount | 展示封顶的数字值 | number | 99 | |
+| showZero | 当数值为 0 时,是否展示 Badge | boolean | false | |
+| status | 设置 Badge 为状态点 | Enum{ 'success', 'processing, 'default', 'error', 'warning' } | '' | |
+| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | string | '' | |
+| title | 设置鼠标放在状态点上时显示的文字 | string | `count` | |
diff --git a/components/badge/style/index.less b/components/badge/style/index.less
index 73d1cd3592..aabac9b0d6 100644
--- a/components/badge/style/index.less
+++ b/components/badge/style/index.less
@@ -94,6 +94,18 @@
&-warning {
background-color: @warning-color;
}
+
+ // mixin to iterate over colors and create CSS class for each one
+ .make-color-classes(@i: length(@preset-colors)) when (@i > 0) {
+ .make-color-classes(@i - 1);
+ @color: extract(@preset-colors, @i);
+ @darkColor: '@{color}-6';
+ &-@{color} {
+ background: @@darkColor;
+ }
+ }
+ .make-color-classes();
+
&-text {
margin-left: 8px;
color: @text-color;
diff --git a/components/style/color/colors.less b/components/style/color/colors.less
index b489eed0cb..86c5697f64 100644
--- a/components/style/color/colors.less
+++ b/components/style/color/colors.less
@@ -144,3 +144,6 @@
@gold-8: color(~`colorPalette('@{gold-6}', 8) `);
@gold-9: color(~`colorPalette('@{gold-6}', 9) `);
@gold-10: color(~`colorPalette('@{gold-6}', 10) `);
+
+@preset-colors: pink, magenta, red, volcano, orange, yellow, gold, cyan, lime, green, blue, geekblue,
+ purple;
diff --git a/components/tag/index.tsx b/components/tag/index.tsx
index 74e36184f8..943085e568 100644
--- a/components/tag/index.tsx
+++ b/components/tag/index.tsx
@@ -6,6 +6,7 @@ import { polyfill } from 'react-lifecycles-compat';
import Icon from '../icon';
import CheckableTag from './CheckableTag';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
+import { PresetColorTypes } from '../_util/colors';
import Wave from '../_util/wave';
export { CheckableTagProps } from './CheckableTag';
@@ -29,6 +30,8 @@ interface InnterTagProps extends TagProps {
show: boolean;
}
+const PresetColorRegex = new RegExp(`^(${PresetColorTypes.join('|')})(-inverse)?$`);
+
const InnerTag = ({ show, ...restProps }: InnterTagProps) => {
const divProps = omit(restProps, ['onClose', 'afterClose', 'color', 'visible', 'closable']);
return ;
@@ -83,9 +86,7 @@ class Tag extends React.Component {
if (!color) {
return false;
}
- return /^(pink|red|yellow|orange|cyan|green|blue|purple|geekblue|magenta|volcano|gold|lime)(-inverse)?$/.test(
- color,
- );
+ return PresetColorRegex.test(color);
}
getTagStyle() {
diff --git a/components/tag/style/index.less b/components/tag/style/index.less
index aa588c6b0e..f6caf20d3f 100644
--- a/components/tag/style/index.less
+++ b/components/tag/style/index.less
@@ -98,13 +98,10 @@
display: none;
}
- @colors: pink, magenta, red, volcano, orange, yellow, gold, cyan, lime, green, blue, geekblue,
- purple;
-
// mixin to iterate over colors and create CSS class for each one
- .make-color-classes(@i: length(@colors)) when (@i > 0) {
+ .make-color-classes(@i: length(@preset-colors)) when (@i > 0) {
.make-color-classes(@i - 1);
- @color: extract(@colors, @i);
+ @color: extract(@preset-colors, @i);
@lightColor: '@{color}-1';
@lightBorderColor: '@{color}-3';
@darkColor: '@{color}-6';