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",
|
"mini-css-extract-plugin": "^0.4.2",
|
||||||
"portal-vue": "^2.1.7",
|
"portal-vue": "^2.1.7",
|
||||||
"vue-dragscroll": "^1.10.2",
|
"vue-dragscroll": "^1.10.2",
|
||||||
|
"vue-fragment": "^1.5.1",
|
||||||
"vue-removed-hook-mixin": "^0.1.1",
|
"vue-removed-hook-mixin": "^0.1.1",
|
||||||
"vue2-leaflet": "^1.0.2",
|
"vue2-leaflet": "^1.0.2",
|
||||||
"vuex": "^3.0.1",
|
"vuex": "^3.0.1",
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
<portal to="popups">
|
<fragment>
|
||||||
<transition name="fade">
|
<portal to="popups">
|
||||||
<popper class="popper--tooltip" arrow :reference="element" :placement="placement" v-if="show" :responsive="false">
|
<transition name="tooltip">
|
||||||
<slot />
|
<popper class="popper--tooltip" aria-hidden="true" arrow :reference="root" :placement="placement" v-if="show" :responsive="false">
|
||||||
</popper>
|
<slot />
|
||||||
</transition>
|
</popper>
|
||||||
</portal>
|
</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% {
|
0% {
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}
|
}
|
||||||
|
@ -15,16 +15,27 @@ import Vue from "vue";
|
|||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
import PortalVue from 'portal-vue';
|
import PortalVue from 'portal-vue';
|
||||||
import VueDragscroll from 'vue-dragscroll';
|
import VueDragscroll from 'vue-dragscroll';
|
||||||
|
import { Plugin as VueFragment } from 'vue-fragment';
|
||||||
import { Workbox } from "workbox-window";
|
import { Workbox } from "workbox-window";
|
||||||
|
|
||||||
import { migrate } from "./store/migrations";
|
import { migrate } from "./store/migrations";
|
||||||
|
import { Component } from "vue-property-decorator";
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
Vue.use(PortalVue);
|
Vue.use(PortalVue);
|
||||||
Vue.use(VueDragscroll);
|
Vue.use(VueDragscroll);
|
||||||
|
Vue.use(VueFragment);
|
||||||
|
|
||||||
|
declare module 'vue/types/vue' {
|
||||||
|
interface Vue {
|
||||||
|
$isTouch: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Vue.prototype.$isTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints > 0;
|
Vue.prototype.$isTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints > 0;
|
||||||
|
|
||||||
|
Component.registerHooks(['removed']);
|
||||||
|
|
||||||
// async dependencies
|
// async dependencies
|
||||||
(async function () {
|
(async function () {
|
||||||
await migrate("vuex");
|
await migrate("vuex");
|
||||||
|
@ -1,34 +1,88 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Component from "vue-class-component";
|
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') })
|
@Component({ template: require('../../components/tooltip.html') })
|
||||||
export class TooltipComponent extends Vue {
|
export class TooltipComponent extends Vue {
|
||||||
@Prop({ type: String, default: "auto" }) public placement: string;
|
@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 show: boolean = false;
|
||||||
public element: Element = null;
|
public root: Element = null;
|
||||||
|
|
||||||
private _events: { [event: string]: any };
|
private _events: Events;
|
||||||
private _timeout: number;
|
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$el.parentElement.addEventListener('mouseenter', this._events['mouseenter'] = () => {
|
this.root = (this.$refs['root'] as HTMLSpanElement).parentElement;
|
||||||
this._timeout = window.setTimeout(() => { this.show = true }, this.delay);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$el.parentElement.addEventListener('mouseleave', this._events['mouseleave'] = () => {
|
this._registerEventListeners();
|
||||||
window.clearTimeout(this._timeout);
|
|
||||||
this.show = false
|
|
||||||
});
|
|
||||||
|
|
||||||
this.element = this.$el.parentElement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.$el.parentElement.removeEventListener('mouseenter', this._events['mouseenter']);
|
this._removeEventListeners();
|
||||||
this.$el.parentElement.removeEventListener('mouseleave', this._events['mouseleave']);
|
}
|
||||||
|
|
||||||
|
@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() {
|
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"
|
resolved "https://registry.yarnpkg.com/vue-dragscroll/-/vue-dragscroll-1.10.2.tgz#34ace3c6aa7a39edc157cac5e9ea1d5b31b1119c"
|
||||||
integrity sha512-fGVw8KP3ggbp49csa1Tbj2my0YuNmZ1zxYYge4QWIypGNHVwd9hResy/v6QF5HxY0a+qd2EBteeBpxtJxFMp5A==
|
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:
|
vue-property-decorator@^7.0.0:
|
||||||
version "7.3.0"
|
version "7.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-7.3.0.tgz#d50d67f0b0f1c814f9f2fba36d6eeccbcc62dbb6"
|
resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-7.3.0.tgz#d50d67f0b0f1c814f9f2fba36d6eeccbcc62dbb6"
|
||||||
|
Loading…
Reference in New Issue
Block a user