Badge support customize color (#15764)

* popout

* update snapshot

* update doc

* update def
This commit is contained in:
zombieJ 2019-03-31 20:21:20 +08:00 committed by GitHub
parent aebb781000
commit 75cd91a966
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 394 additions and 37 deletions

View File

@ -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];

View File

@ -475,6 +475,262 @@ exports[`renders ./components/badge/demo/change.md correctly 1`] = `
</div>
`;
exports[`renders ./components/badge/demo/colorful.md correctly 1`] = `
<div>
<h4
style="margin-bottom:16px"
>
Presets:
</h4>
<div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-pink"
/>
<span
class="ant-badge-status-text"
>
pink
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-red"
/>
<span
class="ant-badge-status-text"
>
red
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-yellow"
/>
<span
class="ant-badge-status-text"
>
yellow
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-orange"
/>
<span
class="ant-badge-status-text"
>
orange
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-cyan"
/>
<span
class="ant-badge-status-text"
>
cyan
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-green"
/>
<span
class="ant-badge-status-text"
>
green
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-blue"
/>
<span
class="ant-badge-status-text"
>
blue
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-purple"
/>
<span
class="ant-badge-status-text"
>
purple
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-geekblue"
/>
<span
class="ant-badge-status-text"
>
geekblue
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-magenta"
/>
<span
class="ant-badge-status-text"
>
magenta
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-volcano"
/>
<span
class="ant-badge-status-text"
>
volcano
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-gold"
/>
<span
class="ant-badge-status-text"
>
gold
</span>
</span>
</div>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot ant-badge-status-lime"
/>
<span
class="ant-badge-status-text"
>
lime
</span>
</span>
</div>
</div>
<h4
style="margin:16px 0"
>
Custom:
</h4>
<div>
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot"
style="background:#f50"
/>
<span
class="ant-badge-status-text"
>
#f50
</span>
</span>
<br />
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot"
style="background:#2db7f5"
/>
<span
class="ant-badge-status-text"
>
#2db7f5
</span>
</span>
<br />
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot"
style="background:#87d068"
/>
<span
class="ant-badge-status-text"
>
#87d068
</span>
</span>
<br />
<span
class="ant-badge ant-badge-status ant-badge-not-a-wrapper"
>
<span
class="ant-badge-status-dot"
style="background:#108ee9"
/>
<span
class="ant-badge-status-text"
>
#108ee9
</span>
</span>
</div>
</div>
`;
exports[`renders ./components/badge/demo/dot.md correctly 1`] = `
<div>
<span

View File

@ -0,0 +1,51 @@
---
order: 8
title:
zh-CN: 多彩徽标
en-US: Colorful Badge
---
## zh-CN
3.16.0 后新增。我们添加了多种预设色彩的徽标样式,用作不同场景使用。如果预设值不能满足你的需求,可以设置为具体的色值。
## en-US
New feature after 3.16.0. We preset a series of colorful Badge style for different situation usage.
And you can always set it to a hex color string for custom color.
````jsx
import { Badge } from 'antd';
const colors = ['pink', 'red', 'yellow', 'orange', 'cyan', 'green', 'blue', 'purple', 'geekblue', 'magenta', 'volcano', 'gold', 'lime'];
ReactDOM.render(
<div>
<h4 style={{ marginBottom: 16 }}>Presets:</h4>
<div>
{colors.map((color) => (
<div key={color}>
<Badge color={color} text={color} />
</div>
))}
</div>
<h4 style={{ margin: '16px 0' }}>Custom:</h4>
<div>
<Badge color="#f50" text="#f50" />
<br />
<Badge color="#2db7f5" text="#2db7f5" />
<br />
<Badge color="#87d068" text="#87d068" />
<br />
<Badge color="#108ee9" text="#108ee9" />
</div>
</div>,
mountNode
);
````
````css
.ant-tag {
margin-bottom: 8px;
}
````

View File

@ -22,13 +22,14 @@ Badge normally appears in proximity to notifications or user avatars with eye-ca
<Badge count={5} />
```
| 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` | |

View File

@ -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<BadgeProps, any> {
static defaultProps = {
count: null,
@ -41,22 +47,27 @@ export default class Badge extends React.Component<BadgeProps, any> {
};
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<BadgeProps, any> {
}
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<BadgeProps, any> {
[`${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<BadgeProps, any> {
text,
offset,
title,
color,
...restProps
} = this.props;
@ -177,17 +189,22 @@ export default class Badge extends React.Component<BadgeProps, any> {
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;
}
// <Badge status="success" />
if (!children && status) {
if (!children && this.hasStatus()) {
const styleWithOffset = this.getStyleWithOffset();
const statusTextColor = styleWithOffset && styleWithOffset.color;
return (
<span {...restProps} className={this.getBadgeClassName(prefixCls)} style={styleWithOffset}>
<span className={statusCls} />
<span className={statusCls} style={statusStyle} />
<span style={{ color: statusTextColor }} className={`${prefixCls}-status-text`}>
{text}
</span>

View File

@ -23,13 +23,14 @@ title: Badge
<Badge count={5} />
```
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| 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` | |

View File

@ -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;

View File

@ -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;

View File

@ -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 <div {...divProps} />;
@ -83,9 +86,7 @@ class Tag extends React.Component<TagProps, TagState> {
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() {

View File

@ -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';