@dnax/ui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/components/QAccordion.vue +68 -0
- package/components/QAccordionContent.vue +62 -0
- package/components/QAccordionItem.vue +24 -0
- package/components/QAccordionTrigger.vue +51 -0
- package/components/QActionSheet.vue +159 -0
- package/components/QApp.vue +8 -0
- package/components/QAutocomplete.vue +316 -0
- package/components/QAvatar.vue +92 -0
- package/components/QBackHeader.vue +69 -0
- package/components/QBackTop.vue +125 -0
- package/components/QBadge.vue +55 -0
- package/components/QBottomSheet.vue +177 -0
- package/components/QBottomSheetFooter.vue +9 -0
- package/components/QBottomSheetHeader.vue +35 -0
- package/components/QBottomSheetProvider.vue +62 -0
- package/components/QBottomSheetTrigger.vue +18 -0
- package/components/QBtn.vue +144 -0
- package/components/QBtnGroup.vue +31 -0
- package/components/QBubble.vue +36 -0
- package/components/QBubbleContent.vue +28 -0
- package/components/QBubbleGroup.vue +25 -0
- package/components/QBubbleReactions.vue +40 -0
- package/components/QCard.vue +63 -0
- package/components/QCardActions.vue +27 -0
- package/components/QCardContent.vue +29 -0
- package/components/QCarousel.vue +115 -0
- package/components/QCarouselContent.vue +23 -0
- package/components/QCarouselItem.vue +20 -0
- package/components/QCarouselNav.vue +51 -0
- package/components/QCheckbox.vue +146 -0
- package/components/QChip.vue +91 -0
- package/components/QCircularProgress.vue +122 -0
- package/components/QCol.vue +52 -0
- package/components/QCollapse.vue +141 -0
- package/components/QConfigProvider.vue +164 -0
- package/components/QContainer.vue +201 -0
- package/components/QCountDown.vue +164 -0
- package/components/QCountryPicker.vue +593 -0
- package/components/QDataGrid.vue +491 -0
- package/components/QDatePicker.vue +250 -0
- package/components/QDialog.vue +163 -0
- package/components/QDialogFooter.vue +9 -0
- package/components/QDialogHeader.vue +41 -0
- package/components/QDialogProvider.vue +65 -0
- package/components/QDialogTrigger.vue +18 -0
- package/components/QFab.vue +80 -0
- package/components/QFabAction.vue +48 -0
- package/components/QFilePicker.vue +294 -0
- package/components/QFooter.vue +72 -0
- package/components/QGallery.vue +280 -0
- package/components/QGrid.vue +54 -0
- package/components/QHeader.vue +38 -0
- package/components/QIcon.vue +53 -0
- package/components/QImagePicker.vue +248 -0
- package/components/QImagePreview.vue +225 -0
- package/components/QImagePreviewProvider.vue +35 -0
- package/components/QImg.vue +142 -0
- package/components/QInfiniteScroll.vue +109 -0
- package/components/QInnerLoading.vue +67 -0
- package/components/QInput.vue +289 -0
- package/components/QInputOtp.vue +238 -0
- package/components/QInputPassword.vue +67 -0
- package/components/QInputTag.vue +281 -0
- package/components/QIntersection.vue +119 -0
- package/components/QItem.vue +60 -0
- package/components/QItemSection.vue +47 -0
- package/components/QLinearProgress.vue +94 -0
- package/components/QList.vue +39 -0
- package/components/QLoading.vue +77 -0
- package/components/QLoadingProvider.vue +41 -0
- package/components/QMarquee.vue +56 -0
- package/components/QMessageScroller.vue +10 -0
- package/components/QMessageScrollerButton.vue +48 -0
- package/components/QMessageScrollerContent.vue +31 -0
- package/components/QMessageScrollerItem.vue +49 -0
- package/components/QMessageScrollerProvider.vue +198 -0
- package/components/QMessageScrollerViewport.vue +109 -0
- package/components/QNavMenu.vue +75 -0
- package/components/QNavMenuContent.vue +10 -0
- package/components/QNavMenuItem.vue +60 -0
- package/components/QNavMenuTrigger.vue +96 -0
- package/components/QNotifyProvider.vue +33 -0
- package/components/QNotifyToast.vue +60 -0
- package/components/QPage.vue +56 -0
- package/components/QPagination.vue +195 -0
- package/components/QParallax.vue +124 -0
- package/components/QPullToRefresh.vue +138 -0
- package/components/QRadio.vue +99 -0
- package/components/QRating.vue +105 -0
- package/components/QReorder.vue +191 -0
- package/components/QRollingText.vue +225 -0
- package/components/QRow.vue +23 -0
- package/components/QSafeArea.vue +39 -0
- package/components/QScrollArea.vue +118 -0
- package/components/QSelect.vue +698 -0
- package/components/QSeparator.vue +39 -0
- package/components/QSidebar.vue +153 -0
- package/components/QSidebarContent.vue +14 -0
- package/components/QSidebarFooter.vue +14 -0
- package/components/QSidebarHeader.vue +14 -0
- package/components/QSidebarMenu.vue +9 -0
- package/components/QSidebarMenuButton.vue +59 -0
- package/components/QSidebarMenuItem.vue +9 -0
- package/components/QSidebarTrigger.vue +32 -0
- package/components/QSkeleton.vue +95 -0
- package/components/QSlider.vue +205 -0
- package/components/QSpace.vue +10 -0
- package/components/QSpinner.vue +172 -0
- package/components/QSplitter.vue +145 -0
- package/components/QSticky.vue +181 -0
- package/components/QSwipeCell.vue +217 -0
- package/components/QSwiper.vue +102 -0
- package/components/QSwiperSlide.vue +19 -0
- package/components/QSyntax.vue +171 -0
- package/components/QTab.vue +175 -0
- package/components/QTabPanel.vue +50 -0
- package/components/QTabPanels.vue +106 -0
- package/components/QTable.vue +575 -0
- package/components/QTabs.vue +188 -0
- package/components/QText.vue +316 -0
- package/components/QTextCaption.vue +122 -0
- package/components/QToolbar.vue +28 -0
- package/components/QTooltip.vue +313 -0
- package/components/QUploader.vue +473 -0
- package/components/QVideo.vue +289 -0
- package/components/QVirtualScroll.vue +190 -0
- package/components/internal/QDateCalendar.vue +153 -0
- package/index.ts +151 -0
- package/lib/breakpoints.ts +44 -0
- package/lib/colors.ts +24 -0
- package/lib/config.ts +34 -0
- package/lib/countries.ts +261 -0
- package/lib/formula.ts +630 -0
- package/lib/icons.ts +38 -0
- package/lib/loading.ts +75 -0
- package/lib/overlayBack.ts +124 -0
- package/lib/platform.ts +146 -0
- package/lib/primitive.ts +25 -0
- package/lib/q.ts +287 -0
- package/lib/screen.ts +105 -0
- package/lib/search.ts +35 -0
- package/lib/themeVars.ts +22 -0
- package/lib/useComponentProps.ts +54 -0
- package/lib/utils.ts +7 -0
- package/module.ts +89 -0
- package/package.json +41 -0
- package/scripts/generate-exports.ts +56 -0
- package/styles/main.css +7627 -0
- package/tsconfig.json +33 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// QTooltip — API Quasar, comportement type shadcn-vue (reka-ui) :
|
|
3
|
+
// <q-tooltip side="top" align="center" :side-offset="8" show-arrow :delay="300" disable>
|
|
4
|
+
// À placer en enfant de la cible. Affichage au hover/focus, position fixed calculée
|
|
5
|
+
// avec FLIP automatique (bascule du côté opposé si manque de place) et clamping.
|
|
6
|
+
import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, ref, watch } from "vue"
|
|
7
|
+
import { Icon } from "@iconify/vue"
|
|
8
|
+
import { cn } from "../lib/utils"
|
|
9
|
+
import { colorValue, foregroundFor } from "../lib/colors"
|
|
10
|
+
|
|
11
|
+
type Side = "top" | "bottom" | "left" | "right"
|
|
12
|
+
type Align = "start" | "center" | "end"
|
|
13
|
+
type TooltipType = "positive" | "success" | "negative" | "error" | "info" | "warning"
|
|
14
|
+
|
|
15
|
+
interface Props {
|
|
16
|
+
/** Contrôle externe (v-model) ; sinon géré au hover */
|
|
17
|
+
modelValue?: boolean
|
|
18
|
+
/** Délai d'ouverture (ms) — défaut 300 */
|
|
19
|
+
delay?: number
|
|
20
|
+
/** Délai d'ouverture (ms), prioritaire sur delay */
|
|
21
|
+
openDelay?: number
|
|
22
|
+
/** Délai de fermeture (ms) — défaut 0 */
|
|
23
|
+
closeDelay?: number
|
|
24
|
+
/** Désactive le tooltip */
|
|
25
|
+
disable?: boolean
|
|
26
|
+
/** Ancrage legacy : "edge align" (ex. "top middle", "right middle") */
|
|
27
|
+
anchor?: string
|
|
28
|
+
/** Bord d'ancrage : top | bottom | left | right (défaut : top) */
|
|
29
|
+
side?: Side
|
|
30
|
+
/** Alignement : start | center | end (défaut : center) */
|
|
31
|
+
align?: Align
|
|
32
|
+
/** Distance tooltip ↔ cible (px) — défaut 8 */
|
|
33
|
+
sideOffset?: number
|
|
34
|
+
/** Décalage d'alignement (px) — défaut 0 */
|
|
35
|
+
alignOffset?: number
|
|
36
|
+
/** Décalage supplémentaire [x, y] en px (compat ancêtre) */
|
|
37
|
+
offset?: [number, number]
|
|
38
|
+
/** Flèche pointant vers la cible */
|
|
39
|
+
showArrow?: boolean
|
|
40
|
+
/** true = le survol du tooltip ne le maintient pas ouvert (pointer-events none) */
|
|
41
|
+
disableHoverableContent?: boolean
|
|
42
|
+
/** Variante sémantique — définit le fond : positive/success, negative/error, info, warning */
|
|
43
|
+
type?: TooltipType
|
|
44
|
+
/** Couleur de fond (token ou hex) — prioritaire sur type */
|
|
45
|
+
color?: string
|
|
46
|
+
/** Couleur du texte (token ou hex) — défaut : blanc (contraste calculé si couleur libre) */
|
|
47
|
+
textColor?: string
|
|
48
|
+
/** Icône Iconify affichée dans le tooltip (ex. "lucide:info") */
|
|
49
|
+
icon?: string
|
|
50
|
+
/** Position de l'icône : left (défaut) | right */
|
|
51
|
+
iconPosition?: "left" | "right"
|
|
52
|
+
contentClass?: string
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
56
|
+
disable: false,
|
|
57
|
+
sideOffset: 8,
|
|
58
|
+
alignOffset: 0,
|
|
59
|
+
offset: () => [0, 0] as [number, number],
|
|
60
|
+
showArrow: false,
|
|
61
|
+
disableHoverableContent: false,
|
|
62
|
+
contentClass: "",
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
const emit = defineEmits<{ "update:modelValue": [value: boolean] }>()
|
|
66
|
+
|
|
67
|
+
// — Délais —
|
|
68
|
+
const openDelay = computed(() => props.openDelay ?? props.delay ?? 300)
|
|
69
|
+
const closeDelay = computed(() => props.closeDelay ?? 0)
|
|
70
|
+
|
|
71
|
+
// — Side / align (props explicites > anchor legacy) —
|
|
72
|
+
const anchorSide = computed<Side>(() => (props.anchor?.split(" ")[0] as Side) || "top")
|
|
73
|
+
const anchorAlign = computed<Align>(() => {
|
|
74
|
+
const a = props.anchor?.split(" ")[1]
|
|
75
|
+
if (a === "left" || a === "top") return "start"
|
|
76
|
+
if (a === "right" || a === "bottom") return "end"
|
|
77
|
+
return "center"
|
|
78
|
+
})
|
|
79
|
+
const side = computed<Side>(() => props.side ?? anchorSide.value)
|
|
80
|
+
const align = computed<Align>(() => props.align ?? anchorAlign.value)
|
|
81
|
+
const effectiveSide = ref<Side>("top") // après flip éventuel
|
|
82
|
+
|
|
83
|
+
// — Ouverture contrôlée / interne —
|
|
84
|
+
// Détection du v-model par les PROPS RÉELLEMENT PASSÉES (vnode.props) : un prop
|
|
85
|
+
// Boolean non fourni vaut false (pas undefined) → `modelValue !== undefined`
|
|
86
|
+
// serait TOUJOURS contrôlé et le tooltip ne s'ouvrirait jamais sans v-model.
|
|
87
|
+
const instance = getCurrentInstance()
|
|
88
|
+
const controlled = computed(() => {
|
|
89
|
+
const p = instance?.vnode.props
|
|
90
|
+
return !!(p && ("modelValue" in p || "onUpdate:modelValue" in p))
|
|
91
|
+
})
|
|
92
|
+
const internalOpen = ref(false)
|
|
93
|
+
const open = computed(() => (controlled.value ? props.modelValue : internalOpen.value))
|
|
94
|
+
|
|
95
|
+
const setOpen = (v: boolean) => {
|
|
96
|
+
if (controlled.value) emit("update:modelValue", v)
|
|
97
|
+
else internalOpen.value = v
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let showTimer: ReturnType<typeof setTimeout> | null = null
|
|
101
|
+
let hideTimer: ReturnType<typeof setTimeout> | null = null
|
|
102
|
+
|
|
103
|
+
const cancelHide = () => {
|
|
104
|
+
if (hideTimer) {
|
|
105
|
+
clearTimeout(hideTimer)
|
|
106
|
+
hideTimer = null
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const show = () => {
|
|
111
|
+
if (props.disable) return
|
|
112
|
+
cancelHide()
|
|
113
|
+
if (showTimer) clearTimeout(showTimer)
|
|
114
|
+
showTimer = setTimeout(() => setOpen(true), openDelay.value)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const scheduleHide = () => {
|
|
118
|
+
if (showTimer) clearTimeout(showTimer)
|
|
119
|
+
if (hideTimer) clearTimeout(hideTimer)
|
|
120
|
+
hideTimer = setTimeout(() => setOpen(false), closeDelay.value)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// — Positionnement (flip + clamp) —
|
|
124
|
+
const tipRef = ref<HTMLElement | null>(null)
|
|
125
|
+
const parentEl = ref<HTMLElement | null>(null)
|
|
126
|
+
const posStyle = ref<Record<string, string>>({})
|
|
127
|
+
const arrowStyle = ref<Record<string, string>>({})
|
|
128
|
+
// Ancre invisible rendue DANS la cible : retrouve l'élément parent même après
|
|
129
|
+
// le Teleport vers body (qui couperait le lien DOM).
|
|
130
|
+
const anchorEl = ref<HTMLElement | null>(null)
|
|
131
|
+
|
|
132
|
+
const PAD = 8
|
|
133
|
+
const ARROW = 10
|
|
134
|
+
|
|
135
|
+
const updatePosition = () => {
|
|
136
|
+
const tip = tipRef.value
|
|
137
|
+
const parent = parentEl.value
|
|
138
|
+
if (!tip || !parent) return
|
|
139
|
+
const pr = parent.getBoundingClientRect()
|
|
140
|
+
const tw = tip.offsetWidth
|
|
141
|
+
const th = tip.offsetHeight
|
|
142
|
+
const vw = window.innerWidth
|
|
143
|
+
const vh = window.innerHeight
|
|
144
|
+
|
|
145
|
+
const place = (s: Side, a: Align) => {
|
|
146
|
+
const off = props.sideOffset
|
|
147
|
+
const aoff = props.alignOffset
|
|
148
|
+
let left = 0
|
|
149
|
+
let top = 0
|
|
150
|
+
if (s === "top" || s === "bottom") {
|
|
151
|
+
left = a === "start" ? pr.left + aoff : a === "end" ? pr.right - tw - aoff : pr.left + (pr.width - tw) / 2
|
|
152
|
+
top = s === "top" ? pr.top - th - off : pr.bottom + off
|
|
153
|
+
} else {
|
|
154
|
+
top = a === "start" ? pr.top + aoff : a === "end" ? pr.bottom - th - aoff : pr.top + (pr.height - th) / 2
|
|
155
|
+
left = s === "left" ? pr.left - tw - off : pr.right + off
|
|
156
|
+
}
|
|
157
|
+
return { left: left + props.offset[0], top: top + props.offset[1] }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
let s = side.value
|
|
161
|
+
let a = align.value
|
|
162
|
+
let pos = place(s, a)
|
|
163
|
+
|
|
164
|
+
// FLIP : bascule sur le côté opposé si le côté demandé déborde
|
|
165
|
+
if (s === "top" && pos.top < PAD && pr.bottom + props.sideOffset + th <= vh - PAD) {
|
|
166
|
+
s = "bottom"
|
|
167
|
+
pos = place(s, a)
|
|
168
|
+
} else if (s === "bottom" && pos.top + th > vh - PAD && pr.top - props.sideOffset - th >= PAD) {
|
|
169
|
+
s = "top"
|
|
170
|
+
pos = place(s, a)
|
|
171
|
+
} else if (s === "left" && pos.left < PAD && pr.right + props.sideOffset + tw <= vw - PAD) {
|
|
172
|
+
s = "right"
|
|
173
|
+
pos = place(s, a)
|
|
174
|
+
} else if (s === "right" && pos.left + tw > vw - PAD && pr.left - props.sideOffset - tw >= PAD) {
|
|
175
|
+
s = "left"
|
|
176
|
+
pos = place(s, a)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// CLAMP : garde le tooltip dans le viewport
|
|
180
|
+
pos.left = Math.max(PAD, Math.min(pos.left, vw - tw - PAD))
|
|
181
|
+
pos.top = Math.max(PAD, Math.min(pos.top, vh - th - PAD))
|
|
182
|
+
effectiveSide.value = s
|
|
183
|
+
|
|
184
|
+
posStyle.value = { left: `${pos.left}px`, top: `${pos.top}px` }
|
|
185
|
+
|
|
186
|
+
// Flèche : centrée/alignée sur le bord côté cible
|
|
187
|
+
if (props.showArrow) {
|
|
188
|
+
if (s === "top" || s === "bottom") {
|
|
189
|
+
const x = a === "start" ? 14 + props.alignOffset : a === "end" ? tw - 14 - props.alignOffset : tw / 2
|
|
190
|
+
arrowStyle.value = {
|
|
191
|
+
left: `${x - ARROW / 2}px`,
|
|
192
|
+
top: s === "top" ? `${th - ARROW / 2}px` : `${-ARROW / 2}px`,
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
const y = a === "start" ? 14 + props.alignOffset : a === "end" ? th - 14 - props.alignOffset : th / 2
|
|
196
|
+
arrowStyle.value = {
|
|
197
|
+
top: `${y - ARROW / 2}px`,
|
|
198
|
+
left: s === "left" ? `${tw - ARROW / 2}px` : `${-ARROW / 2}px`,
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
watch(open, async (v) => {
|
|
205
|
+
if (v) {
|
|
206
|
+
await nextTick()
|
|
207
|
+
updatePosition()
|
|
208
|
+
if (typeof window !== "undefined") {
|
|
209
|
+
window.addEventListener("scroll", updatePosition, true)
|
|
210
|
+
window.addEventListener("resize", updatePosition)
|
|
211
|
+
}
|
|
212
|
+
} else if (typeof window !== "undefined") {
|
|
213
|
+
window.removeEventListener("scroll", updatePosition, true)
|
|
214
|
+
window.removeEventListener("resize", updatePosition)
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
onMounted(() => {
|
|
219
|
+
// L'ancre (span invisible rendu DANS la cible) permet de retrouver l'élément
|
|
220
|
+
// cible même après le Teleport vers body (qui coupe le lien DOM parent).
|
|
221
|
+
parentEl.value = anchorEl.value?.parentElement ?? null
|
|
222
|
+
const p = parentEl.value
|
|
223
|
+
if (p) {
|
|
224
|
+
p.addEventListener("mouseenter", show)
|
|
225
|
+
p.addEventListener("mouseleave", scheduleHide)
|
|
226
|
+
p.addEventListener("focusin", show)
|
|
227
|
+
p.addEventListener("focusout", scheduleHide)
|
|
228
|
+
}
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
onBeforeUnmount(() => {
|
|
232
|
+
const p = parentEl.value
|
|
233
|
+
if (p) {
|
|
234
|
+
p.removeEventListener("mouseenter", show)
|
|
235
|
+
p.removeEventListener("mouseleave", scheduleHide)
|
|
236
|
+
p.removeEventListener("focusin", show)
|
|
237
|
+
p.removeEventListener("focusout", scheduleHide)
|
|
238
|
+
}
|
|
239
|
+
if (typeof window !== "undefined") {
|
|
240
|
+
window.removeEventListener("scroll", updatePosition, true)
|
|
241
|
+
window.removeEventListener("resize", updatePosition)
|
|
242
|
+
}
|
|
243
|
+
if (showTimer) clearTimeout(showTimer)
|
|
244
|
+
if (hideTimer) clearTimeout(hideTimer)
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
const tipClasses = computed(() =>
|
|
248
|
+
cn("q-tooltip", open.value && "q-tooltip--show", props.contentClass),
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
// — Thème : type sémantique / couleur / texte / icône —
|
|
252
|
+
const typeBg = computed<string | undefined>(() => {
|
|
253
|
+
switch (props.type) {
|
|
254
|
+
case "positive":
|
|
255
|
+
case "success":
|
|
256
|
+
return "positive"
|
|
257
|
+
case "negative":
|
|
258
|
+
case "error":
|
|
259
|
+
return "negative"
|
|
260
|
+
case "info":
|
|
261
|
+
return "info"
|
|
262
|
+
case "warning":
|
|
263
|
+
return "warning"
|
|
264
|
+
default:
|
|
265
|
+
return undefined
|
|
266
|
+
}
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
const themeStyle = computed<Record<string, string>>(() => {
|
|
270
|
+
const s: Record<string, string> = {}
|
|
271
|
+
const bg = props.color ?? typeBg.value
|
|
272
|
+
if (bg) {
|
|
273
|
+
s["--q-tooltip-bg"] = colorValue(bg)
|
|
274
|
+
s["--q-tooltip-fg"] = props.textColor ? colorValue(props.textColor) : foregroundFor(bg)
|
|
275
|
+
} else if (props.textColor) {
|
|
276
|
+
s["--q-tooltip-fg"] = colorValue(props.textColor)
|
|
277
|
+
}
|
|
278
|
+
return s
|
|
279
|
+
})
|
|
280
|
+
</script>
|
|
281
|
+
|
|
282
|
+
<template>
|
|
283
|
+
<!-- Ancre invisible dans la cible : sert de référence pour le hover ET pour
|
|
284
|
+
retrouver l'élément cible après le Teleport. -->
|
|
285
|
+
<span ref="anchorEl" class="q-tooltip__anchor" aria-hidden="true" style="display: none" />
|
|
286
|
+
<Teleport to="body">
|
|
287
|
+
<div
|
|
288
|
+
ref="tipRef"
|
|
289
|
+
v-show="open"
|
|
290
|
+
class="q-tooltip"
|
|
291
|
+
:class="[tipClasses, disableHoverableContent && 'q-tooltip--no-hover']"
|
|
292
|
+
:style="[themeStyle, posStyle]"
|
|
293
|
+
role="tooltip"
|
|
294
|
+
@mouseenter="cancelHide"
|
|
295
|
+
@mouseleave="scheduleHide"
|
|
296
|
+
>
|
|
297
|
+
<Icon
|
|
298
|
+
v-if="icon && iconPosition !== 'right'"
|
|
299
|
+
:icon="icon"
|
|
300
|
+
class="q-tooltip__icon"
|
|
301
|
+
aria-hidden="true"
|
|
302
|
+
/>
|
|
303
|
+
<slot />
|
|
304
|
+
<Icon
|
|
305
|
+
v-if="icon && iconPosition === 'right'"
|
|
306
|
+
:icon="icon"
|
|
307
|
+
class="q-tooltip__icon"
|
|
308
|
+
aria-hidden="true"
|
|
309
|
+
/>
|
|
310
|
+
<span v-if="showArrow" class="q-tooltip__arrow" :style="arrowStyle" aria-hidden="true" />
|
|
311
|
+
</div>
|
|
312
|
+
</Teleport>
|
|
313
|
+
</template>
|