diff --git a/components/notification/demo/basic.md b/components/notification/demo/basic.md new file mode 100644 index 000000000..e69de29bb diff --git a/components/notification/index.en-US.md b/components/notification/index.en-US.md new file mode 100644 index 000000000..3b9af9239 --- /dev/null +++ b/components/notification/index.en-US.md @@ -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 | diff --git a/components/notification/index.vue b/components/notification/index.vue new file mode 100644 index 000000000..fabfea257 --- /dev/null +++ b/components/notification/index.vue @@ -0,0 +1,201 @@ + \ No newline at end of file diff --git a/components/notification/index.zh-CN.md b/components/notification/index.zh-CN.md new file mode 100644 index 000000000..1b79dd3c4 --- /dev/null +++ b/components/notification/index.zh-CN.md @@ -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 | diff --git a/components/notification/style/index.js b/components/notification/style/index.js new file mode 100644 index 000000000..cf31ed80f --- /dev/null +++ b/components/notification/style/index.js @@ -0,0 +1,2 @@ +import '../../style/index.less' +import './index.less' diff --git a/components/notification/style/index.less b/components/notification/style/index.less new file mode 100644 index 000000000..abaaf1f20 --- /dev/null +++ b/components/notification/style/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; + } +}