Skip to content

Commit 6f0f1f2

Browse files
committed
refactor(core): FloatingTooltip component
1 parent d8003d6 commit 6f0f1f2

8 files changed

Lines changed: 110 additions & 89 deletions

File tree

packages/core/src/client/webcomponents/components/DockEmbedded.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import type { DocksContext } from '@vitejs/devtools-kit/client'
33
import Dock from './Dock.vue'
44
import DockPanel from './DockPanel.vue'
5-
import FloatingTooltip from './FloatingTooltip.vue'
5+
import FloatingTooltip from './FloatingTooltip'
66
77
defineProps<{
88
context: DocksContext

packages/core/src/client/webcomponents/components/DockEntries.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<script setup lang="ts">
22
import type { DevToolsDockEntry } from '@vitejs/devtools-kit'
3+
import type { DocksContext } from '@vitejs/devtools-kit/client'
34
import { toRefs } from 'vue'
45
import DockEntry from './DockEntry.vue'
56
67
const props = defineProps<{
8+
context: DocksContext
79
entries: DevToolsDockEntry[]
810
selected: DevToolsDockEntry | null
911
isVertical: boolean

packages/core/src/client/webcomponents/components/DockEntriesWithCategories.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<script setup lang="ts">
22
import type { DevToolsDockEntry } from '@vitejs/devtools-kit'
3+
import type { DocksContext } from '@vitejs/devtools-kit/client'
34
import { computed, toRefs } from 'vue'
45
import { DEFAULT_CATEGORIES_ORDER } from '../constants'
56
import DockEntries from './DockEntries.vue'
67
import DockEntry from './DockEntry.vue'
78
89
const props = defineProps<{
10+
context: DocksContext
911
entries: DevToolsDockEntry[]
1012
selected: DevToolsDockEntry | null
1113
capacity?: number
@@ -88,6 +90,7 @@ const overflowBadge = computed(() => {
8890
<div class="border-base m1 h-20px w-px border-r-1.5" />
8991
</slot>
9092
<DockEntries
93+
:context="context"
9194
:entries="entries"
9295
:is-vertical="isVertical"
9396
:selected="selected"

packages/core/src/client/webcomponents/components/DockEntry.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function updatePos() {
1919
const rect = button.value?.getBoundingClientRect()
2020
if (rect) {
2121
setFloatingTooltip({
22-
text: props.dock.title,
22+
render: props.dock.title,
2323
width: rect.width,
2424
height: rect.height,
2525
left: rect.left,
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import type { FloatingTooltip } from '../state/floating-tooltip'
2+
import { computed, defineComponent, h, ref, watchEffect } from 'vue'
3+
import { useFloatingTooltip } from '../state/floating-tooltip'
4+
5+
// @unocss-include
6+
7+
const DETECT_MARGIN = 100
8+
const GAP = 10
9+
10+
const FloatingTooltipComponent = defineComponent({
11+
name: 'FloatingTooltip',
12+
setup() {
13+
const current = useFloatingTooltip()
14+
const box = ref<FloatingTooltip>({
15+
render: '',
16+
width: 0,
17+
height: 0,
18+
left: 0,
19+
top: 0,
20+
})
21+
22+
// guess alignment of the tooltip based on viewport position
23+
const align = computed<'bottom' | 'left' | 'right' | 'top'>(() => {
24+
const vw = window.innerWidth
25+
const vh = window.innerHeight
26+
if (box.value.left < DETECT_MARGIN)
27+
return 'right'
28+
if (box.value.left + box.value.width > vw - DETECT_MARGIN)
29+
return 'left'
30+
if (box.value.top < DETECT_MARGIN)
31+
return 'bottom'
32+
if (box.value.top + box.value.height > vh - DETECT_MARGIN)
33+
return 'top'
34+
return 'bottom'
35+
})
36+
37+
const style = computed(() => {
38+
switch (align.value) {
39+
case 'bottom': {
40+
return {
41+
left: `${box.value.left + box.value.width / 2}px`,
42+
top: `${box.value.top + box.value.height + GAP}px`,
43+
transform: 'translateX(-50%)',
44+
}
45+
}
46+
case 'top': {
47+
return {
48+
left: `${box.value.left + box.value.width / 2}px`,
49+
bottom: `${window.innerHeight - box.value.top + GAP}px`,
50+
transform: 'translateX(-50%)',
51+
}
52+
}
53+
case 'left': {
54+
return {
55+
right: `${window.innerWidth - box.value.left + GAP}px`,
56+
top: `${box.value.top + box.value.height / 2}px`,
57+
transform: 'translateY(-50%)',
58+
}
59+
}
60+
case 'right': {
61+
return {
62+
left: `${box.value.left + box.value.width + GAP}px`,
63+
top: `${box.value.top + box.value.height / 2}px`,
64+
transform: 'translateY(-50%)',
65+
}
66+
}
67+
default: {
68+
throw new Error('Unreachable')
69+
}
70+
}
71+
})
72+
73+
watchEffect(() => {
74+
if (current.value) {
75+
box.value = { ...current.value }
76+
}
77+
})
78+
79+
return () => {
80+
if (!box.value.render)
81+
return null
82+
83+
const content = typeof box.value.render === 'string' ? h('span', box.value.render) : box.value.render()
84+
85+
return h(
86+
'div',
87+
{
88+
class: [
89+
'fixed z-floating-tooltip text-xs transition-all duration-300 w-max bg-glass border border-base rounded px2 p1',
90+
current ? 'op100' : 'op0 pointer-events-none',
91+
],
92+
style: style.value,
93+
},
94+
content,
95+
)
96+
}
97+
},
98+
})
99+
100+
export default FloatingTooltipComponent

packages/core/src/client/webcomponents/components/FloatingTooltip.vue

Lines changed: 0 additions & 85 deletions
This file was deleted.

packages/core/src/client/webcomponents/scripts/build-css.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { createGenerator } from 'unocss'
1212
import config from '../uno.config'
1313

1414
const SRC_DIR = fileURLToPath(new URL('..', import.meta.url))
15-
const GLOBS = ['components/**/*.vue']
15+
const GLOBS = ['components/**/*.{ts,vue}']
1616
const USER_STYLE = join(SRC_DIR, 'style.css')
1717
const GENERATED_CSS = join(SRC_DIR, '.generated/css.ts')
1818
const MINIFY = true

packages/core/src/client/webcomponents/state/floating-tooltip.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import type { VNode } from 'vue'
12
import { shallowRef } from 'vue'
23

34
export interface FloatingTooltip {
45
left: number
56
top: number
67
width: number
78
height: number
8-
text: string
9+
render: string | (() => VNode)
910
}
1011

1112
const state = shallowRef<FloatingTooltip | null>(null)

0 commit comments

Comments
 (0)