Tooltip component now works on mobile
This commit is contained in:
parent
f9c289aacd
commit
519dc8de22
@ -46,6 +46,7 @@
|
||||
"mini-css-extract-plugin": "^0.4.2",
|
||||
"portal-vue": "^2.1.7",
|
||||
"vue-dragscroll": "^1.10.2",
|
||||
"vue-fragment": "^1.5.1",
|
||||
"vue-removed-hook-mixin": "^0.1.1",
|
||||
"vue2-leaflet": "^1.0.2",
|
||||
"vuex": "^3.0.1",
|
||||
|
@ -1,7 +1,10 @@
|
||||
<portal to="popups">
|
||||
<transition name="fade">
|
||||
<popper class="popper--tooltip" arrow :reference="element" :placement="placement" v-if="show" :responsive="false">
|
||||
<slot />
|
||||
</popper>
|
||||
</transition>
|
||||
</portal>
|
||||
<fragment>
|
||||
<portal to="popups">
|
||||
<transition name="tooltip">
|
||||
<popper class="popper--tooltip" aria-hidden="true" arrow :reference="root" :placement="placement" v-if="show" :responsive="false">
|
||||
<slot />
|
||||
</popper>
|
||||
</transition>
|
||||
</portal>
|
||||
<span ref="root" class="sr-only"><slot /></span>
|
||||
</fragment>
|
||||
|
@ -14,7 +14,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
@include vue-animation(fade, 150ms ease-in-out) {
|
||||
@include vue-animation(fade, 250ms ease-in-out) {
|
||||
0% {
|
||||
opacity: 0
|
||||
}
|
||||
100% {
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
|
||||
@include vue-animation(tooltip, 100ms ease-in-out) {
|
||||
0% {
|
||||
opacity: 0
|
||||
}
|
||||
|
@ -15,16 +15,27 @@ import Vue from "vue";
|
||||
import Vuex from 'vuex';
|
||||
import PortalVue from 'portal-vue';
|
||||
import VueDragscroll from 'vue-dragscroll';
|
||||
import { Plugin as VueFragment } from 'vue-fragment';
|
||||
import { Workbox } from "workbox-window";
|
||||
|
||||
import { migrate } from "./store/migrations";
|
||||
import { Component } from "vue-property-decorator";
|
||||
|
||||
Vue.use(Vuex);
|
||||
Vue.use(PortalVue);
|
||||
Vue.use(VueDragscroll);
|
||||
Vue.use(VueFragment);
|
||||
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
$isTouch: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$isTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints > 0;
|
||||
|
||||
Component.registerHooks(['removed']);
|
||||
|
||||
// async dependencies
|
||||
(async function () {
|
||||
await migrate("vuex");
|
||||
|
@ -1,34 +1,88 @@
|
||||
import Vue from 'vue';
|
||||
import Component from "vue-class-component";
|
||||
import { Prop } from "vue-property-decorator";
|
||||
import { Prop, Watch } from "vue-property-decorator";
|
||||
|
||||
type Events = {
|
||||
[evnet: string]: (...any) => void,
|
||||
}
|
||||
|
||||
type Trigger = "hover" | "focus";
|
||||
|
||||
const longPressTimeout = 1000;
|
||||
|
||||
@Component({ template: require('../../components/tooltip.html') })
|
||||
export class TooltipComponent extends Vue {
|
||||
@Prop({ type: String, default: "auto" }) public placement: string;
|
||||
@Prop({ type: Number, default: 100 }) public delay: number;
|
||||
@Prop({ type: Number, default: 200 }) public delay: number;
|
||||
@Prop({ type: Array, default: ["hover", "focus"]}) public triggers: Trigger[];
|
||||
|
||||
public show: boolean = false;
|
||||
public element: Element = null;
|
||||
public root: Element = null;
|
||||
|
||||
private _events: { [event: string]: any };
|
||||
private _timeout: number;
|
||||
private _events: Events;
|
||||
|
||||
mounted() {
|
||||
this.$el.parentElement.addEventListener('mouseenter', this._events['mouseenter'] = () => {
|
||||
this._timeout = window.setTimeout(() => { this.show = true }, this.delay);
|
||||
});
|
||||
this.root = (this.$refs['root'] as HTMLSpanElement).parentElement;
|
||||
|
||||
this.$el.parentElement.addEventListener('mouseleave', this._events['mouseleave'] = () => {
|
||||
window.clearTimeout(this._timeout);
|
||||
this.show = false
|
||||
});
|
||||
|
||||
this.element = this.$el.parentElement;
|
||||
this._registerEventListeners();
|
||||
}
|
||||
|
||||
beforeDestroy() {
|
||||
this.$el.parentElement.removeEventListener('mouseenter', this._events['mouseenter']);
|
||||
this.$el.parentElement.removeEventListener('mouseleave', this._events['mouseleave']);
|
||||
this._removeEventListeners();
|
||||
}
|
||||
|
||||
@Watch('triggers', { immediate: true })
|
||||
updateTriggers() {
|
||||
this._removeEventListeners();
|
||||
|
||||
this._events = {};
|
||||
|
||||
let blocked: boolean = false;
|
||||
|
||||
if (this.triggers.includes("hover")) {
|
||||
let timeout;
|
||||
|
||||
this._events['mouseenter'] = () => {
|
||||
timeout = window.setTimeout(() => { this.show = !blocked }, this.delay);
|
||||
};
|
||||
|
||||
this._events['mouseleave'] = () => {
|
||||
window.clearTimeout(timeout);
|
||||
this.show = false
|
||||
};
|
||||
}
|
||||
|
||||
if (this.triggers.includes("focus") || (this.triggers.includes("hover") && this.$isTouch)) {
|
||||
if (this.$isTouch) {
|
||||
this._events['touchstart'] = () => {
|
||||
// this is to prevent showing tooltips after tap
|
||||
blocked = true;
|
||||
setTimeout(() => blocked = false, longPressTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
this._events['focus'] = () => {
|
||||
this.show = !blocked;
|
||||
};
|
||||
|
||||
this._events['blur'] = () => {
|
||||
this.show = false
|
||||
};
|
||||
}
|
||||
|
||||
this._registerEventListeners();
|
||||
}
|
||||
|
||||
private _registerEventListeners() {
|
||||
for (const [event, handler] of Object.entries(this._events)) {
|
||||
this.root.addEventListener(event, handler);
|
||||
}
|
||||
}
|
||||
|
||||
private _removeEventListeners() {
|
||||
for (const [event, handler] of Object.entries(this._events)) {
|
||||
this.root.removeEventListener(event, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ export class PopperComponent extends Vue {
|
||||
}
|
||||
|
||||
removed() {
|
||||
this._popper.destroy();
|
||||
this._popper.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6453,6 +6453,11 @@ vue-dragscroll@^1.10.2:
|
||||
resolved "https://registry.yarnpkg.com/vue-dragscroll/-/vue-dragscroll-1.10.2.tgz#34ace3c6aa7a39edc157cac5e9ea1d5b31b1119c"
|
||||
integrity sha512-fGVw8KP3ggbp49csa1Tbj2my0YuNmZ1zxYYge4QWIypGNHVwd9hResy/v6QF5HxY0a+qd2EBteeBpxtJxFMp5A==
|
||||
|
||||
vue-fragment@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-fragment/-/vue-fragment-1.5.1.tgz#44c070d55ed1e9a6c698ef57a5c83f64bb06feeb"
|
||||
integrity sha512-ig6eES6TcMBbANW71ylB+AJgRN+Zksb3f50AxjGpAk6hMzqmeuD80qeh4LJP0jVw2dMBMjgRUfIkrvxygoRgtQ==
|
||||
|
||||
vue-property-decorator@^7.0.0:
|
||||
version "7.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-7.3.0.tgz#d50d67f0b0f1c814f9f2fba36d6eeccbcc62dbb6"
|
||||
|
Loading…
Reference in New Issue
Block a user