Update:Show tooltip for library item card titles that are truncated #2451

- Refactored tooltip so that they dont overflow the window
This commit is contained in:
advplyr 2024-01-06 15:54:48 -06:00
parent 935e545caa
commit e88c1fa329
2 changed files with 69 additions and 21 deletions

View File

@ -8,10 +8,10 @@
<!-- Alternative bookshelf title/author/sort --> <!-- Alternative bookshelf title/author/sort -->
<div v-if="isAlternativeBookshelfView || isAuthorBookshelfView" class="absolute left-0 z-50 w-full" :style="{ bottom: `-${titleDisplayBottomOffset}rem` }"> <div v-if="isAlternativeBookshelfView || isAuthorBookshelfView" class="absolute left-0 z-50 w-full" :style="{ bottom: `-${titleDisplayBottomOffset}rem` }">
<div :style="{ fontSize: 0.9 * sizeMultiplier + 'rem' }"> <div :style="{ fontSize: 0.9 * sizeMultiplier + 'rem' }">
<div class="flex items-center"> <ui-tooltip :text="displayTitle" :disabled="!displayTitleTruncated" direction="bottom" :delayOnShow="500" class="flex items-center">
<span class="truncate">{{ displayTitle }}</span> <p ref="displayTitle" class="truncate">{{ displayTitle }}</p>
<widgets-explicit-indicator :explicit="isExplicit" /> <widgets-explicit-indicator :explicit="isExplicit" />
</div> </ui-tooltip>
</div> </div>
<p class="truncate text-gray-400" :style="{ fontSize: 0.8 * sizeMultiplier + 'rem' }">{{ displayLineTwo || '&nbsp;' }}</p> <p class="truncate text-gray-400" :style="{ fontSize: 0.8 * sizeMultiplier + 'rem' }">{{ displayLineTwo || '&nbsp;' }}</p>
<p v-if="displaySortLine" class="truncate text-gray-400" :style="{ fontSize: 0.8 * sizeMultiplier + 'rem' }">{{ displaySortLine }}</p> <p v-if="displaySortLine" class="truncate text-gray-400" :style="{ fontSize: 0.8 * sizeMultiplier + 'rem' }">{{ displaySortLine }}</p>
@ -164,6 +164,7 @@ export default {
imageReady: false, imageReady: false,
selected: false, selected: false,
isSelectionMode: false, isSelectionMode: false,
displayTitleTruncated: false,
showCoverBg: false showCoverBg: false
} }
}, },
@ -642,6 +643,12 @@ export default {
} }
this.libraryItem = libraryItem this.libraryItem = libraryItem
this.$nextTick(() => {
if (this.$refs.displayTitle) {
this.displayTitleTruncated = this.$refs.displayTitle.scrollWidth > this.$refs.displayTitle.clientWidth
}
})
}, },
clickCard(e) { clickCard(e) {
if (this.processing) return if (this.processing) return

View File

@ -15,6 +15,13 @@ export default {
type: String, type: String,
default: 'right' default: 'right'
}, },
/**
* Delay showing the tooltip after X milliseconds of hovering
*/
delayOnShow: {
type: Number,
default: 0
},
disabled: Boolean disabled: Boolean
}, },
data() { data() {
@ -22,7 +29,8 @@ export default {
tooltip: null, tooltip: null,
tooltipId: null, tooltipId: null,
isShowing: false, isShowing: false,
hideTimeout: null hideTimeout: null,
delayOnShowTimeout: null
} }
}, },
watch: { watch: {
@ -59,29 +67,44 @@ export default {
this.tooltip = tooltip this.tooltip = tooltip
}, },
setTooltipPosition(tooltip) { setTooltipPosition(tooltip) {
var boxChow = this.$refs.box.getBoundingClientRect() const boxRect = this.$refs.box.getBoundingClientRect()
const shouldMount = !tooltip.isConnected
var shouldMount = !tooltip.isConnected
// Calculate size of tooltip // Calculate size of tooltip
if (shouldMount) document.body.appendChild(tooltip) if (shouldMount) document.body.appendChild(tooltip)
var { width, height } = tooltip.getBoundingClientRect() const tooltipRect = tooltip.getBoundingClientRect()
if (shouldMount) tooltip.remove() if (shouldMount) tooltip.remove()
var top = 0 // Subtracting scrollbar size
var left = 0 const windowHeight = window.innerHeight - 8
const windowWidth = window.innerWidth - 8
let top = 0
let left = 0
if (this.direction === 'right') { if (this.direction === 'right') {
top = boxChow.top - height / 2 + boxChow.height / 2 top = Math.max(0, boxRect.top - tooltipRect.height / 2 + boxRect.height / 2)
left = boxChow.left + boxChow.width + 4 left = Math.max(0, boxRect.left + boxRect.width + 4)
} else if (this.direction === 'bottom') { } else if (this.direction === 'bottom') {
top = boxChow.top + boxChow.height + 4 top = Math.max(0, boxRect.top + boxRect.height + 4)
left = boxChow.left - width / 2 + boxChow.width / 2 left = Math.max(0, boxRect.left - tooltipRect.width / 2 + boxRect.width / 2)
} else if (this.direction === 'top') { } else if (this.direction === 'top') {
top = boxChow.top - height - 4 top = Math.max(0, boxRect.top - tooltipRect.height - 4)
left = boxChow.left - width / 2 + boxChow.width / 2 left = Math.max(0, boxRect.left - tooltipRect.width / 2 + boxRect.width / 2)
} else if (this.direction === 'left') { } else if (this.direction === 'left') {
top = boxChow.top - height / 2 + boxChow.height / 2 top = Math.max(0, boxRect.top - tooltipRect.height / 2 + boxRect.height / 2)
left = boxChow.left - width - 4 left = Math.max(0, boxRect.left - tooltipRect.width - 4)
} }
// Shift left if tooltip would overflow the window on the right
if (left + tooltipRect.width > windowWidth) {
left -= left + tooltipRect.width - windowWidth
}
// Shift up if tooltip would overflow the window on the bottom
if (top + tooltipRect.height > windowHeight) {
top -= top + tooltipRect.height - windowHeight
}
tooltip.style.top = top + 'px' tooltip.style.top = top + 'px'
tooltip.style.left = left + 'px' tooltip.style.left = left + 'px'
}, },
@ -107,15 +130,33 @@ export default {
this.isShowing = false this.isShowing = false
}, },
cancelHide() { cancelHide() {
if (this.hideTimeout) clearTimeout(this.hideTimeout) clearTimeout(this.hideTimeout)
}, },
mouseover() { mouseover() {
if (!this.isShowing) this.showTooltip() if (this.isShowing || this.disabled) return
if (this.delayOnShow) {
if (this.delayOnShowTimeout) {
// Delay already running
return
}
this.delayOnShowTimeout = setTimeout(() => {
this.showTooltip()
this.delayOnShowTimeout = null
}, this.delayOnShow)
} else {
this.showTooltip()
}
}, },
mouseleave() { mouseleave() {
if (this.isShowing) { if (!this.isShowing) {
this.hideTimeout = setTimeout(this.hideTooltip, 100) clearTimeout(this.delayOnShowTimeout)
this.delayOnShowTimeout = null
return
} }
this.hideTimeout = setTimeout(this.hideTooltip, 100)
} }
}, },
beforeDestroy() { beforeDestroy() {