forked from npmx-dev/npmx.dev
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBase.vue
More file actions
66 lines (60 loc) · 2.15 KB
/
Base.vue
File metadata and controls
66 lines (60 loc) · 2.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import type { Placement, Strategy } from '@floating-ui/vue'
import { autoUpdate, flip, offset, shift, useFloating } from '@floating-ui/vue'
const props = withDefaults(
defineProps<{
/** Tooltip text (optional when using content slot) */
text?: string
/** Position: 'top' | 'bottom' | 'left' | 'right' */
position?: 'top' | 'bottom' | 'left' | 'right'
/** is tooltip visible */
isVisible: boolean
/** Allow pointer events on tooltip (for interactive content like links) */
interactive?: boolean
/** attributes for tooltip element */
tooltipAttr?: HTMLAttributes
/** Teleport target for the tooltip content (defaults to 'body') */
to?: string | HTMLElement
/** Strategy for the tooltip - prefer fixed for sticky containers (defaults to 'absolute') */
strategy?: Strategy
}>(),
{
to: 'body',
strategy: 'absolute',
},
)
const triggerRef = useTemplateRef('triggerRef')
const tooltipRef = useTemplateRef('tooltipRef')
const placement = computed<Placement>(() => props.position || 'bottom')
const { floatingStyles } = useFloating(triggerRef, tooltipRef, {
placement,
whileElementsMounted: autoUpdate,
strategy: props.strategy,
middleware: [offset(4), flip(), shift({ padding: 8 })],
})
</script>
<template>
<div ref="triggerRef" class="inline-flex">
<slot />
<Teleport :to="props.to">
<Transition
enter-active-class="transition-opacity duration-150 motion-reduce:transition-none"
leave-active-class="transition-opacity duration-100 motion-reduce:transition-none"
enter-from-class="opacity-0"
leave-to-class="opacity-0"
>
<div
v-if="props.isVisible"
ref="tooltipRef"
class="px-2 py-1 font-mono text-xs text-fg bg-bg-elevated border border-border rounded shadow-lg whitespace-pre-line break-words max-w-xs z-[100]"
:class="{ 'pointer-events-none': !interactive }"
:style="floatingStyles"
v-bind="tooltipAttr"
>
<slot name="content">{{ text }}</slot>
</div>
</Transition>
</Teleport>
</div>
</template>