feat: notification

This commit is contained in:
07akioni 2019-06-20 19:10:53 +08:00
parent b342cd82e4
commit 6c1e292422
13 changed files with 309 additions and 10 deletions

View File

@ -0,0 +1,58 @@
<template>
<div
ref="doc"
class="doc"
>
<h1>Message</h1>
<hr>
<h2>基本用法</h2>
<button @click="emitMessage">
爱你那么用力却好像一场闹剧
</button>
<br><br>
<textarea rows="5"><button @click="emitMessage">
爱你那么用力却好像一场闹剧
</button>
<script>
emitMessage () {
this.$NMessage.error('Oops, here is a error')
this.$NMessage.success('Cloned Successfully')
}
</script>
</textarea>
<hr>
</div>
</template>
<script>
import docCodeEditorMixin from './docCodeEditorMixin'
export default {
mixins: [docCodeEditorMixin],
methods: {
emitMessage () {
this.$NNotification.notify({
title: 'Notification',
titleMeta: 'From Xingyue Feng',
content: 'VTS has been edited by admin',
meta: '2019-5-27 15:11',
action: 'Mark as read',
actionCallback: () => {}
})
}
}
}
</script>
<style scoped lang="scss">
.doc {
width: 900px;
margin: auto;
textarea {
width: 100%;
min-height: 3em;
}
}
</style>

View File

@ -14,7 +14,7 @@
This is the contextual help
</div>
</n-tooltip>
<br>
<br><br>
<textarea rows="5"><n-tooltip>
<template v-slot:activator>
scaffold

View File

@ -54,6 +54,10 @@
<router-link to="/n-tooltip">
帮助 / n-tooltip
</router-link>
<br>
<router-link to="/n-notification">
通知 / $NNotification
</router-link>
</div>
</div>
</template>

View File

@ -20,6 +20,7 @@ import Select from '../packages/common/Select'
import Modal from '../packages/common/Modal'
import Message from '../packages/common/Message'
import Tooltip from '../packages/common/Tooltip'
import Notification from '../packages/common/Notification'
import ServiceCard from 'packages/nimbus/ServiceCard'
import HomeLayout from 'packages/nimbus/HomeLayout'
@ -41,6 +42,7 @@ import modalDemo from './components/modalDemo'
import nimbusFormCardDemo from './components/nimbusFormCardDemo'
import messageDemo from './components/messageDemo'
import tooltipDemo from './components/tooltipDemo'
import notificationDemo from './components/notificationDemo'
import demo from './demo'
Vue.use(VueRouter)
@ -67,6 +69,7 @@ Modal.install(Vue)
NimbusFormCard.install(Vue)
Message.install(Vue)
Tooltip.install(Vue)
Notification.install(Vue)
const routes = [
{ path: '/', component: demo },
@ -83,7 +86,8 @@ const routes = [
{ path: '/n-modal', component: modalDemo },
{ path: '/n-nimbus-form-card', component: nimbusFormCardDemo },
{ path: '/n-message', component: messageDemo },
{ path: '/n-tooltip', component: tooltipDemo }
{ path: '/n-tooltip', component: tooltipDemo },
{ path: '/n-notification', component: notificationDemo }
]
const router = new VueRouter({

View File

@ -13,6 +13,7 @@ import Switch from './packages/common/Switch'
import Select from './packages/common/Select'
import Modal from './packages/common/Modal'
import Input from './packages/common/Input'
import Message from './packages/common/Message'
import ServiceCard from './packages/nimbus/ServiceCard'
import HomeLayout from './packages/nimbus/HomeLayout'
@ -41,6 +42,7 @@ function installUiToVue (Vue) {
Modal.install(Vue)
NimbusFormCard.install(Vue)
Input.install(Vue)
Message.install(Vue)
}
export default installUiToVue

View File

@ -0,0 +1,7 @@
import Notification from './src/main.js'
Notification.install = function (Vue) {
Vue.prototype.$NNotification = Notification
}
export default Notification

View File

@ -0,0 +1,53 @@
<template>
<div
class="n-notification__cell"
:class="{
[`n-notification__cell--${type}`]: true
}"
>
<div class="n-notification-cell__avator" />
<div class="n-notification-cell__body">
<div class="n-notification-cell__header">
{{ notification.title }}
</div>
<div class="n-notification-cell__title-meta">
{{ notification.titleMeta }}
</div>
<div class="n-notification-cell__content">
{{ notification.content }}
</div>
<div class="n-notification-cell__footer">
<div class="n-notification-cell__meta">
{{ notification.meta }}
</div>
<div class="n-notification-cell__action">
{{ notification.action }}
</div>
</div>
</div>
</div>
</template>
<script>
import NIcon from '../../Icon/index'
export default {
components: {
NIcon
},
props: {
type: {
type: String,
default: 'success'
},
content: {
type: String,
default: ''
},
notification: {
type: Object,
default: null
}
}
}
</script>

View File

@ -0,0 +1,57 @@
import Vue from 'vue'
import NMessageCell from './MessageCell'
function attachMessageContainer () {
let notificationContainer = document.querySelector('.n-notification.n-notification__container')
console.log(notificationContainer)
if (!notificationContainer) {
notificationContainer = document.createElement('div')
notificationContainer.classList.add('n-notification', 'n-notification__container')
notificationContainer.style = `
z-index: 300;
position: fixed;
left: 0;
right: 15px;
top: 10px;
height: 0;
overflow: visible;
display: flex;
flex-direction: column;
align-items: flex-end;
`
document.body.appendChild(notificationContainer)
}
return notificationContainer
}
const defaultOptions = {
timeout: 50000,
emergeTransitionTimeout: 300,
vanishTransitionTimeout: 300
}
function registerMessageEl (container, el, option) {
el.classList.add('is-going-to-emerge')
container.appendChild(el)
el.getBoundingClientRect()
el.classList.remove('is-going-to-emerge')
setTimeout(function () {
setTimeout(function () {
setTimeout(function () {
container.removeChild(el)
}, option.vanishTransitionTimeout)
el.classList.add('is-vanishing')
}, option.timeout)
}, option.emergeTransitionTimeout)
}
const NMessage = {
notify (notification, type = 'success', option = defaultOptions) {
const notificationContainer = attachMessageContainer()
const notificationCell = (new Vue({ ...NMessageCell, propsData: { type, notification: notification } })).$mount()
registerMessageEl(notificationContainer, notificationCell.$el, option)
}
}
export default NMessage

View File

@ -44,10 +44,15 @@ export default {
}
this.isHidden = false
this.hasEmerged = true
this.$nextTick(() => {
this.$el.getBoundingClientRect()
this.hasEmerged = false
})
this
.$nextTick()
.then(vm => {
vm.$el.getBoundingClientRect()
return this.$nextTick()
})
.then(vm => {
vm.hasEmerged = false
})
},
handleMouseLeave (x) {
this.isVanishing = true

View File

@ -131,8 +131,8 @@ export default {
bottom: 0;
left: 0;
right: 0;
z-index: 0;
}
.body {
& {
padding: 21px 48px;

107
styles/Notification.scss Normal file
View File

@ -0,0 +1,107 @@
@import './mixins/mixins.scss';
@import './theme/default.scss';
@include b(notification) {
&.n-notification__container {
.n-notification__cell {
&.is-going-to-emerge {
opacity: 0;
transform: translateX(calc(100% + 15px));
max-height: 0px;
margin-bottom: 0;
}
& {
position: relative;
transform: translateX(0);
display: flex;
transition: opacity .3s $default-cubic-bezier, transform .3s $default-cubic-bezier, max-height .3s $default-cubic-bezier, margin-bottom .3s $default-cubic-bezier;
opacity: 1;
margin-bottom: 9px;
width:365px;
padding: 15px;
box-sizing: border-box;
max-height: 400px;
background:linear-gradient(225deg,rgba(91,197,161,1) 0%,rgba(116,127,157,1) 100%);
box-shadow:0px 2px 25px 0px rgba(0,0,0,0.5);
border-radius:6px;
flex-shrink: 0;
font-weight: 700;
color: #ffffff;
.n-notification-cell__avator {
position: absolute;
height: 28px;
width: 28px;
border-radius: 14px;
background-color: #59C3B2FF;
left: 15px;
top: 15px;
}
.n-notification-cell__body {
display: flex;
flex-direction: column;
margin-left: 41px;
font-size: 14px;
width: 100%;
color: #ffffff;
.n-notification-cell__header {
font-weight: 700;
font-size: 16px;
margin-bottom: 6px;
}
.n-notification-cell__title-meta {
margin-bottom: 8px;
}
.n-notification-cell__title-meta, .n-notification-cell__meta {
font-size: 12px;
color: rgba(255,255,255,.4);
}
.n-notification-cell__content {
color: #ffffff;
margin-bottom: 7px;
}
.n-notification-cell__action {
cursor: pointer;
color: #00FFA9FF;
}
.n-notification-cell__footer {
display: flex;
align-items: center;
justify-content: space-between;
}
}
.n-notification-cell__icon {
margin-right: 11px;
display: inline-flex;
height: 40px;
line-height: 40px;
align-items: center;
i::before {
font-size: 20px;
}
}
&.n-notification__cell--success {
background-color: #2F6C66FF;
.n-notification-cell__icon {
i::before {
color: #63E2B7FF
}
}
}
&.n-notification__cell--error {
background-color: #D03A52FF;
.n-notification-cell__icon {
i::before {
color: #FF92A4FF
}
}
}
}
&.is-vanishing {
opacity: 0;
transform: translateX(calc(100% + 15px));
max-height: 0px;
margin-bottom: 0;
}
}
}
}

View File

@ -10,15 +10,15 @@
display: none;
}
.n-tooltip__popup.has-emerged {
opacity: 0;
transform: translateX(-50%);
opacity: .5;
transform: translateX(-50%) translateY(4px);
}
.n-tooltip__popup {
z-index: 1;
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
transform: translateX(-50%) translateY(0px);
padding-top: 2px;
opacity: 1;
transition: opacity .3s $default-cubic-bezier, transform .3s $default-cubic-bezier;
@ -33,5 +33,6 @@
}
.n-tooltip__popup.is-vanishing {
opacity: 0;
transform: translateX(-50%) translateY(4px);
}
}

View File

@ -15,5 +15,6 @@
@import './Select.scss';
@import './Message.scss';
@import './Tooltip.scss';
@import './Notification.scss';
@import './NimbusServiceLayout.scss';