mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-04-12 14:40:47 +08:00
feat: tooltip
This commit is contained in:
parent
da34b9c340
commit
b309d9b87b
@ -25,3 +25,5 @@ installNaiveUiTo(Vue)
|
||||
import 'naive-ui/dist/lib/index.css'
|
||||
...
|
||||
```
|
||||
# Todo
|
||||
Z-index management on `Select` & `Tooltip` & `Modal`! 这几个东西的顺序管理实在是有点麻烦,放在之后完善吧...
|
@ -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 {
|
||||
|
47
demo/components/tooltipDemo.vue
Normal file
47
demo/components/tooltipDemo.vue
Normal 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>
|
@ -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;
|
||||
|
@ -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({
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "naive-ui",
|
||||
"version": "0.1.39",
|
||||
"version": "0.1.40",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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>
|
||||
|
7
packages/common/Tooltip/index.js
Normal file
7
packages/common/Tooltip/index.js
Normal file
@ -0,0 +1,7 @@
|
||||
import Tooltip from './src/main.vue'
|
||||
|
||||
Tooltip.install = function (Vue) {
|
||||
Vue.component(Tooltip.name, Tooltip)
|
||||
}
|
||||
|
||||
export default Tooltip
|
61
packages/common/Tooltip/src/main.vue
Normal file
61
packages/common/Tooltip/src/main.vue
Normal 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>
|
@ -49,6 +49,7 @@ export default {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.n-nimbus-form-card {
|
||||
position: relative;
|
||||
min-width: 600px;
|
||||
width: 1032px;
|
||||
margin: auto;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
37
styles/Tooltip.scss
Normal 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;
|
||||
}
|
||||
}
|
@ -14,5 +14,6 @@
|
||||
@import './Input.scss';
|
||||
@import './Select.scss';
|
||||
@import './Message.scss';
|
||||
@import './Tooltip.scss';
|
||||
|
||||
@import './NimbusServiceLayout.scss';
|
Loading…
x
Reference in New Issue
Block a user