-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
315 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
<html> | ||
<head> | ||
<title>Tooltip Example</title> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/6.0.0/normalize.css"> | ||
<style> | ||
body, | ||
html { | ||
min-height: 100%; | ||
} | ||
|
||
* { | ||
outline: none; | ||
} | ||
|
||
code { | ||
background: #eee; | ||
display: inline-block; | ||
margin: 5px 0; | ||
padding: 6px; | ||
} | ||
|
||
button { | ||
transition: background .3s; | ||
background: #4196ff; | ||
border: 1px solid #004edc; | ||
border-radius: 3px; | ||
color: #fff; | ||
} | ||
|
||
button:hover { | ||
background: #7eb8ff; | ||
} | ||
|
||
.tooltip-target { | ||
color:cornflowerblue; | ||
text-decoration: underline; | ||
} | ||
|
||
.vue-tooltip.tooltip-custom { | ||
background-color: red; | ||
} | ||
|
||
.vue-tooltip.tooltip-custom[x-placement^="top"] [x-arrow] { | ||
border-top-color: red; | ||
} | ||
|
||
.vue-tooltip.tooltip-custom[x-placement^="bottom"] [x-arrow] { | ||
border-bottom-color: red; | ||
} | ||
|
||
.vue-tooltip.tooltip-custom[x-placement^="left"] [x-arrow] { | ||
border-left-color: red; | ||
} | ||
|
||
.vue-tooltip.tooltip-custom[x-placement^="right"] [x-arrow] { | ||
border-right-color: red; | ||
} | ||
</style> | ||
<link rel="stylesheet" href="../css/index.css"> | ||
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script> | ||
<script src="../dist/vueDirectiveTooltip.js"></script> | ||
</head> | ||
<body> | ||
<div id="app"> | ||
<h2>Vue.js Tooltip directive <img src="https://img.shields.io/badge/vue-2-green.svg" alt="Vue.js v2+"></h2> | ||
<section> | ||
<h3>Usage</h3> | ||
|
||
<h4>With Webpack, Rollup, etc...</h4> | ||
<p> | ||
<pre><code> | ||
// in your js file | ||
import Vue from 'vue'; | ||
import Tooltip from 'vue-directive-tooltip'; | ||
// or require('vue-directive-tooltip'); | ||
import App from './App.vue'; | ||
</code></pre> | ||
</p> | ||
|
||
<h4>With tag directly in the page</h4> | ||
<p> | ||
<pre><code> | ||
<link rel="stylesheet" href="path/to/css/index.css"> | ||
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script> | ||
<script src="path/to/vueDirectiveTooltip.js"></script> | ||
</code></pre> | ||
</p> | ||
</section> | ||
<section> | ||
<h3>Positioning</h3> | ||
<p> | ||
Default <span class="tooltip-target" v-tooltip="'bottom'">position</span> | ||
<code><span v-tooltip="'I am on the bottom'"...</code> | ||
</p> | ||
<p> | ||
Position <span class="tooltip-target" v-tooltip.right="'I am on the right'">right</span> | ||
<code><span v-tooltip.right="'I am on the right'"...</code> | ||
</p> | ||
<p> | ||
Position <span class="tooltip-target" v-tooltip.top="'I am on the top'">top</span> | ||
<code><span v-tooltip.top="'I am on the top'"...</code> | ||
</p> | ||
<p> | ||
I need a longer sentence to position <span class="tooltip-target" v-tooltip.left="'I am on the left'">left</span> | ||
<code><span v-tooltip.left="'I am on the left'"...</code> | ||
</p> | ||
</section> | ||
<section> | ||
<h3>Options</h3> | ||
|
||
<h4>Content</h4> | ||
<p> | ||
Simple way <span class="tooltip-target" v-tooltip="'simple way'">to set text</span> | ||
<code><span v-tooltip="'simple way'"...</code> | ||
</p> | ||
<p> | ||
"Option" way <span class="tooltip-target" v-tooltip="{ content: 'option way' }">to set text</span> | ||
<code><span v-tooltip="{ content: 'option way' }"...</code> | ||
</p> | ||
|
||
<h4>Visibility</h4> | ||
<p> | ||
In case you need to hide a tooltip, you can use the <b class="tooltip-target" v-tooltip.top="{ content: 'change the visibility', visible: visibility }">visible</b> option | ||
</p> | ||
<p> | ||
<code><span v-tooltip="{ content: 'change the visibility', visible: <span v-text="visibility"></span> }"...</code> | ||
</p> | ||
<p> | ||
<button @click="visibility = !visibility"> | ||
<span v-if="visibility">hide</span> | ||
<span v-else>show</span> | ||
tooltip | ||
</button> | ||
</p> | ||
|
||
<h4>Custom CSS classes</h4> | ||
<p> | ||
Add your custom CSS classes to change the <span class="tooltip-target" v-tooltip.top="{ content: 'custom class', class: 'tooltip-custom tooltip-other-custom' }">tooltip appearance</span> | ||
</p> | ||
<p> | ||
<code><span v-tooltip="{ content: 'custom class', class: 'tooltip-custom tooltip-other-custom' }"...</code> | ||
</p> | ||
<p> | ||
CSS | ||
<pre><code> | ||
.vue-tooltip.tooltip-custom { | ||
background-color: red; | ||
} | ||
|
||
.vue-tooltip.tooltip-custom[x-placement^="top"] [x-arrow] { | ||
border-top-color: red; | ||
} | ||
|
||
.vue-tooltip.tooltip-custom[x-placement^="bottom"] [x-arrow] { | ||
border-bottom-color: red; | ||
} | ||
|
||
.vue-tooltip.tooltip-custom[x-placement^="left"] [x-arrow] { | ||
border-left-color: red; | ||
} | ||
|
||
.vue-tooltip.tooltip-custom[x-placement^="right"] [x-arrow] { | ||
border-right-color: red; | ||
} | ||
</code></pre> | ||
</p> | ||
</section> | ||
</div> | ||
|
||
<script> | ||
new Vue({ el: '#app', data() { | ||
return { | ||
visibility: true | ||
}; | ||
} }); | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/** | ||
* @author: laurent blanes <[email protected]> | ||
*/ | ||
import Popper from 'popper.js'; | ||
|
||
const BASE_CLASS = 'vue-tooltip'; | ||
|
||
/** | ||
* usage: | ||
* | ||
* // basic usage: | ||
* <div v-tooltip="'my content'"> | ||
* or | ||
* <div v-tooltip="{content: 'my content'}"> | ||
* | ||
* // change position of tooltip | ||
* // options: bottom (default) | top | left | right | ||
* <div v-tooltip.top="{content: 'my content'}"> | ||
* | ||
* // add custom class | ||
* <div v-tooltip="{class: 'custom-class', content: 'my content'}"> | ||
* | ||
* // toggle visibility | ||
* <div v-tooltip="{visible: false, content: 'my content'}"> | ||
*/ | ||
export default { | ||
name: 'tooltip', | ||
config: {}, | ||
install (Vue) { | ||
Vue.directive('tooltip', { | ||
bind (el, binding, vnode) { | ||
let $popper = null; | ||
let placement = 'bottom'; | ||
|
||
if (binding.modifiers.left) { | ||
placement = 'left'; | ||
} else if (binding.modifiers.right) { | ||
placement = 'right'; | ||
} else if (binding.modifiers.top) { | ||
placement = 'top'; | ||
} else if (binding.modifiers.bottom) { | ||
placement = 'bottom'; | ||
} | ||
|
||
// wrapper | ||
$popper = document.createElement('div'); | ||
$popper.setAttribute('class', BASE_CLASS); | ||
Popper.Utils.setStyles($popper, {visibility: 'hidden'}); | ||
|
||
// make arrow | ||
let $arrow = document.createElement('div'); | ||
$arrow.setAttribute('x-arrow', ''); | ||
$popper.appendChild($arrow); | ||
|
||
// make content container | ||
let $content = document.createElement('div'); | ||
$content.setAttribute('class', 'vue-tooltip-content'); | ||
$popper.appendChild($content); | ||
|
||
document.querySelector('body').appendChild($popper); | ||
|
||
const options = Object.assign({}, | ||
binding.value, | ||
{ | ||
placement, | ||
onCreate (e) { | ||
setProperties(el, binding); | ||
setAttributes($popper, $content, el); | ||
}, | ||
onUpdate (e) { | ||
setAttributes($popper, $content, el); | ||
} | ||
} | ||
); | ||
el.popper = new Popper(el, $popper, options); | ||
}, | ||
inserted (el, binding, vnode, oldVnode) { | ||
el.addEventListener('mouseover', onMouseOver); | ||
el.addEventListener('mouseout', onMouseOut); | ||
el.addEventListener('mouseleave', onMouseOut); | ||
}, | ||
componentUpdated (el, binding, vnode, oldVnode) { | ||
setProperties(el, binding); | ||
}, | ||
unbind (el, binding, vnode, oldVnode) { | ||
el.removeEventListener('mouseover', onMouseOver); | ||
el.removeEventListener('mouseout', onMouseOut); | ||
el.removeEventListener('mouseleave', onMouseOut); | ||
document.querySelector('body').removeChild(el.popper.popper); | ||
} | ||
}); | ||
} | ||
}; | ||
|
||
function setProperties (el, binding) { | ||
if (typeof binding.value === 'string') { | ||
el.popper._class = ''; | ||
el.popper._content = binding.value; | ||
el.popper._visible = true; | ||
} else { | ||
el.popper._class = binding.value.class || ''; | ||
el.popper._content = binding.value.content; | ||
el.popper._visible = binding.value.visible !== false; | ||
} | ||
} | ||
|
||
function setAttributes ($popper, $content, el) { | ||
$content.innerHTML = el.popper._content; | ||
Popper.Utils.setStyles(el.popper.popper, { | ||
display: el.popper._visible ? 'inline-block' : 'none' | ||
}); | ||
const classes = `${BASE_CLASS} ${el.popper._class}`; | ||
$popper.setAttribute('class', classes.trim()); | ||
} | ||
|
||
function onMouseOver (e) { | ||
const el = e.target; | ||
Popper.Utils.setStyles(el.popper.popper, {visibility: 'visible'}); | ||
el.popper.update(); | ||
} | ||
|
||
function onMouseOut (e) { | ||
const el = e.target; | ||
Popper.Utils.setStyles(el.popper.popper, {visibility: 'hidden'}); | ||
} |