fix: Badge count style when customize color (#31617)

* fix: Badge count style when customize color

close #31590
close #31591

* add demo for debug

* update badge demos

* create ribbon.test.tsx
This commit is contained in:
afc163 2021-08-02 12:22:30 +08:00 committed by GitHub
parent 416482bb87
commit 06dff86287
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 754 additions and 540 deletions

File diff suppressed because it is too large Load Diff

View File

@ -7,31 +7,64 @@ exports[`Badge render Badge status/color when contains children 1`] = `
> >
<a /> <a />
<sup <sup
class="ant-scroll-number ant-badge-dot ant-badge-status-success" class="ant-scroll-number ant-badge-count ant-badge-status-success"
data-show="true" data-show="true"
title="5" title="5"
/> >
<span
class="ant-scroll-number-only"
style="transition: none;"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span> </span>
<span <span
class="ant-badge ant-badge-status" class="ant-badge ant-badge-status"
> >
<a /> <a />
<sup <sup
class="ant-scroll-number ant-badge-dot ant-badge-status-blue" class="ant-scroll-number ant-badge-count ant-badge-status-blue"
data-show="true" data-show="true"
title="5" title="5"
/> >
<span
class="ant-scroll-number-only"
style="transition: none;"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span> </span>
<span <span
class="ant-badge ant-badge-status" class="ant-badge ant-badge-status"
> >
<a /> <a />
<sup <sup
class="ant-scroll-number ant-badge-dot" class="ant-scroll-number ant-badge-count"
data-show="true" data-show="true"
style="background: rgb(0, 136, 204);" style="background: rgb(0, 136, 204);"
title="5" title="5"
/> >
<span
class="ant-scroll-number-only"
style="transition: none;"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span> </span>
</div> </div>
`; `;
@ -547,20 +580,3 @@ exports[`Badge should support offset when count is a ReactNode 1`] = `
/> />
</span> </span>
`; `;
exports[`Ribbon rtl render component should be rendered correctly in RTL direction 1`] = `
<div
class="ant-ribbon-wrapper"
>
<div
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-rtl"
>
<span
class="ant-ribbon-text"
/>
<div
class="ant-ribbon-corner"
/>
</div>
</div>
`;

View File

@ -0,0 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Ribbon rtl render component should be rendered correctly in RTL direction 1`] = `
<div
class="ant-ribbon-wrapper"
>
<div
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-rtl"
>
<span
class="ant-ribbon-text"
/>
<div
class="ant-ribbon-corner"
/>
</div>
</div>
`;

View File

@ -128,6 +128,7 @@ describe('Badge', () => {
}); });
// https://github.com/ant-design/ant-design/issues/21331 // https://github.com/ant-design/ant-design/issues/21331
// https://github.com/ant-design/ant-design/issues/31590
it('render Badge status/color when contains children', () => { it('render Badge status/color when contains children', () => {
const wrapper = mount( const wrapper = mount(
<div> <div>
@ -143,6 +144,9 @@ describe('Badge', () => {
</div>, </div>,
); );
expect(wrapper.render()).toMatchSnapshot(); expect(wrapper.render()).toMatchSnapshot();
expect(wrapper.find(Badge).at(0).find('.ant-scroll-number-only-unit').text()).toBe('5');
expect(wrapper.find(Badge).at(1).find('.ant-scroll-number-only-unit').text()).toBe('5');
expect(wrapper.find(Badge).at(2).find('.ant-scroll-number-only-unit').text()).toBe('5');
}); });
it('Badge should work when status/color is empty string', () => { it('Badge should work when status/color is empty string', () => {
@ -156,72 +160,3 @@ describe('Badge', () => {
expect(wrapper.find('.ant-badge')).toHaveLength(2); expect(wrapper.find('.ant-badge')).toHaveLength(2);
}); });
}); });
describe('Ribbon', () => {
mountTest(Badge.Ribbon);
rtlTest(Badge.Ribbon);
describe('placement', () => {
it('works with `start` & `end` placement', () => {
const wrapperStart = mount(
<Badge.Ribbon placement="start">
<div />
</Badge.Ribbon>,
);
expect(wrapperStart.find('.ant-ribbon-placement-start').length).toEqual(1);
const wrapperEnd = mount(
<Badge.Ribbon placement="end">
<div />
</Badge.Ribbon>,
);
expect(wrapperEnd.find('.ant-ribbon-placement-end').length).toEqual(1);
});
});
describe('color', () => {
it('works with preset color', () => {
const wrapper = mount(
<Badge.Ribbon color="green">
<div />
</Badge.Ribbon>,
);
expect(wrapper.find('.ant-ribbon-color-green').length).toEqual(1);
});
it('works with custom color', () => {
const wrapperLeft = mount(
<Badge.Ribbon color="#888" placement="start">
<div />
</Badge.Ribbon>,
);
expect(wrapperLeft.find('.ant-ribbon').prop('style').background).toEqual('#888');
expect(wrapperLeft.find('.ant-ribbon-corner').prop('style').color).toEqual('#888');
const wrapperRight = mount(
<Badge.Ribbon color="#888" placement="end">
<div />
</Badge.Ribbon>,
);
expect(wrapperRight.find('.ant-ribbon').prop('style').background).toEqual('#888');
expect(wrapperRight.find('.ant-ribbon-corner').prop('style').color).toEqual('#888');
});
});
describe('text', () => {
it('works with string', () => {
const wrapper = mount(
<Badge.Ribbon text="cool">
<div />
</Badge.Ribbon>,
);
expect(wrapper.find('.ant-ribbon').text()).toEqual('cool');
});
it('works with element', () => {
const wrapper = mount(
<Badge.Ribbon text={<span className="cool" />}>
<div />
</Badge.Ribbon>,
);
expect(wrapper.find('.cool').length).toEqual(1);
});
});
});

View File

@ -0,0 +1,74 @@
import React from 'react';
import { mount } from 'enzyme';
import Badge from '../index';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
describe('Ribbon', () => {
mountTest(Badge.Ribbon);
rtlTest(Badge.Ribbon);
describe('placement', () => {
it('works with `start` & `end` placement', () => {
const wrapperStart = mount(
<Badge.Ribbon placement="start">
<div />
</Badge.Ribbon>,
);
expect(wrapperStart.find('.ant-ribbon-placement-start').length).toEqual(1);
const wrapperEnd = mount(
<Badge.Ribbon placement="end">
<div />
</Badge.Ribbon>,
);
expect(wrapperEnd.find('.ant-ribbon-placement-end').length).toEqual(1);
});
});
describe('color', () => {
it('works with preset color', () => {
const wrapper = mount(
<Badge.Ribbon color="green">
<div />
</Badge.Ribbon>,
);
expect(wrapper.find('.ant-ribbon-color-green').length).toEqual(1);
});
it('works with custom color', () => {
const wrapperLeft = mount(
<Badge.Ribbon color="#888" placement="start">
<div />
</Badge.Ribbon>,
);
expect(wrapperLeft.find('.ant-ribbon').prop('style')?.background).toEqual('#888');
expect(wrapperLeft.find('.ant-ribbon-corner').prop('style')?.color).toEqual('#888');
const wrapperRight = mount(
<Badge.Ribbon color="#888" placement="end">
<div />
</Badge.Ribbon>,
);
expect(wrapperRight.find('.ant-ribbon').prop('style')?.background).toEqual('#888');
expect(wrapperRight.find('.ant-ribbon-corner').prop('style')?.color).toEqual('#888');
});
});
describe('text', () => {
it('works with string', () => {
const wrapper = mount(
<Badge.Ribbon text="cool">
<div />
</Badge.Ribbon>,
);
expect(wrapper.find('.ant-ribbon').text()).toEqual('cool');
});
it('works with element', () => {
const wrapper = mount(
<Badge.Ribbon text={<span className="cool" />}>
<div />
</Badge.Ribbon>,
);
expect(wrapper.find('.cool').length).toEqual(1);
});
});
});

View File

@ -14,21 +14,21 @@ title:
Simplest Usage. Badge will be hidden when `count` is `0`, but we can use `showZero` to show it. Simplest Usage. Badge will be hidden when `count` is `0`, but we can use `showZero` to show it.
```jsx ```jsx
import { Badge } from 'antd'; import { Badge, Avatar } from 'antd';
import { ClockCircleOutlined } from '@ant-design/icons'; import { ClockCircleOutlined } from '@ant-design/icons';
ReactDOM.render( ReactDOM.render(
<div> <>
<Badge count={5}> <Badge count={5}>
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
<Badge count={0} showZero> <Badge count={0} showZero>
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
<Badge count={<ClockCircleOutlined style={{ color: '#f5222d' }} />}> <Badge count={<ClockCircleOutlined style={{ color: '#f5222d' }} />}>
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
</div>, </>,
mountNode, mountNode,
); );
``` ```
@ -41,15 +41,4 @@ ReactDOM.render(
margin-right: 0; margin-right: 0;
margin-left: 20px; margin-left: 20px;
} }
.head-example {
width: 42px;
height: 42px;
border-radius: 2px;
background: #eee;
display: inline-block;
vertical-align: middle;
}
[data-theme="dark"] .head-example {
background: rgba(255,255,255,.12);
}
</style> </style>

View File

@ -14,7 +14,7 @@ title:
The count will be animated as it changes. The count will be animated as it changes.
```jsx ```jsx
import { Badge, Button, Switch } from 'antd'; import { Badge, Button, Switch, Divider, Avatar } from 'antd';
import { MinusOutlined, PlusOutlined, QuestionOutlined } from '@ant-design/icons'; import { MinusOutlined, PlusOutlined, QuestionOutlined } from '@ant-design/icons';
const ButtonGroup = Button.Group; const ButtonGroup = Button.Group;
@ -49,30 +49,27 @@ class Demo extends React.Component {
render() { render() {
return ( return (
<div> <>
<div> <Badge count={this.state.count}>
<Badge count={this.state.count}> <Avatar shape="square" size="large" />
<a href="#" className="head-example" /> </Badge>
</Badge> <ButtonGroup>
<ButtonGroup> <Button onClick={this.decline}>
<Button onClick={this.decline}> <MinusOutlined />
<MinusOutlined /> </Button>
</Button> <Button onClick={this.increase}>
<Button onClick={this.increase}> <PlusOutlined />
<PlusOutlined /> </Button>
</Button> <Button onClick={this.random}>
<Button onClick={this.random}> <QuestionOutlined />
<QuestionOutlined /> </Button>
</Button> </ButtonGroup>
</ButtonGroup> <Divider />
</div> <Badge dot={this.state.show}>
<div style={{ marginTop: 10 }}> <Avatar shape="square" size="large" />
<Badge dot={this.state.show}> </Badge>
<a href="#" className="head-example" /> <Switch onChange={this.onChange} checked={this.state.show} />
</Badge> </>
<Switch onChange={this.onChange} checked={this.state.show} />
</div>
</div>
); );
} }
} }

View File

@ -1,5 +1,5 @@
--- ---
order: 8 order: 9
title: title:
zh-CN: 多彩徽标 zh-CN: 多彩徽标
en-US: Colorful Badge en-US: Colorful Badge
@ -43,7 +43,7 @@ ReactDOM.render(
))} ))}
</div> </div>
<Divider orientation="left">Custom</Divider> <Divider orientation="left">Custom</Divider>
<div> <>
<Badge color="#f50" text="#f50" /> <Badge color="#f50" text="#f50" />
<br /> <br />
<Badge color="#2db7f5" text="#2db7f5" /> <Badge color="#2db7f5" text="#2db7f5" />
@ -51,7 +51,7 @@ ReactDOM.render(
<Badge color="#87d068" text="#87d068" /> <Badge color="#87d068" text="#87d068" />
<br /> <br />
<Badge color="#108ee9" text="#108ee9" /> <Badge color="#108ee9" text="#108ee9" />
</div> </>
</>, </>,
mountNode, mountNode,
); );

View File

@ -18,26 +18,14 @@ import { Badge } from 'antd';
import { NotificationOutlined } from '@ant-design/icons'; import { NotificationOutlined } from '@ant-design/icons';
ReactDOM.render( ReactDOM.render(
<div> <>
<Badge dot> <Badge dot>
<NotificationOutlined /> <NotificationOutlined style={{ fontSize: 16 }} />
</Badge>
<Badge count={0} dot>
<NotificationOutlined />
</Badge> </Badge>
<Badge dot> <Badge dot>
<a href="#">Link something</a> <a href="#">Link something</a>
</Badge> </Badge>
</div>, </>,
mountNode, mountNode,
); );
``` ```
<style>
.anticon-notification {
width: 16px;
height: 16px;
line-height: 16px;
font-size: 16px;
}
</style>

View File

@ -1,5 +1,5 @@
--- ---
order: 3 order: 5
title: title:
zh-CN: 可点击 zh-CN: 可点击
en-US: Clickable en-US: Clickable
@ -14,12 +14,12 @@ title:
The badge can be wrapped with `a` tag to make it linkable. The badge can be wrapped with `a` tag to make it linkable.
```jsx ```jsx
import { Badge } from 'antd'; import { Badge, Avatar } from 'antd';
ReactDOM.render( ReactDOM.render(
<a href="#"> <a href="#">
<Badge count={5}> <Badge count={5}>
<span className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
</a>, </a>,
mountNode, mountNode,

View File

@ -0,0 +1,49 @@
---
order: 99
title:
zh-CN: 各种混用的情况
en-US: Mixed usage
debug: true
---
## zh-CN
测试 `count` `stauts` `color` `dot` 共用的情况。
## en-US
Using `count/dot` with custom `stauts/color`.
```jsx
import { Badge, Avatar } from 'antd';
ReactDOM.render(
<>
<Badge count={5} status="success">
<Avatar shape="square" size="large" />
</Badge>
<Badge count={5} status="warning">
<Avatar shape="square" size="large" />
</Badge>
<Badge count={5} color="blue">
<Avatar shape="square" size="large" />
</Badge>
<Badge count={5} color="#fa541c">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot status="success">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot status="warning">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot color="blue">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot color="#fa541c">
<Avatar shape="square" size="large" />
</Badge>
</>,
mountNode,
);
```

View File

@ -24,15 +24,9 @@ const Demo = () => {
return ( return (
<Space> <Space>
<Switch <Switch checked={show} onChange={() => setShow(!show)} />
checked={show}
onChange={() => {
setShow(!show);
}}
/>
<Badge count={show ? 25 : 0} /> <Badge count={show ? 25 : 0} />
<Badge count={show ? <ClockCircleOutlined style={{ color: '#f5222d' }} /> : 0} /> <Badge count={show ? <ClockCircleOutlined style={{ color: '#f5222d' }} /> : 0} />
<Badge count={show ? 4 : 0} className="site-badge-count-4" />
<Badge <Badge
className="site-badge-count-109" className="site-badge-count-109"
count={show ? 109 : 0} count={show ? 109 : 0}
@ -44,18 +38,3 @@ const Demo = () => {
ReactDOM.render(<Demo />, mountNode); ReactDOM.render(<Demo />, mountNode);
``` ```
```css
.site-badge-count-4 .ant-badge-count {
color: #999;
background-color: #fff;
box-shadow: 0 0 0 1px #d9d9d9 inset;
}
```
<style>
[data-theme="dark"] .site-badge-count-4 .ant-badge-count {
background-color: #141414;
box-shadow: 0 0 0 1px #434343 inset;
}
</style>

View File

@ -1,5 +1,5 @@
--- ---
order: 5 order: 6
title: title:
zh-CN: 自定义位置偏移 zh-CN: 自定义位置偏移
en-US: Offset en-US: Offset
@ -14,14 +14,12 @@ title:
Set offset of the badge dot, the format is `[left, top]`, which represents the offset of the status dot from the left and top of the default position. Set offset of the badge dot, the format is `[left, top]`, which represents the offset of the status dot from the left and top of the default position.
```jsx ```jsx
import { Badge } from 'antd'; import { Badge, Avatar } from 'antd';
ReactDOM.render( ReactDOM.render(
<> <Badge count={5} offset={[10, 10]}>
<Badge count={5} offset={[10, 10]}> <Avatar shape="square" size="large" />
<a href="#" className="head-example" /> </Badge>,
</Badge>
</>,
mountNode, mountNode,
); );
``` ```

View File

@ -14,23 +14,23 @@ title:
`${overflowCount}+` is displayed when count is larger than `overflowCount`. The default value of `overflowCount` is `99`. `${overflowCount}+` is displayed when count is larger than `overflowCount`. The default value of `overflowCount` is `99`.
```jsx ```jsx
import { Badge } from 'antd'; import { Badge, Avatar } from 'antd';
ReactDOM.render( ReactDOM.render(
<div> <>
<Badge count={99}> <Badge count={99}>
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
<Badge count={100}> <Badge count={100}>
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
<Badge count={99} overflowCount={10}> <Badge count={99} overflowCount={10}>
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
<Badge count={1000} overflowCount={999}> <Badge count={1000} overflowCount={999}>
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
</div>, </>,
mountNode, mountNode,
); );
``` ```

View File

@ -1,5 +1,5 @@
--- ---
order: 15 order: 10
title: title:
zh-CN: 缎带 zh-CN: 缎带
en-US: Ribbon en-US: Ribbon

View File

@ -1,5 +1,5 @@
--- ---
order: 9 order: 7
title: title:
zh-CN: 大小 zh-CN: 大小
en-US: Size en-US: Size
@ -14,15 +14,15 @@ title:
Set size of numeral Badge. Set size of numeral Badge.
```jsx ```jsx
import { Badge } from 'antd'; import { Badge, Avatar } from 'antd';
ReactDOM.render( ReactDOM.render(
<> <>
<Badge size="default" count={5}> <Badge size="default" count={5}>
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
<Badge size="small" count={5}> <Badge size="small" count={5}>
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
</>, </>,
mountNode, mountNode,

View File

@ -1,5 +1,5 @@
--- ---
order: 6 order: 8
title: title:
zh-CN: 状态点 zh-CN: 状态点
en-US: Status en-US: Status
@ -17,7 +17,7 @@ Standalone badge with status.
import { Badge } from 'antd'; import { Badge } from 'antd';
ReactDOM.render( ReactDOM.render(
<div> <>
<Badge status="success" /> <Badge status="success" />
<Badge status="error" /> <Badge status="error" />
<Badge status="default" /> <Badge status="default" />
@ -33,7 +33,7 @@ ReactDOM.render(
<Badge status="processing" text="Processing" /> <Badge status="processing" text="Processing" />
<br /> <br />
<Badge status="warning" text="Warning" /> <Badge status="warning" text="Warning" />
</div>, </>,
mountNode, mountNode,
); );
``` ```

View File

@ -15,39 +15,17 @@ debug: true
The badge will display `title` when hovered over, instead of `count`. The badge will display `title` when hovered over, instead of `count`.
```jsx ```jsx
import { Badge } from 'antd'; import { Badge, Avatar } from 'antd';
ReactDOM.render( ReactDOM.render(
<div> <>
<Badge count={5} title="Custom hover text"> <Badge count={5} title="Custom hover text">
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
<Badge count={-5} title="Negative"> <Badge count={-5} title="Negative">
<a href="#" className="head-example" /> <Avatar shape="square" size="large" />
</Badge> </Badge>
</div>, </>,
mountNode, mountNode,
); );
``` ```
<style>
.ant-badge:not(.ant-badge-not-a-wrapper) {
margin-right: 20px;
}
.ant-badge.ant-badge-rtl:not(.ant-badge-not-a-wrapper) {
margin-right: 0;
margin-left: 20px;
}
.head-example {
width: 42px;
height: 42px;
border-radius: 2px;
background: #eee;
display: inline-block;
}
[data-theme="dark"] .head-example {
background: rgba(255,255,255,.12);
}
</style>

View File

@ -58,16 +58,16 @@ const Badge: CompoundedComponent = ({
const prefixCls = getPrefixCls('badge', customizePrefixCls); const prefixCls = getPrefixCls('badge', customizePrefixCls);
// ================================ Misc ================================ // ================================ Misc ================================
const numberedDisplayCount = ((count as number) > (overflowCount as number) const numberedDisplayCount = (
? `${overflowCount}+` (count as number) > (overflowCount as number) ? `${overflowCount}+` : count
: count) as string | number | null; ) as string | number | null;
const hasStatus = const hasStatus =
(status !== null && status !== undefined) || (color !== null && color !== undefined); (status !== null && status !== undefined) || (color !== null && color !== undefined);
const isZero = numberedDisplayCount === '0' || numberedDisplayCount === 0; const isZero = numberedDisplayCount === '0' || numberedDisplayCount === 0;
const showAsDot = (dot && !isZero) || hasStatus; const showAsDot = dot && !isZero;
const mergedCount = showAsDot ? '' : numberedDisplayCount; const mergedCount = showAsDot ? '' : numberedDisplayCount;