Fix flickering tooltip when hovering modified in FileExplorer. Use the new, improved tooltip also in gallery to show full name, modified and size of an item.
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<div v-if="visible" class="cursor-tooltip" :style="tooltipStyle">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
// Global activation state - shared across all instances
|
||||
let globalActive = false
|
||||
let globalDeactivateTimer: ReturnType<typeof setTimeout> | null = null
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
text: string
|
||||
delay?: number
|
||||
}>()
|
||||
|
||||
const visible = ref(false)
|
||||
const mouseX = ref(0)
|
||||
const mouseY = ref(0)
|
||||
let hoverTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const tooltipStyle = computed(() => ({
|
||||
left: `${mouseX.value + 12}px`,
|
||||
top: `${mouseY.value + 12}px`,
|
||||
}))
|
||||
|
||||
const startHover = (e: MouseEvent) => {
|
||||
mouseX.value = e.clientX
|
||||
mouseY.value = e.clientY
|
||||
// Clear any pending deactivation
|
||||
if (globalDeactivateTimer) {
|
||||
clearTimeout(globalDeactivateTimer)
|
||||
globalDeactivateTimer = null
|
||||
}
|
||||
const delay = globalActive ? 0 : (props.delay ?? 800)
|
||||
hoverTimer = setTimeout(() => {
|
||||
visible.value = true
|
||||
globalActive = true
|
||||
}, delay)
|
||||
}
|
||||
|
||||
const updatePosition = (e: MouseEvent) => {
|
||||
mouseX.value = e.clientX
|
||||
mouseY.value = e.clientY
|
||||
}
|
||||
|
||||
const endHover = () => {
|
||||
if (hoverTimer) {
|
||||
clearTimeout(hoverTimer)
|
||||
hoverTimer = null
|
||||
}
|
||||
visible.value = false
|
||||
// Deactivate global state after a short delay if no new tooltip started
|
||||
if (globalDeactivateTimer) clearTimeout(globalDeactivateTimer)
|
||||
globalDeactivateTimer = setTimeout(() => {
|
||||
globalActive = false
|
||||
}, 500)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
startHover,
|
||||
updatePosition,
|
||||
endHover,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.cursor-tooltip {
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
padding: .5rem 1rem;
|
||||
border-radius: 3rem 0 3rem 0;
|
||||
box-shadow: 0 0 1rem var(--accent-color);
|
||||
background-color: var(--accent-color);
|
||||
color: var(--primary-color);
|
||||
white-space: nowrap;
|
||||
pointer-events: none;
|
||||
font-size: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -2,15 +2,11 @@
|
||||
<td class="modified right">
|
||||
<time
|
||||
:datetime=datetime
|
||||
@mouseenter="startHover"
|
||||
@mousemove="updatePosition"
|
||||
@mouseleave="endHover"
|
||||
@mouseenter="tooltip?.startHover"
|
||||
@mousemove="tooltip?.updatePosition"
|
||||
@mouseleave="tooltip?.endHover"
|
||||
>{{ modified }}</time>
|
||||
<Teleport to="body">
|
||||
<div v-if="showTooltip" class="cursor-tooltip" :style="tooltipStyle">
|
||||
{{ tooltipText }}
|
||||
</div>
|
||||
</Teleport>
|
||||
<CursorTooltip ref="tooltip" :text="tooltipText">{{ tooltipText }}</CursorTooltip>
|
||||
</td>
|
||||
</template>
|
||||
|
||||
@@ -18,12 +14,15 @@
|
||||
import { Doc } from '@/repositories/Document'
|
||||
import { formatUnixDate } from '@/utils'
|
||||
import { computed, ref } from 'vue'
|
||||
import CursorTooltip from './CursorTooltip.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
doc: Doc
|
||||
now: number
|
||||
}>()
|
||||
|
||||
const tooltip = ref<InstanceType<typeof CursorTooltip> | null>(null)
|
||||
|
||||
// Reference props.now to trigger reactivity when time updates
|
||||
const modified = computed(() => {
|
||||
props.now // trigger reactivity
|
||||
@@ -37,50 +36,4 @@ const datetime = computed(() =>
|
||||
const tooltipText = computed(() =>
|
||||
datetime.value.replace('T', ' ').replace('Z', ' UTC')
|
||||
)
|
||||
|
||||
const showTooltip = ref(false)
|
||||
const mouseX = ref(0)
|
||||
const mouseY = ref(0)
|
||||
let hoverTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const tooltipStyle = computed(() => ({
|
||||
left: `${mouseX.value + 12}px`,
|
||||
top: `${mouseY.value + 12}px`,
|
||||
}))
|
||||
|
||||
const startHover = (e: MouseEvent) => {
|
||||
mouseX.value = e.clientX
|
||||
mouseY.value = e.clientY
|
||||
hoverTimer = setTimeout(() => {
|
||||
showTooltip.value = true
|
||||
}, 500)
|
||||
}
|
||||
|
||||
const updatePosition = (e: MouseEvent) => {
|
||||
mouseX.value = e.clientX
|
||||
mouseY.value = e.clientY
|
||||
}
|
||||
|
||||
const endHover = () => {
|
||||
if (hoverTimer) {
|
||||
clearTimeout(hoverTimer)
|
||||
hoverTimer = null
|
||||
}
|
||||
showTooltip.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.cursor-tooltip {
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
padding: .5rem 1rem;
|
||||
border-radius: 3rem 0 3rem 0;
|
||||
box-shadow: 0 0 1rem var(--accent-color);
|
||||
background-color: var(--accent-color);
|
||||
color: var(--primary-color);
|
||||
white-space: pre;
|
||||
pointer-events: none;
|
||||
font-size: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
@contextmenu.stop
|
||||
@focus.stop="store.cursor = doc.key"
|
||||
@click=onclick
|
||||
@mouseenter="tooltip?.startHover"
|
||||
@mousemove="tooltip?.updatePosition"
|
||||
@mouseleave="tooltip?.endHover"
|
||||
>
|
||||
<figure>
|
||||
<slot></slot>
|
||||
@@ -15,19 +18,24 @@
|
||||
</template>
|
||||
<template v-else>
|
||||
<SelectBox :doc=doc @click="store.cursor = doc.key"/>
|
||||
<span :title="doc.name + '\n' + doc.modified + '\n' + doc.sizedisp">{{ doc.name }}</span>
|
||||
<span>{{ doc.name }}</span>
|
||||
<div class=namespacer></div>
|
||||
</template>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<CursorTooltip ref="tooltip" :text="tooltipText">
|
||||
<div class="tooltip-name">{{ doc.name }}</div>
|
||||
<div class="tooltip-details">{{ doc.modified }} — {{ doc.sizedisp }}</div>
|
||||
</CursorTooltip>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script setup lang=ts>
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useMainStore } from '@/stores/main'
|
||||
import { Doc } from '@/repositories/Document'
|
||||
import MediaPreview from '@/components/MediaPreview.vue'
|
||||
import CursorTooltip from './CursorTooltip.vue'
|
||||
|
||||
const store = useMainStore()
|
||||
type EditingProp = {
|
||||
@@ -40,6 +48,9 @@ const props = defineProps<{
|
||||
editing?: EditingProp,
|
||||
}>()
|
||||
const m = ref<typeof MediaPreview | null>(null)
|
||||
const tooltip = ref<InstanceType<typeof CursorTooltip> | null>(null)
|
||||
|
||||
const tooltipText = computed(() => props.doc.key)
|
||||
|
||||
const onclick = (ev: Event) => {
|
||||
if (m.value!.play()) ev.preventDefault()
|
||||
@@ -48,6 +59,13 @@ const onclick = (ev: Event) => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tooltip-name {
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
.tooltip-details {
|
||||
text-align: center;
|
||||
}
|
||||
figure {
|
||||
max-height: 15em;
|
||||
position: relative;
|
||||
|
||||
Reference in New Issue
Block a user