feat(Notificatoion): add theme to Notification

This commit is contained in:
songwanli2025@163.com 2019-10-18 17:14:47 +08:00
parent 98f97c09ec
commit cc64afeefd
14 changed files with 328 additions and 259 deletions

View File

@ -1,25 +1,17 @@
<template>
<div
ref="doc"
class="n-doc"
ref="doc"
>
<div class="n-doc-header">
<n-gradient-text :font-size="20">
Notification / $nNotify
</n-gradient-text>
<n-gradient-text :font-size="20">Notification / $nNotify</n-gradient-text>
</div>
<div class="n-doc-body">
<div class="n-doc-section">
<div class="n-doc-section__header">
Basic Usage
</div>
<div class="n-doc-section__header">Basic Usage</div>
<div class="n-doc-section__view">
<n-button @click="notify1">
Wouldn't it be Nice
</n-button>
<n-button @click="notify2">
Satisfaction
</n-button>
<n-button @click="notify1">Wouldn't it be Nice</n-button>
<n-button @click="notify2">Satisfaction</n-button>
</div>
<div class="n-doc-section__source">
<textarea>

View File

@ -1,7 +1,7 @@
import Confirm from './src/index.js'
import install from '../../utils/installThemeableComponent'
import { install } from '../../utils/installThemeableComponent'
Confirm.install = function (Vue) {
Confirm.install = function(Vue) {
Confirm.Vue = Vue
install(Vue, Confirm, '$NModal')
}

View File

@ -1,8 +1,8 @@
/* istanbul ignore file */
import LoadingBar from './src/main.js'
import install from '../../utils/installThemeableComponent'
import { install } from '../../utils/installThemeableComponent'
LoadingBar.install = function (Vue) {
LoadingBar.install = function(Vue) {
install(Vue, LoadingBar, '$NLoadingBar')
LoadingBar.Vue = Vue
}

View File

@ -1,7 +1,7 @@
import Message from './src/main.js'
import install from '../../utils/installThemeableComponent'
import { install } from '../../utils/installThemeableComponent'
Message.install = function (Vue) {
Message.install = function(Vue) {
Message.Vue = Vue
install(Vue, Message, '$NMessage')
}

View File

@ -1,13 +1,14 @@
import Message from './Message'
function setTheme (messageContainer) {
const themeClasses = Array.from(messageContainer.classList).filter(c => c.endsWith('-theme'))
function setTheme(messageContainer) {
const themeClasses = Array.from(messageContainer.classList).filter(c =>
c.endsWith('-theme')
)
themeClasses.forEach(c => messageContainer.classList.remove(c))
if (this.theme) messageContainer.classList.add(`n-${this.theme}-theme`)
}
function attachMessageContainer () {
function attachMessageContainer() {
let messageContainer = document.querySelector('.n-message-container')
if (!messageContainer) {
messageContainer = document.createElement('div')
@ -19,14 +20,14 @@ function attachMessageContainer () {
return messageContainer
}
function registerMessageEl (container, el, option) {
function registerMessageEl(container, el, option) {
el.classList.add('n-message--enter')
container.appendChild(el)
el.getBoundingClientRect()
el.classList.remove('n-message--enter')
setTimeout(function () {
setTimeout(function () {
setTimeout(function () {
setTimeout(function() {
setTimeout(function() {
setTimeout(function() {
container.removeChild(el)
}, option.vanishTransitionTimeout)
el.classList.add('n-message--leave')
@ -43,7 +44,7 @@ function registerMessageEl (container, el, option) {
* @param {string} option.icon
* @param {string} option.iconColor
*/
function mixinOption (option) {
function mixinOption(option) {
const defaultOptions = {
duration: 3000,
emergeTransitionTimeout: 300,
@ -67,30 +68,34 @@ const NMessage = {
top: 20
},
attachMessageContainer,
notice (content, option) {
notice(content, option) {
console.log('test', this)
const messageContainer = this.attachMessageContainer()
const messageCell = (new this.Vue({ ...Message, propsData: { option, content } })).$mount()
const messageCell = new this.Vue({
...Message,
propsData: { option, content }
}).$mount()
registerMessageEl(messageContainer, messageCell.$el, mixinOption(option))
},
info (content, option) {
info(content, option) {
option = mixinOption(option)
option.type = 'info'
this.notice(content, option)
},
success (content, option) {
success(content, option) {
option = mixinOption(option)
option.type = 'success'
this.notice(content, option)
},
warning (content, option) {
warning(content, option) {
option = mixinOption(option)
option.type = 'warning'
this.notice(content, option)
},
error (content, option) {
error(content, option) {
option = mixinOption(option)
option.type = 'error'
this.notice(content, (option))
this.notice(content, option)
}
}

View File

@ -1,6 +1,6 @@
import Notification from './src/main.js'
Notification.install = function (Vue) {
Notification.install = function(Vue) {
Vue.prototype.$NNotification = Notification
Vue.prototype.$nNotify = Notification.notify
}

View File

@ -1,47 +1,35 @@
<template>
<div
class="n-notification__cell"
:class="{
[`n-notification__cell--${type}`]: true
}"
class="n-notification__cell 222"
>
<div class="n-notification-cell__wrapper">
<div
v-if="!notification.avator"
class="n-notification-cell__avator"
>
!
</div>
v-if="!notification.avator"
>!</div>
<div
class="n-notification-cell__deactivator"
@click="close"
class="n-notification-cell__deactivator"
/>
<div
ref="body"
class="n-notification-cell__body"
ref="body"
>
<div class="n-notification-cell__header">
{{ notification.title }}
</div>
<div class="n-notification-cell__header">{{ notification.title }}</div>
<div
v-if="notification.titleMeta"
class="n-notification-cell__title-meta"
>
{{ notification.titleMeta }}
</div>
<div class="n-notification-cell__content">
{{ notification.content }}
</div>
v-if="notification.titleMeta"
>{{ 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__meta">{{ notification.meta }}</div>
<div
class="n-notification-cell__action"
@click="handleActionClick"
>
{{ notification.action }}
</div>
class="n-notification-cell__action"
>{{ notification.action }}</div>
</div>
</div>
</div>
@ -49,7 +37,6 @@
</template>
<script>
export default {
props: {
type: {

View File

@ -1,12 +1,26 @@
import Vue from 'vue'
import NNotificationCell from './NotificationCell'
import { getTheme } from '../../../utils/installThemeableComponent'
function attachNotificationContainer () {
let notificationContainer = document.querySelector('.n-notification.n-notification__container')
function setTheme(notificationContainer) {
let theme = getTheme(this)
const themeClasses = Array.from(notificationContainer.classList).filter(c =>
c.endsWith('-theme')
)
themeClasses.forEach(c => notificationContainer.classList.remove(c))
if (theme) notificationContainer.classList.add(`n-${theme}-theme`)
}
function attachNotificationContainer() {
let notificationContainer = document.querySelector(
'.n-notification.n-notification__container'
)
if (!notificationContainer) {
notificationContainer = document.createElement('div')
notificationContainer.classList.add('n-notification', 'n-notification__container')
notificationContainer.classList.add(
'n-notification',
'n-notification__container'
)
notificationContainer.style = `
z-index: 4000;
position: fixed;
@ -35,17 +49,18 @@ const defaultNotification = {
actionCallback: () => {}
}
function mountNotificationEl (container, vm, option) {
function mountNotificationEl(container, vm, option) {
const el = vm.$el
el.classList.add('is-going-to-emerge')
container.appendChild(el)
el.getBoundingClientRect()
el.classList.remove('is-going-to-emerge')
el.style['max-height'] = `${30 + vm.$refs.body.getBoundingClientRect().height}px`
el.style['max-height'] = `${30 +
vm.$refs.body.getBoundingClientRect().height}px`
}
function removeNotificationEl (container, el, option, notificationVueInstance) {
setTimeout(function () {
function removeNotificationEl(container, el, option, notificationVueInstance) {
setTimeout(function() {
if (container.contains(el)) {
container.removeChild(el)
const notification = notificationVueInstance.notification
@ -59,25 +74,27 @@ function removeNotificationEl (container, el, option, notificationVueInstance) {
}
const NMessage = {
notify (notification, type = 'success', option = defaultOptions) {
notify(notification, type = 'success', option = defaultOptions) {
notification = { ...defaultNotification, ...notification }
const notificationContainer = attachNotificationContainer()
const notificationCell = (new Vue({ ...NNotificationCell,
setTheme.call(this, notificationContainer)
const notificationCell = new Vue({
...NNotificationCell,
propsData: { type, notification: notification },
mounted () {
mounted() {
if (notification.duration) {
setTimeout(this.close, notification.duration)
}
},
methods: {
close () {
close() {
removeNotificationEl(notificationContainer, this.$el, option, this)
},
handleActionClick () {
handleActionClick() {
notification.actionCallback(this)
}
}
})).$mount()
}).$mount()
mountNotificationEl(notificationContainer, notificationCell, option)
}
}

View File

@ -1,4 +1,4 @@
function getTheme (component) {
function getTheme(component) {
let cursor = component
while (cursor.$parent) {
const name = cursor.$options.name
@ -13,20 +13,24 @@ function getTheme (component) {
return null
}
function install (Vue, Component, name) {
const prototypeProxy = new Proxy(function () {
return Component
}, {
apply (target, thisArg, argumentsList) {
if (thisArg instanceof Vue) {
Component.theme = getTheme(thisArg)
function install(Vue, Component, name) {
const prototypeProxy = new Proxy(
function() {
return Component
},
{
apply(target, thisArg, argumentsList) {
if (thisArg instanceof Vue) {
Component.theme = getTheme(thisArg)
console.log('theme', getTheme(thisArg))
}
return target.bind(thisArg)(...argumentsList)
}
return target.bind(thisArg)(...argumentsList)
}
})
)
Object.defineProperty(Vue.prototype, name, {
get: prototypeProxy
})
}
export default install
export { getTheme, install }

View File

@ -1,130 +1,168 @@
@import './mixins/mixins.scss';
@import './themes/vars.scss';
@include b(notification) {
&.n-notification__container {
.n-notification__cell {
position: relative;
transform: translateX(0);
display: flex;
overflow: hidden;
transition: opacity .3s $default-cubic-bezier, transform .3s $default-cubic-bezier, max-height .3s $default-cubic-bezier, margin-bottom .3s linear, padding-top .3s $default-cubic-bezier, padding-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;
&.is-going-to-emerge {
opacity: 0;
transform: translateX(calc(100% + 15px));
max-height: 0px;
margin-bottom: 0;
padding-top: 0;
padding-bottom: 0;
.n-notification-cell__avator {
top: 0;
}
.n-notification-cell__close-mark {
top: 0;
}
}
&.is-vanishing {
opacity: 0;
transform: translateX(calc(100% + 15px));
padding-top: 0;
padding-bottom: 0;
max-height: 0;
margin-bottom: 0;
}
.n-notification-cell__wrapper {
position: relative;
width: 100%;
.n-notification-cell__deactivator {
position: absolute;
height: 15px;
width: 15px;
right: 0px;
top: 0px;
transition: top .3s $default-cubic-bezier;
cursor: pointer;
&::before {
box-sizing: content-box;
position: absolute;
transform: rotate(45deg);
height: 6px;
width: 6px;
top: -2px;
content: "";
border-right: 2px solid #a1d9c6;
border-bottom: 2px solid #a1d9c6
}
&::after {
box-sizing: content-box;
position: absolute;
height: 6px;
width: 6px;
content: "";
transform: rotate(45deg);
top: 7px;
border-left: 2px solid #a1d9c6;
border-top: 2px solid #a1d9c6;
}
}
.n-notification-cell__avator {
position: absolute;
height: 28px;
width: 28px;
border-radius: 14px;
background-color: #59C3B2FF;
left: 0px;
top: 0px;
text-align: center;
font-size: 18px;
line-height: 28px;
transition: top .3s $default-cubic-bezier,
}
.n-notification-cell__body {
@include themes-mixin {
@include b(notification) {
&.n-notification__container {
.n-notification__cell {
background: linear-gradient(
225deg,
$--notification-background-start-color 0%,
$--notification-background-end-color 100%
);
color: $--notification-text-color;
@include once {
position: relative;
display: flex;
flex-direction: column;
margin-left: 41px;
font-size: 14px;
width: calc(100% - 41px);
color: #ffffff;
.n-notification-cell__header {
font-weight: 700;
font-size: 16px;
margin-bottom: 8px;
overflow: hidden;
flex-shrink: 0;
box-sizing: border-box;
margin-bottom: 9px;
padding: 15px;
max-height: 400px;
width: 365px;
border-radius: 6px;
box-shadow: 0 2px 25px 0 rgba(0, 0, 0, 0.5);
font-weight: 700;
opacity: 1;
transition: opacity 0.3s $default-cubic-bezier,
transform 0.3s $default-cubic-bezier,
max-height 0.3s $default-cubic-bezier, margin-bottom 0.3s linear,
padding-top 0.3s $default-cubic-bezier,
padding-bottom 0.3s $default-cubic-bezier;
transform: translateX(0);
}
@include once {
&.is-going-to-emerge {
margin-bottom: 0;
padding-top: 0;
padding-bottom: 0;
max-height: 0;
opacity: 0;
transform: translateX(calc(100% + 15px));
.n-notification-cell__avator {
top: 0;
}
.n-notification-cell__close-mark {
top: 0;
}
}
.n-notification-cell__title-meta {
margin-bottom: 8px;
&.is-vanishing {
margin-bottom: 0;
padding-top: 0;
padding-bottom: 0;
max-height: 0;
opacity: 0;
transform: translateX(calc(100% + 15px));
}
.n-notification-cell__title-meta, .n-notification-cell__meta {
font-size: 12px;
color: rgba(255,255,255,.4);
}
.n-notification-cell__wrapper {
position: relative;
width: 100%;
.n-notification-cell__deactivator {
@include once {
position: absolute;
top: 0;
right: 0;
width: 15px;
height: 15px;
cursor: pointer;
transition: top 0.3s $default-cubic-bezier;
}
&::before {
position: absolute;
top: -2px;
box-sizing: content-box;
width: 6px;
height: 6px;
border-right: 2px solid $--notification-cell_deactive-color;
border-bottom: 2px solid $--notification-cell_deactive-color;
content: '';
transform: rotate(45deg);
}
&::after {
position: absolute;
top: 7px;
box-sizing: content-box;
width: 6px;
height: 6px;
border-top: 2px solid $--notification-cell_deactive-color;
border-left: 2px solid $--notification-cell_deactive-color;
content: '';
transform: rotate(45deg);
}
}
.n-notification-cell__content {
white-space: wrap;
color: #ffffff;
.n-notification-cell__avator {
position: absolute;
top: 0;
left: 0;
width: 28px;
height: 28px;
border-radius: 14px;
background-color: #59c3b2ff;
text-align: center;
font-size: 18px;
line-height: 28px;
transition: top 0.3s $default-cubic-bezier;
}
.n-notification-cell__action {
cursor: pointer;
color: #00FFA9FF;
}
.n-notification-cell__footer {
margin-top: 8px;
display: flex;
align-items: center;
justify-content: space-between;
.n-notification-cell__body {
@include once {
display: flex;
flex-direction: column;
margin-left: 41px;
width: calc(100% - 41px);
font-size: 14px;
}
@include once {
.n-notification-cell__title-meta {
margin-bottom: 8px;
}
}
@include once {
.n-notification-cell__footer {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 8px;
}
}
.n-notification-cell__header {
margin-bottom: 8px;
color: $--notification-cell__header-color;
font-weight: 700;
font-size: 16px;
}
.n-notification-cell__title-meta,
.n-notification-cell__meta {
color: $--notification-cell__title-meta-color;
font-size: 12px;
}
.n-notification-cell__content {
color: $--notification-cell__content-color;
white-space: wrap;
}
.n-notification-cell__action {
color: $--notification-cell__action-color;
cursor: pointer;
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,10 @@
@mixin setup-dark-notification {
$--notification-background-start-color: rgb(91, 197, 161) !global;
$--notification-background-end-color: rgba(116,127,157,1) !global;
$--notification-text-color: #ffffff !global;
$--notification-cell_deactive-color: #a1d9c6 !global;
$--notification-cell__header-color: #ffffff !global;
$--notification-cell__content-color: #ffffff !global;
$--notification-cell__title-meta-color: rgba(255,255,255,.4) !global;
$--notification-cell__action-color: #00FFA9FF !global;
}

View File

@ -1,30 +1,31 @@
@import "darkColors.scss";
@import "components/Button.scss";
@import "components/Divider.scss";
@import "components/NimbusServiceLayout.scss";
@import "components/Scrollbar.scss";
@import "components/BaseLoading.scss";
@import "components/BaseSelectMenu.scss";
@import "components/BasePicker.scss";
@import "components/BaseCancelMark.scss";
@import "components/Tag.scss";
@import "components/Table.scss";
@import 'darkColors.scss';
@import 'components/Button.scss';
@import 'components/Divider.scss';
@import 'components/NimbusServiceLayout.scss';
@import 'components/Scrollbar.scss';
@import 'components/BaseLoading.scss';
@import 'components/BaseSelectMenu.scss';
@import 'components/BasePicker.scss';
@import 'components/BaseCancelMark.scss';
@import 'components/Tag.scss';
@import 'components/Table.scss';
@import 'components/AdvanceTable.scss';
@import "components/Popover.scss";
@import "components/Tooltip.scss";
@import "components/Confirm.scss";
@import "components/CheckBox.scss";
@import "components/Switch.scss";
@import "components/Message.scss";
@import "components/LoadingBar.scss";
@import "components/Badge.scss";
@import "components/Dropdown.scss";
@import "components/Input.scss";
@import "components/Alert.scss";
@import "components/Anchor.scss";
@import "components/BackTop.scss";
@import 'components/Popover.scss';
@import 'components/Tooltip.scss';
@import 'components/Confirm.scss';
@import 'components/CheckBox.scss';
@import 'components/Switch.scss';
@import 'components/Message.scss';
@import 'components/LoadingBar.scss';
@import 'components/Badge.scss';
@import 'components/Dropdown.scss';
@import 'components/Input.scss';
@import 'components/Alert.scss';
@import 'components/Anchor.scss';
@import 'components/BackTop.scss';
@import 'components/Notification.scss';
@mixin setup-dark-theme () {
@mixin setup-dark-theme() {
@include setup-dark-colors();
$--n-primary-color: $--primary-6 !global;
$--n-primary-hover-color: $--primary-5 !global;
@ -46,7 +47,7 @@
$--n-table-body-color: $--neutral-9 !global;
$--n-alpha-table-body-color: $--overlay-9 !global;
$--n-card-color: $--neutral-9 !global;
$--n-disabled-text-color: rgba(255, 255, 255, .3) !global;
$--n-disabled-text-color: rgba(255, 255, 255, 0.3) !global;
$--n-dialog-color: $--neutral-3 !global;
$--n-background-color: $--neutral-10 !global;
@include setup-dark-nimbus-service-layout;
@ -73,4 +74,5 @@
@include setup-dark-anchor;
@include setup-dark-alert;
@include setup-dark-back-top;
}
@include setup-dark-notification;
}

View File

@ -0,0 +1,12 @@
@mixin setup-light-notification {
$--notification-background-start-color: rgb(255, 255, 255) !global;
$--notification-background-end-color: rgb(255, 255, 255) !global;
$--notification-text-color: #262626 !global;
$--notification-cell_deactive-color: #b4b4b4 !global;
$--notification-cell__header-color: #262626 !global;
$--notification-cell__content-color: #595959 !global;
$--notification-cell__title-meta-color: #8c8c8c !global;
$--notification-cell__action-color: $--primary-6 !global;
$--notification-cell__avator-background-color: #59c3b2ff !global;
// $--notification-cell__avator-text-color
}

View File

@ -1,30 +1,31 @@
@import 'lightColors.scss';
@import "components/Button.scss";
@import "components/Divider.scss";
@import "components/NimbusServiceLayout.scss";
@import "components/Scrollbar.scss";
@import "components/BaseLoading.scss";
@import "components/BaseSelectMenu.scss";
@import "components/BasePicker.scss";
@import "components/BaseCancelMark.scss";
@import "components/Tag.scss";
@import "components/Table.scss";
@import "components/AdvanceTable.scss";
@import "components/Popover.scss";
@import "components/Tooltip.scss";
@import "components/Confirm.scss";
@import "components/CheckBox.scss";
@import "components/Switch.scss";
@import "components/Message.scss";
@import "components/LoadingBar.scss";
@import "components/Badge.scss";
@import "components/Dropdown.scss";
@import "components/Input.scss";
@import "components/Alert.scss";
@import "components/Anchor.scss";
@import "components/BackTop.scss";
@import 'components/Button.scss';
@import 'components/Divider.scss';
@import 'components/NimbusServiceLayout.scss';
@import 'components/Scrollbar.scss';
@import 'components/BaseLoading.scss';
@import 'components/BaseSelectMenu.scss';
@import 'components/BasePicker.scss';
@import 'components/BaseCancelMark.scss';
@import 'components/Tag.scss';
@import 'components/Table.scss';
@import 'components/AdvanceTable.scss';
@import 'components/Popover.scss';
@import 'components/Tooltip.scss';
@import 'components/Confirm.scss';
@import 'components/CheckBox.scss';
@import 'components/Switch.scss';
@import 'components/Message.scss';
@import 'components/LoadingBar.scss';
@import 'components/Badge.scss';
@import 'components/Dropdown.scss';
@import 'components/Input.scss';
@import 'components/Alert.scss';
@import 'components/Anchor.scss';
@import 'components/BackTop.scss';
@import 'components/Notification.scss';
@mixin setup-light-theme () {
@mixin setup-light-theme() {
@include setup-light-colors();
$--n-primary-color: $--primary-6 !global;
$--n-primary-hover-color: $--primary-5 !global;
@ -33,18 +34,18 @@
$--n-success-color: $--success-6 !global;
$--n-warning-color: $--warning-6 !global;
$--n-error-color: $--error-6 !global;
$n-selected-color: $neutral-7 !global;
$--n-divider-color: $neutral-7 !global;
$--n-border-color: $neutral-6 !global;
$--n-secondary-text-color: $neutral-3 !global;
$--n-text-color: $neutral-2 !global;
$--n-disabled-text-color: $neutral-5 !global;
$--n-card-color: $neutral-10 !global;
$--n-dialog-color: $neutral-10 !global;
$--n-background-color: $neutral-10 !global;
@include setup-light-nimbus-service-layout;
@include setup-light-divider;
@include setup-light-scrollbar;
@ -69,4 +70,5 @@
@include setup-light-anchor;
@include setup-light-alert;
@include setup-light-back-top;
}
@include setup-light-notification;
}