forked from DebaucheryLibrarian/traxxx
Improved tooltip behavior and styling.
This commit is contained in:
parent
229d74d266
commit
a7e6f470f7
|
@ -38,6 +38,24 @@ async function setConsent(consent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function blur(event) {
|
||||||
|
this.events.emit('blur', event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resize(event) {
|
||||||
|
this.events.emit('resize', event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mounted() {
|
||||||
|
document.addEventListener('click', this.blur);
|
||||||
|
window.addEventListener('resize', this.resize);
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeUnmount() {
|
||||||
|
document.removeEventListener('click', this.blur);
|
||||||
|
window.removeEventListener('resize', this.resize);
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Header,
|
Header,
|
||||||
|
@ -50,9 +68,13 @@ export default {
|
||||||
showWarning: localStorage.getItem('consent') !== window.env.sessionId,
|
showWarning: localStorage.getItem('consent') !== window.env.sessionId,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
mounted,
|
||||||
|
beforeUnmount,
|
||||||
methods: {
|
methods: {
|
||||||
toggleSidebar,
|
toggleSidebar,
|
||||||
setConsent,
|
setConsent,
|
||||||
|
blur,
|
||||||
|
resize,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-slot:tooltip>
|
<template v-slot:tooltip>
|
||||||
<div>
|
<div class="filter-options">
|
||||||
<select
|
<select
|
||||||
v-model="mode"
|
v-model="mode"
|
||||||
class="filter-mode"
|
class="filter-mode"
|
||||||
|
@ -105,3 +105,9 @@ export default {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.filter-options {
|
||||||
|
width: 15rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -95,14 +95,17 @@
|
||||||
<template v-slot:tooltip>
|
<template v-slot:tooltip>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<ul class="menu-items noselect">
|
<ul class="menu-items noselect">
|
||||||
<li class="menu-item disabled">
|
<li
|
||||||
|
class="menu-item disabled"
|
||||||
|
@click.stop
|
||||||
|
>
|
||||||
<Icon icon="enter2" />Sign in
|
<Icon icon="enter2" />Sign in
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li
|
<li
|
||||||
v-show="!sfw"
|
v-show="!sfw"
|
||||||
class="menu-item"
|
class="menu-item"
|
||||||
@click="setSfw(true)"
|
@click.stop="setSfw(true)"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon="flower"
|
icon="flower"
|
||||||
|
@ -113,7 +116,7 @@
|
||||||
<li
|
<li
|
||||||
v-show="sfw"
|
v-show="sfw"
|
||||||
class="menu-item"
|
class="menu-item"
|
||||||
@click="setSfw(false)"
|
@click.stop="setSfw(false)"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon="fire"
|
icon="fire"
|
||||||
|
@ -124,7 +127,7 @@
|
||||||
<li
|
<li
|
||||||
v-show="theme === 'light'"
|
v-show="theme === 'light'"
|
||||||
class="menu-item"
|
class="menu-item"
|
||||||
@click="setTheme('dark')"
|
@click.stop="setTheme('dark')"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon="moon"
|
icon="moon"
|
||||||
|
@ -135,7 +138,7 @@
|
||||||
<li
|
<li
|
||||||
v-show="theme === 'dark'"
|
v-show="theme === 'dark'"
|
||||||
class="menu-item"
|
class="menu-item"
|
||||||
@click="setTheme('light')"
|
@click.stop="setTheme('light')"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon="sun"
|
icon="sun"
|
||||||
|
@ -143,7 +146,10 @@
|
||||||
/>Light theme
|
/>Light theme
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="menu-item">
|
<li
|
||||||
|
class="menu-item disabled"
|
||||||
|
@click.stop
|
||||||
|
>
|
||||||
<Icon icon="filter" />Filters
|
<Icon icon="filter" />Filters
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -1,13 +1,24 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="tooltip-container">
|
<div class="tooltip-container">
|
||||||
<div class="trigger">
|
<div
|
||||||
|
ref="trigger"
|
||||||
|
class="trigger noselect"
|
||||||
|
@click.stop="toggle"
|
||||||
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<teleport to="body">
|
<teleport to="body">
|
||||||
<div class="tooltip">
|
<div
|
||||||
<div class="tooltip-wrapper">
|
v-if="opened"
|
||||||
<slot name="tooltip" />
|
ref="tooltip"
|
||||||
|
class="tooltip-wrapper"
|
||||||
|
:style="{ transform: `translate3d(${tooltipX}px, ${tooltipY}px, 0)` }"
|
||||||
|
>
|
||||||
|
<div class="tooltip-inner">
|
||||||
|
<div class="tooltip">
|
||||||
|
<slot name="tooltip" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</teleport>
|
</teleport>
|
||||||
|
@ -15,23 +26,126 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { nextTick } from 'vue';
|
||||||
|
|
||||||
|
function getX(triggerBoundary, tooltipBoundary) {
|
||||||
|
const idealPosition = triggerBoundary.left + (triggerBoundary.width / 2) - (tooltipBoundary.width / 2);
|
||||||
|
|
||||||
|
// don't overflow left edge
|
||||||
|
if (idealPosition < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't overflow right edge
|
||||||
|
if (idealPosition + tooltipBoundary.width > window.innerWidth) {
|
||||||
|
return window.innerWidth - tooltipBoundary.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// position at the center of trigger
|
||||||
|
return idealPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function calculate() {
|
||||||
|
if (!this.opened) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const triggerBoundary = this.$refs.trigger.getBoundingClientRect();
|
||||||
|
const tooltipBoundary = this.$refs.tooltip.getBoundingClientRect();
|
||||||
|
|
||||||
|
this.tooltipY = triggerBoundary.top + triggerBoundary.height;
|
||||||
|
this.tooltipX = this.getX(triggerBoundary, tooltipBoundary);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function open() {
|
||||||
|
this.events.emit('blur');
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
this.opened = true;
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
this.calculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
this.opened = false;
|
||||||
|
|
||||||
|
this.tooltipY = 0;
|
||||||
|
this.tooltipX = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle() {
|
||||||
|
if (this.opened) {
|
||||||
|
this.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
function mounted() {
|
||||||
|
this.events.on('blur', () => {
|
||||||
|
this.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.events.on('resize', () => {
|
||||||
|
this.calculate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
opened: false,
|
||||||
|
tooltipX: 0,
|
||||||
|
tooltipY: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted,
|
||||||
|
methods: {
|
||||||
|
calculate,
|
||||||
|
getX,
|
||||||
|
open,
|
||||||
|
close,
|
||||||
|
toggle,
|
||||||
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.tooltip-container {
|
.tooltip-wrapper {
|
||||||
position: relative;
|
display: flex;
|
||||||
font-size: 1rem;
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-frame {
|
.tooltip-inner {
|
||||||
position: fixed;
|
position: relative;
|
||||||
|
box-shadow: 0 0 3px var(--darken-weak);
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
position: absolute;
|
||||||
|
z-index : 11;
|
||||||
|
top: -.5rem;
|
||||||
|
left: calc(50% - .5rem);
|
||||||
|
border-left: .5rem solid transparent;
|
||||||
|
border-right: .5rem solid transparent;
|
||||||
|
border-bottom: .5rem solid var(--background-light);
|
||||||
|
margin: 0 auto;
|
||||||
|
filter: drop-shadow(0 0 3px var(--darken-weak));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip {
|
.tooltip {
|
||||||
position: absolute;
|
position: relative;
|
||||||
z-index: 10;
|
|
||||||
top: 2rem;
|
|
||||||
background: var(--background-light);
|
background: var(--background-light);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { createApp, reactive } from 'vue';
|
import { createApp, reactive } from 'vue';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import mitt from 'mitt';
|
||||||
|
|
||||||
|
|
||||||
import router from './router';
|
import router from './router';
|
||||||
import initStore from './store';
|
import initStore from './store';
|
||||||
|
@ -17,6 +19,7 @@ import Tooltip from '../components/tooltip/tooltip.vue';
|
||||||
async function init() {
|
async function init() {
|
||||||
const store = initStore(reactive(router));
|
const store = initStore(reactive(router));
|
||||||
const app = createApp(Container);
|
const app = createApp(Container);
|
||||||
|
const events = mitt();
|
||||||
|
|
||||||
initUiObservers(store, router);
|
initUiObservers(store, router);
|
||||||
|
|
||||||
|
@ -36,6 +39,11 @@ async function init() {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
'v-popover': Tooltip,
|
'v-popover': Tooltip,
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
events,
|
||||||
|
};
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
pageTitle(title) {
|
pageTitle(title) {
|
||||||
if (title) {
|
if (title) {
|
||||||
|
|
|
@ -7569,6 +7569,11 @@
|
||||||
"minipass": "^2.9.0"
|
"minipass": "^2.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mitt": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg=="
|
||||||
|
},
|
||||||
"mixin-deep": {
|
"mixin-deep": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
|
||||||
|
|
|
@ -107,6 +107,7 @@
|
||||||
"knex-migrate": "^1.7.4",
|
"knex-migrate": "^1.7.4",
|
||||||
"longjohn": "^0.2.12",
|
"longjohn": "^0.2.12",
|
||||||
"mime": "^2.4.4",
|
"mime": "^2.4.4",
|
||||||
|
"mitt": "^2.1.0",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"nanoid": "^2.1.11",
|
"nanoid": "^2.1.11",
|
||||||
"opn": "^5.5.0",
|
"opn": "^5.5.0",
|
||||||
|
|
Loading…
Reference in New Issue