feat: alert add action slot

pull/6213/head
tangjinzhou 2 years ago
parent b2841a27ae
commit 1f33babc89

@ -0,0 +1,57 @@
<docs>
---
order: 0
title:
zh-CN: 操作
en-US: Action
---
## zh-CN
可以在右上角自定义操作项
## en-US
Custom action.
</docs>
<template>
<a-space direction="vertical" style="width: 100%">
<a-alert message="Success Tips" type="success" show-icon closable>
<template #action>
<a-button size="small" type="text">UNDO</a-button>
</template>
</a-alert>
<a-alert
message="Error Text"
show-icon
description="Error Description Error Description Error Description Error Description"
type="error"
>
<template #action>
<a-button size="small" danger>Detail</a-button>
</template>
</a-alert>
<a-alert message="Warning Text" type="warning" closable>
<template #action>
<a-space>
<a-button size="small" type="ghost">Done</a-button>
</a-space>
</template>
</a-alert>
<a-alert
message="Info Text"
description="Info Description Info Description Info Description Info Description"
type="info"
closable
>
<template #action>
<a-space direction="vertical">
<a-button size="small" type="primary">Accept</a-button>
<a-button size="small" danger type="ghost">Decline</a-button>
</a-space>
</template>
</a-alert>
</a-space>
</template>

@ -9,6 +9,7 @@
<banner /> <banner />
<custom-icon /> <custom-icon />
<smooth-closed /> <smooth-closed />
<action />
</demo-sort> </demo-sort>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -18,6 +19,7 @@ import Closable from './closable.vue';
import CloseText from './close-text.vue'; import CloseText from './close-text.vue';
import Description from './description.vue'; import Description from './description.vue';
import Icon from './icon.vue'; import Icon from './icon.vue';
import Action from './action.vue';
import Style from './style.vue'; import Style from './style.vue';
import SmoothClosed from './smooth-closed.vue'; import SmoothClosed from './smooth-closed.vue';
import CustomIcon from './custom-icon.vue'; import CustomIcon from './custom-icon.vue';
@ -37,6 +39,7 @@ export default defineComponent({
FourStyle: Style, //style FourStyle: Style, //style
SmoothClosed, SmoothClosed,
CustomIcon, CustomIcon,
Action,
}, },
setup() { setup() {
return {}; return {};

@ -16,6 +16,7 @@ Alert component for feedback.
| Property | Description | Type | Default | Version | | Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| action | The action of Alert | slot | - | 4.0.0 |
| afterClose | Called when close animation is finished | () => void | - | | | afterClose | Called when close animation is finished | () => void | - | |
| banner | Whether to show as banner | boolean | false | | | banner | Whether to show as banner | boolean | false | |
| closable | Whether Alert can be closed | boolean | | | | closable | Whether Alert can be closed | boolean | | |

@ -1,5 +1,5 @@
import type { CSSProperties, ExtractPropTypes, PropType } from 'vue'; import type { CSSProperties, ExtractPropTypes, PropType } from 'vue';
import { defineComponent, ref } from 'vue'; import { computed, defineComponent, ref } from 'vue';
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined'; import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined'; import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined';
import ExclamationCircleOutlined from '@ant-design/icons-vue/ExclamationCircleOutlined'; import ExclamationCircleOutlined from '@ant-design/icons-vue/ExclamationCircleOutlined';
@ -12,7 +12,7 @@ import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { getTransitionProps, Transition } from '../_util/transition'; import { getTransitionProps, Transition } from '../_util/transition';
import { isValidElement, getPropsSlot } from '../_util/props-util'; import { isValidElement } from '../_util/props-util';
import { tuple, withInstall } from '../_util/type'; import { tuple, withInstall } from '../_util/type';
import { cloneElement } from '../_util/vnode'; import { cloneElement } from '../_util/vnode';
import type { NodeMouseEventHandler } from '../vc-tree/contextTypes'; import type { NodeMouseEventHandler } from '../vc-tree/contextTypes';
@ -94,25 +94,31 @@ const Alert = defineComponent({
closed.value = true; closed.value = true;
props.afterClose?.(); props.afterClose?.();
}; };
const mergedType = computed(() => {
const { type } = props;
if (type !== undefined) {
return type;
}
// banner
return props.banner ? 'warning' : 'info';
});
expose({ animationEnd }); expose({ animationEnd });
const motionStyle = ref<CSSProperties>({}); const motionStyle = ref<CSSProperties>({});
return () => { return () => {
const { banner, closeIcon: customCloseIcon = slots.closeIcon?.() } = props; const { banner, closeIcon: customCloseIcon = slots.closeIcon?.() } = props;
let { closable, type, showIcon } = props; let { closable, showIcon } = props;
const closeText = getPropsSlot(slots, props, 'closeText'); const closeText = props.closeText ?? slots.closeText?.();
const description = getPropsSlot(slots, props, 'description'); const description = props.description ?? slots.description?.();
const message = getPropsSlot(slots, props, 'message'); const message = props.message ?? slots.message?.();
const icon = getPropsSlot(slots, props, 'icon'); const icon = props.icon ?? slots.icon?.();
const action = slots.action?.();
// banner Icon // banner Icon
showIcon = banner && showIcon === undefined ? true : showIcon; showIcon = banner && showIcon === undefined ? true : showIcon;
// banner
type = banner && type === undefined ? 'warning' : type || 'info';
const IconType = (description ? iconMapOutlined : iconMapFilled)[type] || null; const IconType = (description ? iconMapOutlined : iconMapFilled)[mergedType.value] || null;
// closeable when closeText is assigned // closeable when closeText is assigned
if (closeText) { if (closeText) {
@ -120,7 +126,7 @@ const Alert = defineComponent({
} }
const prefixClsValue = prefixCls.value; const prefixClsValue = prefixCls.value;
const alertCls = classNames(prefixClsValue, { const alertCls = classNames(prefixClsValue, {
[`${prefixClsValue}-${type}`]: true, [`${prefixClsValue}-${mergedType.value}`]: true,
[`${prefixClsValue}-closing`]: closing.value, [`${prefixClsValue}-closing`]: closing.value,
[`${prefixClsValue}-with-description`]: !!description, [`${prefixClsValue}-with-description`]: !!description,
[`${prefixClsValue}-no-icon`]: !showIcon, [`${prefixClsValue}-no-icon`]: !showIcon,
@ -186,6 +192,7 @@ const Alert = defineComponent({
<div class={`${prefixClsValue}-description`}>{description}</div> <div class={`${prefixClsValue}-description`}>{description}</div>
) : null} ) : null}
</div> </div>
{action ? <div class={`${prefixClsValue}-action`}>{action}</div> : null}
{closeIcon} {closeIcon}
</div> </div>
</Transition> </Transition>

@ -17,6 +17,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/8emPa3fjl/Alert.svg
| 参数 | 说明 | 类型 | 默认值 | 版本 | | 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| action | 自定义操作项 | slot | - | 4.0.0 |
| afterClose | 关闭动画结束后触发的回调函数 | () => void | - | | | afterClose | 关闭动画结束后触发的回调函数 | () => void | - | |
| banner | 是否用作顶部公告 | boolean | false | | | banner | 是否用作顶部公告 | boolean | false | |
| closable | 默认不显示关闭按钮 | boolean | 无 | | | closable | 默认不显示关闭按钮 | boolean | 无 | |

@ -1,155 +0,0 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@alert-prefix-cls: ~'@{ant-prefix}-alert';
.@{alert-prefix-cls} {
.reset-component();
position: relative;
display: flex;
align-items: center;
padding: 8px 15px;
word-wrap: break-word;
border-radius: @border-radius-base;
&-content {
flex: 1;
min-width: 0;
}
&-icon {
margin-right: @margin-xs;
}
&-description {
display: none;
font-size: @font-size-base;
line-height: @font-size-base + 8px;
}
&-success {
background-color: @alert-success-bg-color;
border: @border-width-base @border-style-base @alert-success-border-color;
.@{alert-prefix-cls}-icon {
color: @alert-success-icon-color;
}
}
&-info {
background-color: @alert-info-bg-color;
border: @border-width-base @border-style-base @alert-info-border-color;
.@{alert-prefix-cls}-icon {
color: @alert-info-icon-color;
}
}
&-warning {
background-color: @alert-warning-bg-color;
border: @border-width-base @border-style-base @alert-warning-border-color;
.@{alert-prefix-cls}-icon {
color: @alert-warning-icon-color;
}
}
&-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 {
margin-left: @margin-xs;
padding: 0;
overflow: hidden;
font-size: @font-size-sm;
line-height: @font-size-sm;
background-color: transparent;
border: none;
outline: none;
cursor: pointer;
.@{iconfont-css-prefix}-close {
color: @alert-close-color;
transition: color 0.3s;
&:hover {
color: @alert-close-hover-color;
}
}
}
&-close-text {
color: @alert-close-color;
transition: color 0.3s;
&:hover {
color: @alert-close-hover-color;
}
}
&-with-description {
align-items: flex-start;
padding: @alert-with-description-padding;
}
&-with-description&-no-icon {
padding: @alert-with-description-no-icon-padding-vertical 15px;
}
&-with-description &-icon {
margin-right: @alert-with-description-padding-vertical;
font-size: @alert-with-description-icon-size;
}
&-with-description &-message {
display: block;
margin-bottom: 4px;
color: @alert-message-color;
font-size: @font-size-lg;
}
&-message {
color: @alert-message-color;
}
&-with-description &-description {
display: block;
}
&&-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;
}
&&-motion-leave-active {
max-height: 0;
margin-bottom: 0 !important;
padding-top: 0;
padding-bottom: 0;
opacity: 0;
}
&-banner {
margin-bottom: 0;
border: 0;
border-radius: 0;
}
}
@import './rtl';

@ -1,2 +0,0 @@
import '../../style/index.less';
import './index.less';

@ -1,40 +0,0 @@
.@{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;
}
}
}
}

@ -30,7 +30,7 @@ import './affix/style';
import './cascader/style'; import './cascader/style';
import './back-top/style'; import './back-top/style';
import './modal/style'; import './modal/style';
import './alert/style'; // import './alert/style';
import './time-picker/style'; import './time-picker/style';
import './steps/style'; import './steps/style';
import './breadcrumb/style'; import './breadcrumb/style';

@ -1,3 +1,7 @@
<template> <template>
<a-alert message="Success Text" prefix-cls="tes" type="success" /> <a-alert message="Success Tips" type="success" show-icon closable>
<template #action>
<a-button v-if="false" size="small" type="text">UNDO</a-button>
</template>
</a-alert>
</template> </template>

Loading…
Cancel
Save