+
diff --git a/components/alert/index.en-US.md b/components/alert/index.en-US.md
index 85d20a35b..b342e7a54 100644
--- a/components/alert/index.en-US.md
+++ b/components/alert/index.en-US.md
@@ -20,6 +20,7 @@ Alert component for feedback.
| banner | Whether to show as banner | boolean | false | |
| closable | Whether Alert can be closed | boolean | | |
| closeText | Close text to show | string\|slot | - | |
+| closeIcon | Custom close icon | slot |
| 3.0 |
| description | Additional content of Alert | string\|slot | - | |
| icon | Custom icon, effective when `showIcon` is `true` | vnode \| slot | - | |
| message | Content of Alert | string\|slot | - | |
diff --git a/components/alert/index.tsx b/components/alert/index.tsx
index 2d33dcab9..289136fba 100644
--- a/components/alert/index.tsx
+++ b/components/alert/index.tsx
@@ -1,4 +1,4 @@
-import type { ExtractPropTypes } from 'vue';
+import type { CSSProperties, ExtractPropTypes, PropType } from 'vue';
import { inject, defineComponent, ref } from 'vue';
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined';
@@ -16,6 +16,7 @@ import { isValidElement, getPropsSlot } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider';
import { tuple, withInstall } from '../_util/type';
import { cloneElement } from '../_util/vnode';
+import type { NodeMouseEventHandler } from '../vc-tree/contextTypes';
function noop() {}
@@ -37,7 +38,7 @@ const AlertTypes = tuple('success', 'info', 'warning', 'error');
export type AlertType = typeof AlertTypes[number];
-const alertProps = {
+export const alertProps = () => ({
/**
* Type of Alert styles, options: `success`, `info`, `warning`, `error`
*/
@@ -57,16 +58,16 @@ const alertProps = {
prefixCls: PropTypes.string,
banner: PropTypes.looseBool,
icon: PropTypes.any,
- onClose: PropTypes.any,
-};
+ closeIcon: PropTypes.any,
+ onClose: Function as PropType
,
+});
-export type AlertProps = Partial>;
+export type AlertProps = Partial>>;
const Alert = defineComponent({
name: 'AAlert',
inheritAttrs: false,
- props: alertProps,
- emits: ['close'],
+ props: alertProps(),
setup(props, { slots, emit, attrs, expose }) {
const configProvider = inject('configProvider', defaultConfigProvider);
const closing = ref(false);
@@ -94,9 +95,13 @@ const Alert = defineComponent({
};
expose({ animationEnd });
-
+ const motionStyle = ref({});
return () => {
- const { prefixCls: customizePrefixCls, banner } = props;
+ const {
+ prefixCls: customizePrefixCls,
+ banner,
+ closeIcon: customCloseIcon = slots.closeIcon?.(),
+ } = props;
const { getPrefixCls } = configProvider;
const prefixCls = getPrefixCls('alert', customizePrefixCls);
@@ -132,8 +137,10 @@ const Alert = defineComponent({
) : null;
@@ -147,14 +154,23 @@ const Alert = defineComponent({
{icon}
))) || ;
- const transitionProps = getTransitionProps(`${prefixCls}-slide-up`, {
+ const transitionProps = getTransitionProps(`${prefixCls}-motion`, {
appear: false,
+ css: true,
onAfterLeave: animationEnd,
+ onBeforeLeave: (node: HTMLDivElement) => {
+ node.style.maxHeight = `${node.offsetHeight}px`;
+ },
+ onLeave: (node: HTMLDivElement) => {
+ node.style.maxHeight = '0px';
+ },
});
return closed.value ? null : (
{showIcon ? iconNode : null}
-
{message}
-
{description}
+ {message ?
{message}
: null}
+ {description ?
{description}
: null}
{closeIcon}
diff --git a/components/alert/index.zh-CN.md b/components/alert/index.zh-CN.md
index b07d93a7a..80c6e16cd 100644
--- a/components/alert/index.zh-CN.md
+++ b/components/alert/index.zh-CN.md
@@ -21,6 +21,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/8emPa3fjl/Alert.svg
| banner | 是否用作顶部公告 | boolean | false | |
| closable | 默认不显示关闭按钮 | boolean | 无 | |
| closeText | 自定义关闭按钮 | string\|slot | 无 | |
+| closeIcon | 自定义关闭 Icon | slot | | 3.0 |
| description | 警告提示的辅助性文字介绍 | string\|slot | 无 | |
| icon | 自定义图标,`showIcon` 为 `true` 时有效 | vnode\|slot | - | |
| message | 警告提示内容 | string\|slot | 无 | |
diff --git a/components/alert/style/index.less b/components/alert/style/index.less
index 4c808eb78..722385044 100644
--- a/components/alert/style/index.less
+++ b/components/alert/style/index.less
@@ -3,16 +3,6 @@
@alert-prefix-cls: ~'@{ant-prefix}-alert';
-@alert-message-color: @heading-color;
-@alert-text-color: @text-color;
-@alert-close-color: @text-color-secondary;
-@alert-close-hover-color: @icon-color-hover;
-
-@alert-with-description-icon-size: 24px;
-@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-prefix-cls} {
.reset-component();
@@ -65,9 +55,19 @@
&-error {
background-color: @alert-error-bg-color;
border: @border-width-base @border-style-base @alert-error-border-color;
+
.@{alert-prefix-cls}-icon {
color: @alert-error-icon-color;
}
+
+ .@{alert-prefix-cls}-description > pre {
+ margin: 0;
+ padding: 0;
+ }
+ }
+
+ &-action {
+ margin-left: @margin-xs;
}
&-close-icon {
@@ -84,6 +84,7 @@
.@{iconfont-css-prefix}-close {
color: @alert-close-color;
transition: color 0.3s;
+
&:hover {
color: @alert-close-hover-color;
}
@@ -93,6 +94,7 @@
&-close-text {
color: @alert-close-color;
transition: color 0.3s;
+
&:hover {
color: @alert-close-hover-color;
}
@@ -127,18 +129,20 @@
display: block;
}
- &&-closing {
- height: 0 !important;
- margin: 0;
- padding-top: 0;
- padding-bottom: 0;
- transform-origin: 50% 0;
- transition: all 0.3s @ease-in-out-circ;
+ &&-motion-leave {
+ overflow: hidden;
+ opacity: 1;
+ transition: max-height 0.3s @ease-in-out-circ, opacity 0.3s @ease-in-out-circ,
+ padding-top 0.3s @ease-in-out-circ, padding-bottom 0.3s @ease-in-out-circ,
+ margin-bottom 0.3s @ease-in-out-circ;
}
- &-slide-up-leave {
- animation: antAlertSlideUpOut 0.3s @ease-in-out-circ;
- animation-fill-mode: both;
+ &&-motion-leave-active {
+ max-height: 0;
+ margin-bottom: 0 !important;
+ padding-top: 0;
+ padding-bottom: 0;
+ opacity: 0;
}
&-banner {
@@ -148,28 +152,4 @@
}
}
-@keyframes antAlertSlideUpIn {
- 0% {
- transform: scaleY(0);
- transform-origin: 0% 0%;
- opacity: 0;
- }
- 100% {
- transform: scaleY(1);
- transform-origin: 0% 0%;
- opacity: 1;
- }
-}
-
-@keyframes antAlertSlideUpOut {
- 0% {
- transform: scaleY(1);
- transform-origin: 0% 0%;
- opacity: 1;
- }
- 100% {
- transform: scaleY(0);
- transform-origin: 0% 0%;
- opacity: 0;
- }
-}
+@import './rtl';
diff --git a/components/alert/style/rtl.less b/components/alert/style/rtl.less
new file mode 100644
index 000000000..31d63146c
--- /dev/null
+++ b/components/alert/style/rtl.less
@@ -0,0 +1,40 @@
+.@{alert-prefix-cls} {
+ &&-rtl {
+ direction: rtl;
+ }
+
+ &-icon {
+ .@{alert-prefix-cls}-rtl & {
+ margin-right: auto;
+ margin-left: @margin-xs;
+ }
+ }
+
+ &-action {
+ .@{alert-prefix-cls}-rtl & {
+ margin-right: @margin-xs;
+ margin-left: auto;
+ }
+ }
+
+ &-close-icon {
+ .@{alert-prefix-cls}-rtl & {
+ margin-right: @margin-xs;
+ margin-left: auto;
+ }
+ }
+
+ &-with-description {
+ .@{alert-prefix-cls}-rtl& {
+ padding-right: @alert-with-description-icon-size;
+ padding-left: @alert-with-description-padding-vertical;
+ }
+
+ .@{alert-prefix-cls}-icon {
+ .@{alert-prefix-cls}-rtl& {
+ margin-right: auto;
+ margin-left: @alert-with-description-padding-vertical;
+ }
+ }
+ }
+}
diff --git a/components/style/themes/default.less b/components/style/themes/default.less
index 4276be61b..df7741688 100644
--- a/components/style/themes/default.less
+++ b/components/style/themes/default.less
@@ -919,7 +919,17 @@
@alert-error-border-color: ~`colorPalette('@{error-color}', 3) `;
@alert-error-bg-color: ~`colorPalette('@{error-color}', 1) `;
@alert-error-icon-color: @error-color;
-
+@alert-message-color: @heading-color;
+@alert-text-color: @text-color;
+@alert-close-color: @text-color-secondary;
+@alert-close-hover-color: @icon-color-hover;
+@alert-no-icon-padding-vertical: @padding-xs;
+@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;
+@alert-icon-top: 8px + @font-size-base * (@line-height-base / 2) - (@font-size-base / 2);
+@alert-with-description-icon-size: 24px;
// List
// ---
@list-header-background: transparent;