feat: Add action in Alert and replace with flexbox layout (#25892)

* feat: Add action in Alert and replace with flexbox layout

* update

* update test

* doc

* Revert "update"

This reverts commit aef6e135a757341becdb01082238d48f7648ec5e.

* Update index.less

* Update index.less

* update test

* Update index.test.tsx.snap

* @alert-closable-padding-right

* Update index.less

* correct top of icon

* correct top of close icon

* fix @alert-closable-padding-right

* update

* doc

* Update components/alert/demo/action.md

Co-authored-by: 偏右 <afc163@gmail.com>

* Remove duplicate css

* Simplify styles of close-icon

* font size of close icon

* update test

* update test

* Remove unused less var

Co-authored-by: 偏右 <afc163@gmail.com>
This commit is contained in:
jesse 2020-11-30 11:04:56 +08:00 committed by GitHub
parent 35ee97dad4
commit 4b3aa350b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1745 additions and 1096 deletions

File diff suppressed because it is too large Load Diff

View File

@ -6,20 +6,101 @@ exports[`Alert ErrorBoundary 1`] = `
data-show="true"
role="alert"
>
<span
class="ant-alert-message"
<div
class="ant-alert-content"
>
ReferenceError: NotExisted is not defined
</span>
<span
class="ant-alert-description"
>
<pre>
in ThrowError
<div
class="ant-alert-message"
>
ReferenceError: NotExisted is not defined
</div>
<div
class="ant-alert-description"
>
<pre>
in ThrowError
in ErrorBoundary (created by WrapperComponent)
in WrapperComponent
</pre>
</pre>
</div>
</div>
</div>
`;
exports[`Alert action of Alert custom action 1`] = `
<div
class="ant-alert ant-alert-success"
data-show="true"
role="alert"
>
<span
aria-label="check-circle"
class="anticon anticon-check-circle ant-alert-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="check-circle"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"
/>
</svg>
</span>
<div
class="ant-alert-content"
>
<div
class="ant-alert-message"
>
Success Tips
</div>
<div
class="ant-alert-description"
/>
</div>
<div
class="ant-alert-action"
>
<button
class="ant-btn ant-btn-text ant-btn-sm"
type="button"
>
<span>
UNDO
</span>
</button>
</div>
<button
class="ant-alert-close-icon"
tabindex="0"
type="button"
>
<span
aria-label="close"
class="anticon anticon-close"
role="img"
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
/>
</svg>
</span>
</button>
</div>
`;
@ -34,14 +115,18 @@ exports[`Alert could accept none react element icon 1`] = `
>
icon
</span>
<span
class="ant-alert-message"
<div
class="ant-alert-content"
>
Success Tips
</span>
<span
class="ant-alert-description"
/>
<div
class="ant-alert-message"
>
Success Tips
</div>
<div
class="ant-alert-description"
/>
</div>
</div>
`;
@ -51,11 +136,15 @@ exports[`Alert rtl render component should be rendered correctly in RTL directio
data-show="true"
role="alert"
>
<span
class="ant-alert-message"
/>
<span
class="ant-alert-description"
/>
<div
class="ant-alert-content"
>
<div
class="ant-alert-message"
/>
<div
class="ant-alert-description"
/>
</div>
</div>
`;

View File

@ -1,6 +1,7 @@
import React from 'react';
import { mount } from 'enzyme';
import { mount, render } from 'enzyme';
import Alert from '..';
import Button from '../../button';
import Tooltip from '../../tooltip';
import Popconfirm from '../../popconfirm';
import rtlTest from '../../../tests/shared/rtlTest';
@ -34,6 +35,25 @@ describe('Alert', () => {
expect(onClose).toHaveBeenCalled();
});
describe('action of Alert', () => {
it('custom action', () => {
const wrapper = render(
<Alert
message="Success Tips"
type="success"
showIcon
action={
<Button size="small" type="text">
UNDO
</Button>
}
closable
/>,
);
expect(wrapper).toMatchSnapshot();
});
});
describe('data and aria props', () => {
it('sets data attributes on input', () => {
const wrapper = mount(<Alert data-test="test-id" data-id="12345" message={null} />);

View File

@ -0,0 +1,81 @@
---
order: 13
title:
zh-CN: 操作
en-US: Custom action
---
## zh-CN
可以在右上角自定义操作项。
## en-US
Custom action.
```tsx
import React from 'react';
import { Alert, Button, Space } from 'antd';
ReactDOM.render(
<>
<Alert
message="Success Tips"
type="success"
showIcon
action={
<Button size="small" type="text">
UNDO
</Button>
}
closable
/>
<Alert
message="Error Text"
showIcon
description="Error Description Error Description Error Description Error Description"
type="error"
action={
<Button size="small" danger>
Detail
</Button>
}
/>
<Alert
message="Warning Text"
type="warning"
action={
<Space>
<Button size="small" type="ghost">
Done
</Button>
</Space>
}
closable
/>
<Alert
message="Info Text"
description="Info Description Info Description Info Description Info Description"
type="info"
action={
<Space direction="vertical">
<Button size="small" type="primary">
Accept
</Button>
<Button size="small" danger type="ghost">
Decline
</Button>
</Space>
}
closable
/>
</>,
mountNode,
);
```
<style>
.code-box-demo .ant-alert {
margin-bottom: 16px;
}
</style>

View File

@ -14,18 +14,19 @@ Alert component for feedback.
## API
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| afterClose | Called when close animation is finished | () => void | - |
| banner | Whether to show as banner | boolean | false |
| closable | Whether Alert can be closed | boolean | - |
| closeText | Close text to show | ReactNode | - |
| description | Additional content of Alert | ReactNode | - |
| icon | Custom icon, effective when `showIcon` is true | ReactNode | - |
| message | Content of Alert | ReactNode | - |
| showIcon | Whether to show icon | boolean | false, in `banner` mode default is true |
| type | Type of Alert styles, options: `success`, `info`, `warning`, `error` | string | `info`, in `banner` mode default is `warning` |
| onClose | Callback when Alert is closed | (e: MouseEvent) => void | - |
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| action | The action of Alert | ReactNode | - | 4.9.0 |
| afterClose | Called when close animation is finished | () => void | - | |
| banner | Whether to show as banner | boolean | false | |
| closable | Whether Alert can be closed | boolean | - | |
| closeText | Close text to show | ReactNode | - | |
| description | Additional content of Alert | ReactNode | - | |
| icon | Custom icon, effective when `showIcon` is true | ReactNode | - | |
| message | Content of Alert | ReactNode | - | |
| showIcon | Whether to show icon | boolean | false, in `banner` mode default is true | |
| type | Type of Alert styles, options: `success`, `info`, `warning`, `error` | string | `info`, in `banner` mode default is `warning` | |
| onClose | Callback when Alert is closed | (e: MouseEvent) => void | - | |
### Alert.ErrorBoundary

12
components/alert/index.tsx Executable file → Normal file
View File

@ -42,6 +42,7 @@ export interface AlertProps {
className?: string;
banner?: boolean;
icon?: React.ReactNode;
action?: React.ReactNode;
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
onClick?: React.MouseEventHandler<HTMLDivElement>;
@ -79,6 +80,7 @@ const Alert: AlertInterface = ({
showIcon,
closable,
closeText,
action,
...props
}) => {
const [closed, setClosed] = React.useState(false);
@ -146,7 +148,6 @@ const Alert: AlertInterface = ({
[`${prefixCls}-with-description`]: !!description,
[`${prefixCls}-no-icon`]: !isShowIcon,
[`${prefixCls}-banner`]: !!banner,
[`${prefixCls}-closable`]: isClosable,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
@ -178,8 +179,13 @@ const Alert: AlertInterface = ({
{...dataOrAriaProps}
>
{isShowIcon ? renderIconNode() : null}
<span className={`${prefixCls}-message`}>{message}</span>
<span className={`${prefixCls}-description`}>{description}</span>
<div className={`${prefixCls}-content`}>
<div className={`${prefixCls}-message`}>{message}</div>
<div className={`${prefixCls}-description`}>{description}</div>
</div>
{action ? <div className={`${prefixCls}-action`}>{action}</div> : null}
{renderCloseIcon()}
</div>
)}

View File

@ -15,18 +15,19 @@ cover: https://gw.alipayobjects.com/zos/alicdn/8emPa3fjl/Alert.svg
## API
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| afterClose | 关闭动画结束后触发的回调函数 | () => void | - |
| banner | 是否用作顶部公告 | boolean | false |
| closable | 默认不显示关闭按钮 | boolean | - |
| closeText | 自定义关闭按钮 | ReactNode | - |
| description | 警告提示的辅助性文字介绍 | ReactNode | - |
| icon | 自定义图标,`showIcon` 为 true 时有效 | ReactNode | - |
| message | 警告提示内容 | ReactNode | - |
| showIcon | 是否显示辅助图标 | boolean | false`banner` 模式下默认值为 true |
| type | 指定警告提示的样式,有四种选择 `success`、`info`、`warning`、`error` | string | `info``banner` 模式下默认值为 `warning` |
| onClose | 关闭时触发的回调函数 | (e: MouseEvent) => void | - |
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| action | 自定义操作项 | ReactNode | - | 4.9.0 |
| afterClose | 关闭动画结束后触发的回调函数 | () => void | - | |
| banner | 是否用作顶部公告 | boolean | false | |
| closable | 默认不显示关闭按钮 | boolean | - | |
| closeText | 自定义关闭按钮 | ReactNode | - | |
| description | 警告提示的辅助性文字介绍 | ReactNode | - | |
| icon | 自定义图标,`showIcon` 为 true 时有效 | ReactNode | - | |
| message | 警告提示内容 | ReactNode | - | |
| showIcon | 是否显示辅助图标 | boolean | false`banner` 模式下默认值为 true | |
| type | 指定警告提示的样式,有四种选择 `success`、`info`、`warning`、`error` | string | `info``banner` 模式下默认值为 `warning` | |
| onClose | 关闭时触发的回调函数 | (e: MouseEvent) => void | - | |
### Alert.ErrorBoundary

View File

@ -7,26 +7,26 @@
.reset-component;
position: relative;
padding: 8px 15px 8px 37px;
display: flex;
align-items: flex-start;
padding: 8px 15px 8px 16px;
word-wrap: break-word;
border-radius: @border-radius-base;
&&-no-icon {
padding: @alert-no-icon-padding-vertical 15px;
.@{alert-prefix-cls}-close-icon {
top: @alert-no-icon-padding-vertical + @font-size-base * @line-height-base / 2 -
@font-size-base / 2;
}
}
&&-closable {
padding-right: 30px;
&-content {
flex: 1;
min-width: 0;
}
&-icon {
position: absolute;
top: @alert-icon-top;
left: 16px;
position: relative;
top: @alert-icon-top - 8;
height: @font-size-base * @line-height-base;
margin-right: 37px - 16 - @font-size-base;
}
&-description {
@ -73,10 +73,17 @@
}
}
&-action {
margin-left: @margin-xs;
.@{alert-prefix-cls}-closable & {
margin-right: @margin-xs;
}
}
&-close-icon {
position: absolute;
top: 8px + @font-size-base * @line-height-base / 2 - @font-size-base / 2;
right: @padding-md;
position: relative;
top: @font-size-base * @line-height-base / 2 - @font-size-sm / 2;
margin-left: @margin-xs;
padding: 0;
overflow: hidden;
font-size: @font-size-sm;
@ -116,17 +123,13 @@
}
&-with-description &-icon {
position: absolute;
top: @alert-with-description-icon-top;
left: @alert-with-description-icon-size;
top: 0;
margin-right: @alert-with-description-padding-vertical;
font-size: @alert-with-description-icon-size;
}
&-with-description &-close-icon {
position: absolute;
top: @padding-md;
right: @padding-md;
font-size: @font-size-base;
top: 0;
cursor: pointer;
}

View File

@ -4205,14 +4205,18 @@ Array [
data-show="true"
role="alert"
>
<span
class="ant-alert-message"
<div
class="ant-alert-content"
>
You selected date: 2017-01-25
</span>
<span
class="ant-alert-description"
/>
<div
class="ant-alert-message"
>
You selected date: 2017-01-25
</div>
<div
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-picker-calendar ant-picker-calendar-full"

View File

@ -6,14 +6,18 @@ exports[`ConfigProvider components Alert configProvider 1`] = `
data-show="true"
role="alert"
>
<span
class="config-alert-message"
<div
class="config-alert-content"
>
Bamboo is Little Light
</span>
<span
class="config-alert-description"
/>
<div
class="config-alert-message"
>
Bamboo is Little Light
</div>
<div
class="config-alert-description"
/>
</div>
</div>
`;
@ -23,14 +27,18 @@ exports[`ConfigProvider components Alert configProvider componentSize large 1`]
data-show="true"
role="alert"
>
<span
class="config-alert-message"
<div
class="config-alert-content"
>
Bamboo is Little Light
</span>
<span
class="config-alert-description"
/>
<div
class="config-alert-message"
>
Bamboo is Little Light
</div>
<div
class="config-alert-description"
/>
</div>
</div>
`;
@ -40,14 +48,18 @@ exports[`ConfigProvider components Alert configProvider componentSize middle 1`]
data-show="true"
role="alert"
>
<span
class="config-alert-message"
<div
class="config-alert-content"
>
Bamboo is Little Light
</span>
<span
class="config-alert-description"
/>
<div
class="config-alert-message"
>
Bamboo is Little Light
</div>
<div
class="config-alert-description"
/>
</div>
</div>
`;
@ -57,14 +69,18 @@ exports[`ConfigProvider components Alert configProvider virtual and dropdownMatc
data-show="true"
role="alert"
>
<span
class="ant-alert-message"
<div
class="ant-alert-content"
>
Bamboo is Little Light
</span>
<span
class="ant-alert-description"
/>
<div
class="ant-alert-message"
>
Bamboo is Little Light
</div>
<div
class="ant-alert-description"
/>
</div>
</div>
`;
@ -74,14 +90,18 @@ exports[`ConfigProvider components Alert normal 1`] = `
data-show="true"
role="alert"
>
<span
class="ant-alert-message"
<div
class="ant-alert-content"
>
Bamboo is Little Light
</span>
<span
class="ant-alert-description"
/>
<div
class="ant-alert-message"
>
Bamboo is Little Light
</div>
<div
class="ant-alert-description"
/>
</div>
</div>
`;
@ -91,14 +111,18 @@ exports[`ConfigProvider components Alert prefixCls 1`] = `
data-show="true"
role="alert"
>
<span
class="prefix-Alert-message"
<div
class="prefix-Alert-content"
>
Bamboo is Little Light
</span>
<span
class="prefix-Alert-description"
/>
<div
class="prefix-Alert-message"
>
Bamboo is Little Light
</div>
<div
class="prefix-Alert-description"
/>
</div>
</div>
`;

View File

@ -63,16 +63,20 @@ exports[`renders ./components/spin/demo/delayAndDebounce.md correctly 1`] = `
data-show="true"
role="alert"
>
<span
class="ant-alert-message"
<div
class="ant-alert-content"
>
Alert message title
</span>
<span
class="ant-alert-description"
>
Further details about the context of this alert.
</span>
<div
class="ant-alert-message"
>
Alert message title
</div>
<div
class="ant-alert-description"
>
Further details about the context of this alert.
</div>
</div>
</div>
</div>
</div>
@ -137,16 +141,20 @@ exports[`renders ./components/spin/demo/nested.md correctly 1`] = `
data-show="true"
role="alert"
>
<span
class="ant-alert-message"
<div
class="ant-alert-content"
>
Alert message title
</span>
<span
class="ant-alert-description"
>
Further details about the context of this alert.
</span>
<div
class="ant-alert-message"
>
Alert message title
</div>
<div
class="ant-alert-description"
>
Further details about the context of this alert.
</div>
</div>
</div>
</div>
</div>
@ -291,16 +299,20 @@ exports[`renders ./components/spin/demo/tip.md correctly 1`] = `
data-show="true"
role="alert"
>
<span
class="ant-alert-message"
<div
class="ant-alert-content"
>
Alert message title
</span>
<span
class="ant-alert-description"
>
Further details about the context of this alert.
</span>
<div
class="ant-alert-message"
>
Alert message title
</div>
<div
class="ant-alert-description"
>
Further details about the context of this alert.
</div>
</div>
</div>
</div>
</div>

View File

@ -231,12 +231,8 @@
// ---
@alert-with-description-no-icon-padding-vertical: 7px;
@alert-with-description-padding-vertical: 11px;
@alert-with-description-padding: @alert-with-description-padding-vertical 15px
@alert-with-description-no-icon-padding-vertical @alert-with-description-icon-size * 2 +
@alert-with-description-padding-vertical;
@alert-icon-top: 7px + @font-size-base * @line-height-base / 2 - @font-size-base / 2;
@alert-with-description-icon-size: 20px;
@alert-with-description-icon-top: @alert-with-description-padding-vertical;
// Skeleton
// ---

View File

@ -908,11 +908,9 @@
@alert-with-description-no-icon-padding-vertical: @padding-md - 1px;
@alert-with-description-padding-vertical: @padding-md - 1px;
@alert-with-description-padding: @alert-with-description-padding-vertical 15px
@alert-with-description-no-icon-padding-vertical @alert-with-description-icon-size * 2 +
@alert-with-description-padding-vertical;
@alert-with-description-no-icon-padding-vertical @alert-with-description-icon-size;
@alert-icon-top: 8px + @font-size-base * @line-height-base / 2 - @font-size-base / 2;
@alert-with-description-icon-size: 24px;
@alert-with-description-icon-top: @alert-with-description-padding-vertical;
// List
// ---