From ce8c8f97ec75352d65fe86dff1eb27c3531588b8 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sun, 26 Jan 2020 22:29:16 +0100 Subject: [PATCH] Add tooltip component --- .../components/departures/departure.html | 3 +- resources/components/popper.html | 2 +- resources/components/tooltip.html | 5 +++ resources/styles/_popper.scss | 28 ++++++++++++- resources/ts/components/index.ts | 1 + resources/ts/components/tooltip.ts | 26 ++++++++++++ resources/ts/components/utils.ts | 40 ++++++++++++------- 7 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 resources/components/tooltip.html create mode 100644 resources/ts/components/tooltip.ts diff --git a/resources/components/departures/departure.html b/resources/components/departures/departure.html index 08ef588..8e2b97e 100644 --- a/resources/components/departures/departure.html +++ b/resources/components/departures/departure.html @@ -6,7 +6,8 @@
- + + Czas rozkładowy, nieuwzględniający aktualnej sytuacji komunikacyjnej. diff --git a/resources/components/popper.html b/resources/components/popper.html index 5ad58c9..84c1c94 100644 --- a/resources/components/popper.html +++ b/resources/components/popper.html @@ -1,4 +1,4 @@ -
+
diff --git a/resources/components/tooltip.html b/resources/components/tooltip.html new file mode 100644 index 0000000..4e64c6c --- /dev/null +++ b/resources/components/tooltip.html @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/styles/_popper.scss b/resources/styles/_popper.scss index c3bca2c..07d5247 100644 --- a/resources/styles/_popper.scss +++ b/resources/styles/_popper.scss @@ -108,12 +108,38 @@ } } - &.popper--arrow { + @mixin arrows { @include placement("left"); @include placement("right"); @include placement("top"); @include placement("bottom"); } + + &.popper--arrow { + @include arrows; + } + + &.popper--tooltip { + background: $dark; + color: white; + padding: .5rem .75rem; + font-size: $small-font-size; + font-weight: bold; + min-width: 0; + box-shadow: none; + + &.popper--arrow { + $arrow-color: $dark; + $arrow-border: none; + $arrow-base: 6px; + + @include arrows; + + .popper__arrow::before { + border: none; + } + } + } } @include media-breakpoint-down('sm') { diff --git a/resources/ts/components/index.ts b/resources/ts/components/index.ts index cc580e7..78d820a 100644 --- a/resources/ts/components/index.ts +++ b/resources/ts/components/index.ts @@ -1,3 +1,4 @@ +export * from './tooltip'; export * from './utils' export * from './line' export * from './picker' diff --git a/resources/ts/components/tooltip.ts b/resources/ts/components/tooltip.ts new file mode 100644 index 0000000..e78fd62 --- /dev/null +++ b/resources/ts/components/tooltip.ts @@ -0,0 +1,26 @@ +import Vue from 'vue'; +import Component from "vue-class-component"; +import { Prop } from "vue-property-decorator"; + +@Component({ template: require('../../components/tooltip.html') }) +export class TooltipComponent extends Vue { + @Prop({ type: String, default: "auto" }) public placement: string; + public show: boolean = false; + public element: Element = null; + + private _events: { [event: string]: any }; + + mounted() { + this.$el.parentElement.addEventListener('mouseenter', this._events['mouseenter'] = () => this.show = true); + this.$el.parentElement.addEventListener('mouseleave', this._events['mouseleave'] = () => this.show = false); + + this.element = this.$el.parentElement; + } + + beforeDestroy() { + this.$el.parentElement.removeEventListener('mouseenter', this._events['mouseenter']); + this.$el.parentElement.removeEventListener('mouseleave', this._events['mouseleave']); + } +} + +Vue.component('Tooltip', TooltipComponent); diff --git a/resources/ts/components/utils.ts b/resources/ts/components/utils.ts index d2ba78f..0dd293f 100644 --- a/resources/ts/components/utils.ts +++ b/resources/ts/components/utils.ts @@ -7,8 +7,8 @@ import { Portal } from "portal-vue"; template: require("../../components/popper.html") }) export class PopperComponent extends Vue { - @Prop(String) - public reference: string; + @Prop([ String, HTMLElement ]) + public reference: string | HTMLElement; @Prop(Object) public refs: string; @@ -22,6 +22,28 @@ export class PopperComponent extends Vue { private _event; private _popper; + private getReferenceElement() { + const isInPortal = this.$parent.$options.name == 'portalTarget'; + + if (typeof this.reference === 'string') { + if (this.refs) { + return this.refs[this.reference]; + } + + if (isInPortal) { + return this.$parent.$parent.$refs[this.reference]; + } + + return this.$parent.$refs[this.reference]; + } + + if (this.reference instanceof HTMLElement) { + return this.reference; + } + + return isInPortal ? this.$parent.$el : this.$el.parentElement; + } + focusOut(event: MouseEvent) { if (this.$el.contains(event.target as Node)) { return; @@ -31,7 +53,7 @@ export class PopperComponent extends Vue { } mounted() { - const reference = this.refsSource[this.reference] as HTMLElement; + const reference = this.getReferenceElement(); this._popper = new Popper(reference, this.$el, { placement: this.placement, @@ -76,18 +98,6 @@ export class PopperComponent extends Vue { this._popper.destroy(); this._event && document.removeEventListener('click', this._event, { capture: true }); } - - get refsSource() { - if (this.refs) { - return this.refs; - } - - if (this.$parent.$options.name == 'portalTarget') { - return this.$parent.$parent.$refs; - } - - return this.$parent.$refs - } } @Component({ template: require('../../components/fold.html') })