feat: notification add top & bottom placement

pull/5820/head
tangjinzhou 2022-05-19 17:42:45 +08:00
parent d716421745
commit 5cf2707e11
6 changed files with 122 additions and 33 deletions

View File

@ -1,6 +1,6 @@
<docs> <docs>
--- ---
order: 6 order: 5
title: title:
zh-CN: 位置 zh-CN: 位置
en-US: Placement en-US: Placement
@ -8,31 +8,39 @@ title:
## zh-CN ## zh-CN
可以设置通知从右上角右下角左下角左上角弹出 使用 `placement` 可以配置通知从右上角右下角左下角左上角弹出
## en-US ## en-US
A notification box can pop up from `topRight` or `bottomRight` or `bottomLeft` or `topLeft`. A notification box can appear from the `topRight`, `bottomRight`, `bottomLeft` or `topLeft` of the viewport via `placement`.
</docs> </docs>
<template> <template>
<div> <div>
<a-button type="primary" @click="openNotification('top')">
<template #icon><BorderTopOutlined /></template>
top
</a-button>
<a-button type="primary" @click="openNotification('bottom')">
<template #icon><BorderBottomOutlined /></template>
bottom
</a-button>
<a-button type="primary" @click="openNotification('topLeft')"> <a-button type="primary" @click="openNotification('topLeft')">
<radius-upleft-outlined /> <template #icon><radius-upleft-outlined /></template>
topLeft topLeft
</a-button> </a-button>
<a-button type="primary" @click="openNotification('topRight')"> <a-button type="primary" @click="openNotification('topRight')">
<radius-upright-outlined /> <template #icon><radius-upright-outlined /></template>
topRight topRight
</a-button> </a-button>
<a-divider /> <a-divider />
<a-button type="primary" @click="openNotification('bottomLeft')"> <a-button type="primary" @click="openNotification('bottomLeft')">
<radius-bottomleft-outlined /> <template #icon><radius-bottomleft-outlined /></template>
bottomLeft bottomLeft
</a-button> </a-button>
<a-button type="primary" @click="openNotification('bottomRight')"> <a-button type="primary" @click="openNotification('bottomRight')">
<radius-bottomright-outlined /> <template #icon><radius-bottomright-outlined /></template>
bottomRight bottomRight
</a-button> </a-button>
</div> </div>
@ -43,6 +51,8 @@ import {
RadiusUprightOutlined, RadiusUprightOutlined,
RadiusBottomleftOutlined, RadiusBottomleftOutlined,
RadiusBottomrightOutlined, RadiusBottomrightOutlined,
BorderTopOutlined,
BorderBottomOutlined,
} from '@ant-design/icons-vue'; } from '@ant-design/icons-vue';
import { notification } from 'ant-design-vue'; import { notification } from 'ant-design-vue';
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
@ -53,6 +63,8 @@ export default defineComponent({
RadiusUprightOutlined, RadiusUprightOutlined,
RadiusBottomleftOutlined, RadiusBottomleftOutlined,
RadiusBottomrightOutlined, RadiusBottomrightOutlined,
BorderTopOutlined,
BorderBottomOutlined,
}, },
setup() { setup() {
const openNotification = (placement: NotificationPlacement) => { const openNotification = (placement: NotificationPlacement) => {

View File

@ -40,7 +40,7 @@ The properties of config are as follows:
| icon | Customized icon | VNode \| () => VNode | - | | | icon | Customized icon | VNode \| () => VNode | - | |
| key | The unique identifier of the Notification | string | - | | | key | The unique identifier of the Notification | string | - | |
| message | The title of notification box (required) | string\| VNode \| () => VNode | - | | | message | The title of notification box (required) | string\| VNode \| () => VNode | - | |
| placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` | | | placement | Position of Notification, can be one of `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` | string | `topRight` | `top` `bottom` 3.3.0 |
| style | Customized inline style | Object \| string | - | | | style | Customized inline style | Object \| string | - | |
| top | Distance from the top of the viewport, when `placement` is `topRight` or `topLeft` (unit: pixels). | string | `24px` | | | top | Distance from the top of the viewport, when `placement` is `topRight` or `topLeft` (unit: pixels). | string | `24px` | |
| onClick | Specify a function that will be called when the notification is clicked | Function | - | | | onClick | Specify a function that will be called when the notification is clicked | Function | - | |

View File

@ -11,7 +11,13 @@ import { globalConfig } from '../config-provider';
import type { NotificationInstance as VCNotificationInstance } from '../vc-notification/Notification'; import type { NotificationInstance as VCNotificationInstance } from '../vc-notification/Notification';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
export type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'; export type NotificationPlacement =
| 'top'
| 'topLeft'
| 'topRight'
| 'bottom'
| 'bottomLeft'
| 'bottomRight';
export type IconType = 'success' | 'info' | 'error' | 'warning'; export type IconType = 'success' | 'info' | 'error' | 'warning';
@ -76,6 +82,15 @@ function getPlacementStyle(
) { ) {
let style: CSSProperties; let style: CSSProperties;
switch (placement) { switch (placement) {
case 'top':
style = {
left: '50%',
transform: 'translateX(-50%)',
right: 'auto',
top,
bottom: 'auto',
};
break;
case 'topLeft': case 'topLeft':
style = { style = {
left: '0px', left: '0px',
@ -90,6 +105,15 @@ function getPlacementStyle(
bottom: 'auto', bottom: 'auto',
}; };
break; break;
case 'bottom':
style = {
left: '50%',
transform: 'translateX(-50%)',
right: 'auto',
top: 'auto',
bottom,
};
break;
case 'bottomLeft': case 'bottomLeft':
style = { style = {
left: '0px', left: '0px',
@ -177,6 +201,7 @@ export interface NotificationArgsProps {
duration?: number | null; duration?: number | null;
icon?: VueNode | (() => VueNode); icon?: VueNode | (() => VueNode);
placement?: NotificationPlacement; placement?: NotificationPlacement;
maxCount?: number;
style?: CSSProperties; style?: CSSProperties;
prefixCls?: string; prefixCls?: string;
class?: string; class?: string;

View File

@ -41,7 +41,7 @@ config 参数如下:
| icon | 自定义图标 | VNode \| () => VNode | - | | | icon | 自定义图标 | VNode \| () => VNode | - | |
| key | 当前通知唯一标志 | string | - | | | key | 当前通知唯一标志 | string | - | |
| message | 通知提醒标题,必选 | string \| VNode \| () => VNode | - | | | message | 通知提醒标题,必选 | string \| VNode \| () => VNode | - | |
| placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight | | | placement | 弹出位置,可选 `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` | string | `topRight` | `top` `bottom` 3.3.0 |
| style | 自定义内联样式 | Object \| string | - | | | style | 自定义内联样式 | Object \| string | - | |
| top | 消息从顶部弹出时,距离顶部的位置,单位像素。 | string | `24px` | | | top | 消息从顶部弹出时,距离顶部的位置,单位像素。 | string | `24px` | |
| onClick | 点击通知时触发的回调函数 | Function | - | | | onClick | 点击通知时触发的回调函数 | Function | - | |

View File

@ -16,17 +16,6 @@
z-index: @zindex-notification; z-index: @zindex-notification;
margin-right: @notification-margin-edge; margin-right: @notification-margin-edge;
&-topLeft,
&-bottomLeft {
margin-right: 0;
margin-left: @notification-margin-edge;
.@{notification-prefix-cls}-fade-enter.@{notification-prefix-cls}-fade-enter-active,
.@{notification-prefix-cls}-fade-appear.@{notification-prefix-cls}-fade-appear-active {
animation-name: NotificationLeftFadeIn;
}
}
&-close-icon { &-close-icon {
font-size: @font-size-base; font-size: @font-size-base;
cursor: pointer; cursor: pointer;
@ -50,6 +39,12 @@
border-radius: @border-radius-base; border-radius: @border-radius-base;
box-shadow: @shadow-2; box-shadow: @shadow-2;
.@{notification-prefix-cls}-top &,
.@{notification-prefix-cls}-bottom & {
margin-right: auto;
margin-left: auto;
}
.@{notification-prefix-cls}-topLeft &, .@{notification-prefix-cls}-topLeft &,
.@{notification-prefix-cls}-bottomLeft & { .@{notification-prefix-cls}-bottomLeft & {
margin-right: auto; margin-right: auto;
@ -192,18 +187,6 @@
} }
} }
@keyframes NotificationLeftFadeIn {
0% {
right: @notification-width;
opacity: 0;
}
100% {
right: 0;
opacity: 1;
}
}
@keyframes NotificationFadeOut { @keyframes NotificationFadeOut {
0% { 0% {
max-height: 150px; max-height: 150px;
@ -221,3 +204,4 @@
} }
@import './rtl'; @import './rtl';
@import './placement';

View File

@ -0,0 +1,68 @@
.@{notification-prefix-cls} {
&-top,
&-bottom {
margin-right: 0;
margin-left: 0;
}
&-top {
.@{notification-prefix-cls}-fade-enter.@{notification-prefix-cls}-fade-enter-active,
.@{notification-prefix-cls}-fade-appear.@{notification-prefix-cls}-fade-appear-active {
animation-name: NotificationTopFadeIn;
}
}
&-bottom {
.@{notification-prefix-cls}-fade-enter.@{notification-prefix-cls}-fade-enter-active,
.@{notification-prefix-cls}-fade-appear.@{notification-prefix-cls}-fade-appear-active {
animation-name: NotificationBottomFadeIn;
}
}
&-topLeft,
&-bottomLeft {
margin-right: 0;
margin-left: @notification-margin-edge;
.@{notification-prefix-cls}-fade-enter.@{notification-prefix-cls}-fade-enter-active,
.@{notification-prefix-cls}-fade-appear.@{notification-prefix-cls}-fade-appear-active {
animation-name: NotificationLeftFadeIn;
}
}
}
@keyframes NotificationTopFadeIn {
0% {
margin-top: -100%;
opacity: 0;
}
100% {
margin-top: 0;
opacity: 1;
}
}
@keyframes NotificationBottomFadeIn {
0% {
margin-bottom: -100%;
opacity: 0;
}
100% {
margin-bottom: 0;
opacity: 1;
}
}
@keyframes NotificationLeftFadeIn {
0% {
right: @notification-width;
opacity: 0;
}
100% {
right: 0;
opacity: 1;
}
}