add notification
							parent
							
								
									1e6f60d8d2
								
							
						
					
					
						commit
						aa62123899
					
				|  | @ -0,0 +1,63 @@ | |||
| --- | ||||
| category: Components | ||||
| type: Feedback | ||||
| noinstant: true | ||||
| title: Notification | ||||
| --- | ||||
| 
 | ||||
| Display a notification message globally. | ||||
| 
 | ||||
| ## When To Use | ||||
| 
 | ||||
| To display a notification message at any of the four corners of the viewport. Typically it can be | ||||
| used in the following cases: | ||||
| 
 | ||||
| - A notification with complex content. | ||||
| - A notification providing a feedback based on the user interaction. Or it may show some details | ||||
|   about upcoming steps the user may have to follow. | ||||
| - A notification that is pushed by the application. | ||||
| 
 | ||||
| ## API | ||||
| 
 | ||||
| - `notification.success(config)` | ||||
| - `notification.error(config)` | ||||
| - `notification.info(config)` | ||||
| - `notification.warning(config)` | ||||
| - `notification.warn(config)` | ||||
| - `notification.close(key: String)` | ||||
| - `notification.destroy()` | ||||
| 
 | ||||
| The properties of config are as follows: | ||||
| 
 | ||||
| | Property | Description | Type | Default | | ||||
| | -------- | ----------- | ---- | ------- | | ||||
| | btn | Customized close button | ReactNode | - | | ||||
| | className | Customized CSS class | string | - | | ||||
| | description | The content of notification box (required) | string\|ReactNode | - | | ||||
| | duration | Time in seconds before Notification is closed. When set to 0 or null, it will never be closed automatically | number | 4.5 | | ||||
| | icon | Customized icon | ReactNode | - | | ||||
| | key | The unique identifier of the Notification | string | - | | ||||
| | message | The title of notification box (required) | string\|ReactNode | - | | ||||
| | placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` | | ||||
| | style | Customized inline style | [React.CSSProperties](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e434515761b36830c3e58a970abf5186f005adac/types/react/index.d.ts#L794) | - | | ||||
| | onClose | Specify a function that will be called when the close button is clicked | Function | - | | ||||
| 
 | ||||
| `notification` also provides a global `config()` method that can be used for specifying the default options. Once this method is used, all the notification boxes will take into account these globally defined options when displaying. | ||||
| 
 | ||||
| - `notification.config(options)` | ||||
| 
 | ||||
| ```js | ||||
| notification.config({ | ||||
|   placement: 'bottomRight', | ||||
|   bottom: 50, | ||||
|   duration: 3, | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| | Property | Description | Type | Default | | ||||
| | -------- | ----------- | ---- | ------- | | ||||
| | bottom | Distance from the bottom of the viewport, when `placement` is `bottomRight` or `bottomLeft` (unit: pixels). | number | 24 | | ||||
| | duration | Time in seconds before Notification is closed. When set to 0 or null, it will never be closed automatically | number | 4.5 | | ||||
| | getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body | | ||||
| | placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` | | ||||
| | top | Distance from the top of the viewport, when `placement` is `topRight` or `topLeft` (unit: pixels). | number | 24 | | ||||
|  | @ -0,0 +1,201 @@ | |||
| <script> | ||||
| import Notification from './src/notification'; | ||||
| import Icon from '../icon'; | ||||
| 
 | ||||
| export type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'; | ||||
| 
 | ||||
| export type IconType =  'success' | 'info' | 'error' | 'warning'; | ||||
| 
 | ||||
| const notificationInstance: { [key: string]: any } = {}; | ||||
| let defaultDuration = 4.5; | ||||
| let defaultTop = 24; | ||||
| let defaultBottom = 24; | ||||
| let defaultPlacement: NotificationPlacement = 'topRight'; | ||||
| let defaultGetContainer: () => HTMLElement; | ||||
| 
 | ||||
| export interface ConfigProps { | ||||
|   top?: number; | ||||
|   bottom?: number; | ||||
|   duration?: number; | ||||
|   placement?: NotificationPlacement; | ||||
|   getContainer?: () => HTMLElement; | ||||
| } | ||||
| function setNotificationConfig(options: ConfigProps) { | ||||
|   const { duration, placement, bottom, top, getContainer } = options; | ||||
|   if (duration !== undefined) { | ||||
|     defaultDuration = duration; | ||||
|   } | ||||
|   if (placement !== undefined) { | ||||
|     defaultPlacement = placement; | ||||
|   } | ||||
|   if (bottom !== undefined) { | ||||
|     defaultBottom = bottom; | ||||
|   } | ||||
|   if (top !== undefined) { | ||||
|     defaultTop = top; | ||||
|   } | ||||
|   if (getContainer !== undefined) { | ||||
|     defaultGetContainer = getContainer; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function getPlacementStyle(placement: NotificationPlacement) { | ||||
|   let style; | ||||
|   switch (placement) { | ||||
|     case 'topLeft': | ||||
|       style = { | ||||
|         left: 0, | ||||
|         top: defaultTop, | ||||
|         bottom: 'auto', | ||||
|       }; | ||||
|       break; | ||||
|     case 'topRight': | ||||
|       style = { | ||||
|         right: 0, | ||||
|         top: defaultTop, | ||||
|         bottom: 'auto', | ||||
|       }; | ||||
|       break; | ||||
|     case 'bottomLeft': | ||||
|       style = { | ||||
|         left: 0, | ||||
|         top: 'auto', | ||||
|         bottom: defaultBottom, | ||||
|       }; | ||||
|       break; | ||||
|     default: | ||||
|       style = { | ||||
|         right: 0, | ||||
|         top: 'auto', | ||||
|         bottom: defaultBottom, | ||||
|       }; | ||||
|       break; | ||||
|   } | ||||
|   return style; | ||||
| } | ||||
| 
 | ||||
| function getNotificationInstance(prefixCls: string, placement: NotificationPlacement, callback: (n: any) => void) { | ||||
|   const cacheKey = `${prefixCls}-${placement}`; | ||||
|   if (notificationInstance[cacheKey]) { | ||||
|     callback(notificationInstance[cacheKey]); | ||||
|     return; | ||||
|   } | ||||
|   (Notification as any).newInstance({ | ||||
|     prefixCls, | ||||
|     className: `${prefixCls}-${placement}`, | ||||
|     style: getPlacementStyle(placement), | ||||
|     getContainer: defaultGetContainer, | ||||
|   }, (notification: any) => { | ||||
|     notificationInstance[cacheKey] = notification; | ||||
|     callback(notification); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| const typeToIcon = { | ||||
|   success: 'check-circle-o', | ||||
|   info: 'info-circle-o', | ||||
|   error: 'cross-circle-o', | ||||
|   warning: 'exclamation-circle-o', | ||||
| }; | ||||
| 
 | ||||
| export interface ArgsProps { | ||||
|   message: React.ReactNode; | ||||
|   description: React.ReactNode; | ||||
|   btn?: React.ReactNode; | ||||
|   key?: string; | ||||
|   onClose?: () => void; | ||||
|   duration?: number | null; | ||||
|   icon?: React.ReactNode; | ||||
|   placement?: NotificationPlacement; | ||||
|   style?: React.CSSProperties; | ||||
|   prefixCls?: string; | ||||
|   className?: string; | ||||
|   readonly type?: IconType; | ||||
| } | ||||
| function notice(args: ArgsProps) { | ||||
|   const outerPrefixCls = args.prefixCls || 'ant-notification'; | ||||
|   const prefixCls = `${outerPrefixCls}-notice`; | ||||
|   const duration = args.duration === undefined ? defaultDuration : args.duration; | ||||
| 
 | ||||
|   let iconNode: React.ReactNode = null; | ||||
|   if (args.icon) { | ||||
|     iconNode = ( | ||||
|       <span className={`${prefixCls}-icon`}> | ||||
|         {args.icon} | ||||
|       </span> | ||||
|     ); | ||||
|   } else if (args.type) { | ||||
|     const iconType = typeToIcon[args.type]; | ||||
|     iconNode = ( | ||||
|       <Icon | ||||
|         className={`${prefixCls}-icon ${prefixCls}-icon-${args.type}`} | ||||
|         type={iconType} | ||||
|       /> | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   const autoMarginTag = (!args.description && iconNode) | ||||
|     ? <span className={`${prefixCls}-message-single-line-auto-margin`} /> | ||||
|     : null; | ||||
| 
 | ||||
|   getNotificationInstance(outerPrefixCls, args.placement || defaultPlacement, (notification: any) => { | ||||
|     notification.notice({ | ||||
|       content: ( | ||||
|         <div className={iconNode ? `${prefixCls}-with-icon` : ''}> | ||||
|           {iconNode} | ||||
|           <div className={`${prefixCls}-message`}> | ||||
|             {autoMarginTag} | ||||
|             {args.message} | ||||
|           </div> | ||||
|           <div className={`${prefixCls}-description`}>{args.description}</div> | ||||
|           {args.btn ? <span className={`${prefixCls}-btn`}>{args.btn}</span> : null} | ||||
|         </div> | ||||
|       ), | ||||
|       duration, | ||||
|       closable: true, | ||||
|       onClose: args.onClose, | ||||
|       key: args.key, | ||||
|       style: args.style || {}, | ||||
|       className: args.className, | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| const api: any = { | ||||
|   open: notice, | ||||
|   close(key: string) { | ||||
|     Object.keys(notificationInstance) | ||||
|       .forEach(cacheKey => notificationInstance[cacheKey].removeNotice(key)); | ||||
|   }, | ||||
|   config: setNotificationConfig, | ||||
|   destroy() { | ||||
|     Object.keys(notificationInstance).forEach(cacheKey => { | ||||
|       notificationInstance[cacheKey].destroy(); | ||||
|       delete notificationInstance[cacheKey]; | ||||
|     }); | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| ['success', 'info', 'warning', 'error'].forEach((type) => { | ||||
|   api[type] = (args: ArgsProps) => api.open({ | ||||
|     ...args, | ||||
|     type, | ||||
|   }); | ||||
| }); | ||||
| 
 | ||||
| api.warn = api.warning; | ||||
| 
 | ||||
| export interface NotificationApi { | ||||
|   success(args: ArgsProps): void; | ||||
|   error(args: ArgsProps): void; | ||||
|   info(args: ArgsProps): void; | ||||
|   warn(args: ArgsProps): void; | ||||
|   warning(args: ArgsProps): void; | ||||
|   open(args: ArgsProps): void; | ||||
|   close(key: string): void; | ||||
|   config(options: ConfigProps): void; | ||||
|   destroy(): void; | ||||
| } | ||||
| export default api as NotificationApi; | ||||
| 
 | ||||
| </script> | ||||
|  | @ -0,0 +1,62 @@ | |||
| --- | ||||
| category: Components | ||||
| type: Feedback | ||||
| noinstant: true | ||||
| title: Notification | ||||
| subtitle: 通知提醒框 | ||||
| --- | ||||
| 
 | ||||
| 全局展示通知提醒信息。 | ||||
| 
 | ||||
| ## 何时使用 | ||||
| 
 | ||||
| 在系统四个角显示通知提醒信息。经常用于以下情况: | ||||
| 
 | ||||
| - 较为复杂的通知内容。 | ||||
| - 带有交互的通知,给出用户下一步的行动点。 | ||||
| - 系统主动推送。 | ||||
| 
 | ||||
| ## API | ||||
| 
 | ||||
| - `notification.success(config)` | ||||
| - `notification.error(config)` | ||||
| - `notification.info(config)` | ||||
| - `notification.warning(config)` | ||||
| - `notification.warn(config)` | ||||
| - `notification.close(key: String)` | ||||
| - `notification.destroy()` | ||||
| 
 | ||||
| config 参数如下: | ||||
| 
 | ||||
| | 参数 | 说明 | 类型 | 默认值 | | ||||
| | --- | --- | --- | --- | | ||||
| | btn | 自定义关闭按钮 | ReactNode | - | | ||||
| | className | 自定义 CSS class | string | - | | ||||
| | description | 通知提醒内容,必选 | string\|ReactNode | - | | ||||
| | duration | 默认 4.5 秒后自动关闭,配置为 null 则不自动关闭 | number | 4.5 | | ||||
| | icon | 自定义图标 | ReactNode | - | | ||||
| | key | 当前通知唯一标志 | string | - | | ||||
| | message | 通知提醒标题,必选 | string\|ReactNode | - | | ||||
| | placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight | | ||||
| | style | 自定义内联样式 | [React.CSSProperties](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e434515761b36830c3e58a970abf5186f005adac/types/react/index.d.ts#L794) | - | | ||||
| | onClose | 点击默认关闭按钮时触发的回调函数 | Function | - | | ||||
| 
 | ||||
| 还提供了一个全局配置方法,在调用前提前配置,全局一次生效。 | ||||
| 
 | ||||
| - `notification.config(options)` | ||||
| 
 | ||||
| ```js | ||||
| notification.config({ | ||||
|   placement: 'bottomRight', | ||||
|   bottom: 50, | ||||
|   duration: 3, | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| | 参数 | 说明 | 类型 | 默认值 | | ||||
| | --- | --- | --- | --- | | ||||
| | bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | number | 24 | | ||||
| | duration | 默认自动关闭延时,单位秒 | number | 4.5 | | ||||
| | getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body | | ||||
| | placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight | | ||||
| | top | 消息从顶部弹出时,距离顶部的位置,单位像素。 | number | 24 | | ||||
|  | @ -0,0 +1,2 @@ | |||
| import '../../style/index.less' | ||||
| import './index.less' | ||||
|  | @ -0,0 +1,199 @@ | |||
| @import "../../style/themes/default"; | ||||
| @import "../../style/mixins/index"; | ||||
| 
 | ||||
| @notification-prefix-cls: ~"@{ant-prefix}-notification"; | ||||
| @notification-width: 384px; | ||||
| @notification-padding-vertical: 16px; | ||||
| @notification-padding-horizontal: 24px; | ||||
| @notification-padding: @notification-padding-vertical @notification-padding-horizontal; | ||||
| @notification-margin-bottom: 16px; | ||||
| 
 | ||||
| .@{notification-prefix-cls} { | ||||
|   .reset-component; | ||||
| 
 | ||||
|   position: fixed; | ||||
|   z-index: @zindex-notification; | ||||
|   width: @notification-width; | ||||
|   max-width: ~"calc(100vw - 32px)"; | ||||
|   margin-right: 24px; | ||||
| 
 | ||||
|   &-topLeft, | ||||
|   &-bottomLeft { | ||||
|     margin-left: 24px; | ||||
|     margin-right: 0; | ||||
| 
 | ||||
|     .@{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; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &-notice { | ||||
|     padding: @notification-padding; | ||||
|     border-radius: @border-radius-base; | ||||
|     box-shadow: @shadow-2; | ||||
|     background: @component-background; | ||||
|     line-height: 1.5; | ||||
|     position: relative; | ||||
|     margin-bottom: @notification-margin-bottom; | ||||
|     overflow: hidden; | ||||
| 
 | ||||
|     &-message { | ||||
|       font-size: @font-size-lg; | ||||
|       color: @heading-color; | ||||
|       margin-bottom: 8px; | ||||
|       line-height: 24px; | ||||
|       display: inline-block; | ||||
| 
 | ||||
|       // https://github.com/ant-design/ant-design/issues/5846#issuecomment-296244140 | ||||
|       &-single-line-auto-margin { | ||||
|         width: ~"calc(@{notification-width} - @{notification-padding-horizontal} * 2 - 24px - 48px - 100%)"; | ||||
|         background-color: transparent; | ||||
|         pointer-events: none; | ||||
|         display: block; | ||||
|         max-width: 4px; | ||||
|         &:before { | ||||
|           content: ''; | ||||
|           display: block; | ||||
|           padding-bottom: 100%; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     &-description { | ||||
|       font-size: @font-size-base; | ||||
|     } | ||||
| 
 | ||||
|     &-closable &-message { | ||||
|       padding-right: 24px; | ||||
|     } | ||||
| 
 | ||||
|     &-with-icon &-message { | ||||
|       font-size: @font-size-lg; | ||||
|       margin-left: 48px; | ||||
|       margin-bottom: 4px; | ||||
|     } | ||||
| 
 | ||||
|     &-with-icon &-description { | ||||
|       margin-left: 48px; | ||||
|       font-size: @font-size-base; | ||||
|     } | ||||
| 
 | ||||
|     &-icon { | ||||
|       position: absolute; | ||||
|       font-size: 24px; | ||||
|       line-height: 24px; | ||||
|       margin-left: 4px; | ||||
| 
 | ||||
|       &-success { | ||||
|         color: @success-color; | ||||
|       } | ||||
|       &-info { | ||||
|         color: @info-color; | ||||
|       } | ||||
|       &-warning { | ||||
|         color: @warning-color; | ||||
|       } | ||||
|       &-error { | ||||
|         color: @error-color; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     &-close-x:after { | ||||
|       font-size: @font-size-base; | ||||
|       content: "\e633"; | ||||
|       font-family: "anticon"; | ||||
|       cursor: pointer; | ||||
|     } | ||||
| 
 | ||||
|     &-close { | ||||
|       position: absolute; | ||||
|       right: 22px; | ||||
|       top: 16px; | ||||
|       color: @text-color-secondary; | ||||
|       outline: none; | ||||
| 
 | ||||
|       a&:focus { | ||||
|         text-decoration: none; | ||||
|       } | ||||
| 
 | ||||
|       &:hover { | ||||
|         color: #404040; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     &-btn { | ||||
|       float: right; | ||||
|       margin-top: 16px; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .notification-fade-effect { | ||||
|     animation-duration: 0.24s; | ||||
|     animation-fill-mode: both; | ||||
|     animation-timing-function: @ease-in-out; | ||||
|   } | ||||
| 
 | ||||
|   &-fade-enter, | ||||
|   &-fade-appear { | ||||
|     opacity: 0; | ||||
|     .notification-fade-effect(); | ||||
|     animation-play-state: paused; | ||||
|   } | ||||
| 
 | ||||
|   &-fade-leave { | ||||
|     .notification-fade-effect(); | ||||
|     animation-duration: 0.2s; | ||||
|     animation-play-state: paused; | ||||
|   } | ||||
| 
 | ||||
|   &-fade-enter&-fade-enter-active, | ||||
|   &-fade-appear&-fade-appear-active { | ||||
|     animation-name: NotificationFadeIn; | ||||
|     animation-play-state: running; | ||||
|   } | ||||
| 
 | ||||
|   &-fade-leave&-fade-leave-active { | ||||
|     animation-name: NotificationFadeOut; | ||||
|     animation-play-state: running; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @keyframes NotificationFadeIn { | ||||
|   0% { | ||||
|     opacity: 0; | ||||
|     left: @notification-width; | ||||
|   } | ||||
|   100% { | ||||
|     left: 0; | ||||
|     opacity: 1; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @keyframes NotificationLeftFadeIn { | ||||
|   0% { | ||||
|     opacity: 0; | ||||
|     right: @notification-width; | ||||
|   } | ||||
|   100% { | ||||
|     right: 0; | ||||
|     opacity: 1; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @keyframes NotificationFadeOut { | ||||
|   0% { | ||||
|     opacity: 1; | ||||
|     margin-bottom: @notification-margin-bottom; | ||||
|     padding-top: @notification-padding; | ||||
|     padding-bottom: @notification-padding; | ||||
|     max-height: 150px; | ||||
|   } | ||||
|   100% { | ||||
|     opacity: 0; | ||||
|     margin-bottom: 0; | ||||
|     padding-top: 0; | ||||
|     padding-bottom: 0; | ||||
|     max-height: 0; | ||||
|   } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	 tjz
						tjz