feat: tooltip

This commit is contained in:
07akioni 2019-06-20 12:46:29 +08:00
parent da34b9c340
commit b309d9b87b
16 changed files with 232 additions and 44 deletions

View File

@ -25,3 +25,5 @@ installNaiveUiTo(Vue)
import 'naive-ui/dist/lib/index.css'
...
```
# Todo
Z-index management on `Select` & `Tooltip` & `Modal`! 这几个东西的顺序管理实在是有点麻烦,放在之后完善吧...

View File

@ -5,7 +5,8 @@
<h2>基本用法</h2>
<n-checkbox v-model="checked">
Nimbus
</n-checkbox><br>{{ String(checked) }}
</n-checkbox><br>
<n-checkbox v-model="checked" /><br>{{ String(checked) }}
<br>
<textarea rows="5"><n-checkbox v-model="checked">
Nimbus
@ -15,7 +16,9 @@
</template>
<script>
import docCodeEditorMixin from './docCodeEditorMixin'
export default {
mixins: [docCodeEditorMixin],
props: {},
data () {
return {

View File

@ -0,0 +1,47 @@
<template>
<div
ref="doc"
class="doc"
>
<h1>n-tooltip</h1>
<hr>
<h2>基本用法</h2>
<n-tooltip>
<template v-slot:activator>
<button>hello tooltip</button>
</template>
<div>
This is the contextual help
</div>
</n-tooltip>
<br>
<textarea rows="5"><n-tooltip>
<template v-slot:activator>
scaffold
</template>
<div>
This is the contextual help
</div>
</n-tooltip></textarea>
<hr>
</div>
</template>
<script>
import docCodeEditorMixin from './docCodeEditorMixin'
export default {
mixins: [docCodeEditorMixin]
}
</script>
<style scoped lang="scss">
.doc {
width: 900px;
margin: auto;
textarea {
width: 100%;
min-height: 3em;
}
}
</style>

View File

@ -50,6 +50,10 @@
<router-link to="/n-message">
通知 / $NMessage
</router-link>
<br>
<router-link to="/n-tooltip">
帮助 / n-tooltip
</router-link>
</div>
</div>
</template>
@ -73,6 +77,7 @@ export default {
.CodeMirror {
border: 1px solid #eee;
height: auto;
z-index: -1;
}
.CodeMirror-scroll {
overflow-y: hidden;

View File

@ -19,6 +19,7 @@ import Input from '../packages/common/Input'
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 ServiceCard from 'packages/nimbus/ServiceCard'
import HomeLayout from 'packages/nimbus/HomeLayout'
@ -38,7 +39,8 @@ import inputDemo from './components/inputDemo'
import selectDemo from './components/selectDemo'
import modalDemo from './components/modalDemo'
import nimbusFormCardDemo from './components/nimbusFormCardDemo'
import MessageDemo from './components/messageDemo'
import messageDemo from './components/messageDemo'
import tooltipDemo from './components/tooltipDemo'
import demo from './demo'
Vue.use(VueRouter)
@ -64,6 +66,7 @@ Select.install(Vue)
Modal.install(Vue)
NimbusFormCard.install(Vue)
Message.install(Vue)
Tooltip.install(Vue)
const routes = [
{ path: '/', component: demo },
@ -79,7 +82,8 @@ const routes = [
{ path: '/n-select', component: selectDemo },
{ path: '/n-modal', component: modalDemo },
{ path: '/n-nimbus-form-card', component: nimbusFormCardDemo },
{ path: '/n-message', component: MessageDemo }
{ path: '/n-message', component: messageDemo },
{ path: '/n-tooltip', component: tooltipDemo }
]
const router = new VueRouter({

View File

@ -1,6 +1,6 @@
{
"name": "naive-ui",
"version": "0.1.39",
"version": "0.1.40",
"description": "",
"main": "index.js",
"scripts": {

View File

@ -4,15 +4,18 @@
@click="handleClick"
>
<div
class="checkbox"
:class="{checked:checked}"
class="n-checkbox__checkbox"
:class="{'is-checked':checked}"
>
<div
class="inner"
:class="{checked:checked}"
class="n-checkbox-checkbox__inner"
:class="{'is-checked':checked}"
/>
</div>
<div class="label">
<div
v-if="$slots.default"
class="n-checkbox__label"
>
<slot />
</div>
</div>

View File

@ -20,7 +20,7 @@ function attachMessageContainer () {
flex-direction: column;
align-items: center;
`
document.body.insertBefore(messageContainer, document.body.firstElementChild)
document.body.appendChild(messageContainer)
}
return messageContainer
}

View File

@ -19,27 +19,26 @@ export default {
}
},
watch: {
isActive (val) {
if (!val) {
this.removeOverlay()
} else {
this.addOverlayToApp()
}
}
// isActive (val) {
// if (!val) {
// this.removeOverlay()
// } else {
// this.addOverlayToApp()
// }
// }
},
beforeMount () {
const app = document.querySelector('#app')
console.log()
const app = document.querySelector('body')
if (!app) {
console.warn('Modal will be mounted to #app element, but it doesn\'t exist! Modal component won\'t work!')
console.warn('Modal will be mounted to body element, but it doesn\'t exist! Modal component won\'t work!')
}
},
mounted () {
this.app = document.querySelector('#app')
this.app = document.querySelector('body')
this.detachContentToApp()
},
beforeDestroy () {
this.removeOverlay()
// this.removeOverlay()
this.app.removeChild(this.$refs.content)
},
methods: {
@ -49,7 +48,8 @@ export default {
overlay = document.createElement('div')
overlay.classList.add('n-modal-overlay')
overlay.id = 'overlay'
this.app.insertBefore(overlay, this.app.firstElementChild)
this.app.append(overlay)
// this.app.insertBefore(overlay, this.app.firstElementChild)
this.overlay = overlay
}
},
@ -63,11 +63,15 @@ export default {
detachContentToApp () {
this.$refs.content.parentNode.removeChild(this.$refs.content)
this.content = this.$refs.content
this.app.insertBefore(this.content, this.app.firstElementChild)
// this.addOverlayToApp()
this.app.append(this.content)
// this.app.insertBefore(this.content, this.app.firstElementChild)
}
},
render (h) {
return h('div', [
return h('div', {
staticClass: 'n-modal-activator'
}, [
this.$slots.activator,
h('div', {
staticClass: 'n-modal-content',
@ -76,7 +80,13 @@ export default {
'is-active': this.isActive
}
},
this.$slots.default
[h('div', {
staticClass: 'n-modal-overlay',
ref: 'overlay',
class: {
'is-active': this.isActive
}
}), ...this.$slots.default]
)
])
}
@ -84,6 +94,10 @@ export default {
</script>
<style lang="scss">
.n-modal-activator {
display: inline-block;
}
.n-modal-overlay {
position: fixed;
left: 0;
@ -91,7 +105,10 @@ export default {
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .35);
z-index: 200;
display: none;
&.is-active {
display: block;
}
}
.n-modal-content {
@ -101,11 +118,10 @@ export default {
top: 0;
bottom: 0;
display: flex;
z-index: 201;
visibility: hidden;
display: none;
overflow: auto;
&.is-active {
visibility: visible;
display: block;
}
}
</style>

View File

@ -0,0 +1,7 @@
import Tooltip from './src/main.vue'
Tooltip.install = function (Vue) {
Vue.component(Tooltip.name, Tooltip)
}
export default Tooltip

View File

@ -0,0 +1,61 @@
<template>
<div
class="n-tooltip"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
>
<div
class="n-tooltip__content"
>
<slot name="activator" />
</div>
<div
class="n-tooltip__popup"
:class="{
'is-hidden': isHidden,
'has-emerged': hasEmerged,
'is-vanishing': isVanishing
}"
>
<div class="n-tooltip-popup__content">
<slot />
</div>
</div>
</div>
</template>
<script>
export default {
name: 'NTooltip',
data () {
return {
timeoutId: null,
delayTimeout: null,
isHidden: true,
hasEmerged: false,
isVanishing: false
}
},
methods: {
handleMouseEnter () {
if (this.timeoutId) {
clearTimeout(this.timeoutId)
this.isVanishing = false
}
this.isHidden = false
this.hasEmerged = true
this.$nextTick(() => {
this.$el.getBoundingClientRect()
this.hasEmerged = false
})
},
handleMouseLeave (x) {
this.isVanishing = true
this.timeoutId = setTimeout(() => {
this.isHidden = true
this.isVanishing = false
}, 300)
}
}
}
</script>

View File

@ -49,6 +49,7 @@ export default {
<style lang="scss" scoped>
.n-nimbus-form-card {
position: relative;
min-width: 600px;
width: 1032px;
margin: auto;

View File

@ -7,25 +7,26 @@
justify-content: center;
cursor: pointer;
}
.label {
font-size: 12px;
.n-checkbox__label {
font-size: 13px;
color: #63E2B7;
margin-left: 6px;
}
.checkbox {
.n-checkbox__checkbox {
& {
height: 15px;
width: 15px;
margin-right: 6px;
height: 14px;
width: 14px;
box-sizing: border-box;
border: 1px solid #63E2B7;
background-color: transparent;
border-radius: 4px;
position: relative;
}
&.checked {
&.is-checked {
background-color: #63E2B7;
}
.inner {
.n-checkbox-checkbox__inner {
&::after {
box-sizing: content-box;
content: "";
@ -33,14 +34,14 @@
border-left: 0;
border-top: 0;
height: 8px;
left: 5px;
left: 4px;
position: absolute;
top: 2px;
top: 0px;
transform: rotate(45deg) scaleY(0);
width: 3px;
transform-origin: center;
}
&.checked::after {
&.is-checked::after {
transform: rotate(45deg) scaleY(1);
}
}

View File

@ -69,10 +69,10 @@
}
}
.n-select-menu {
z-index: 100;
z-index: 1;
overflow: hidden;
position: absolute;
visibility: hidden;
display: none;
top: calc(100% + 4px);
left: 0;
right: 0;
@ -119,7 +119,7 @@
}
&.is-active {
.n-select-menu {
visibility: visible;
display: block;
}
&::after {
transform: rotate(135deg);

37
styles/Tooltip.scss Normal file
View File

@ -0,0 +1,37 @@
@import './mixins/mixins.scss';
@import './theme/default.scss';
@include b(tooltip) {
& {
display: inline-block;
position: relative;
}
.n-tooltip__popup.is-hidden {
display: none;
}
.n-tooltip__popup.has-emerged {
opacity: 0;
transform: translateX(-50%);
}
.n-tooltip__popup {
z-index: 1;
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
padding-top: 2px;
opacity: 1;
transition: opacity .3s $default-cubic-bezier, transform .3s $default-cubic-bezier;
.n-tooltip-popup__content {
white-space: nowrap;
border-radius: 6px;
background-color: rgba(75,81,106,1);
color: #FFFFFFE6;
padding: 8px 14px;
font-size: 12px;
}
}
.n-tooltip__popup.is-vanishing {
opacity: 0;
}
}

View File

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