Skip to content

Commit b850449

Browse files
committed
feat(vueltip): allow for custom data to be passed to the tooltip
1 parent 7d0242d commit b850449

7 files changed

Lines changed: 97 additions & 15 deletions

File tree

demo/src/App.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,15 @@ debug('foobar', { count })
158158
>
159159
Hover over me (right)
160160
</p>
161+
<p
162+
v-tooltip="{
163+
text: 'Custom data: ',
164+
custom: { sum: 23 },
165+
}"
166+
class="rounded-xl border border-slate-700 bg-slate-900/70 px-4 py-3 text-sm text-slate-200 shadow-sm transition hover:border-slate-500"
167+
>
168+
Hover over me (custom data)
169+
</p>
161170
</div>
162171
<div class="mt-6 space-y-3">
163172
<div>

demo/src/Tooltip.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ const { tooltipStyles, arrowStyles, show, content } =
3131
class="relative z-10 rounded bg-slate-100 px-2 py-1 text-sm font-semibold text-slate-900 shadow-lg"
3232
>
3333
{{ content?.text }}
34+
<span v-if="content?.custom">
35+
{{ content.custom }}</span
36+
>
3437
</div>
3538
</div>
3639
</template>

demo/src/main.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,9 @@ app
2020
.directive('tooltip', vueltipDirective)
2121

2222
app.mount('#app')
23+
24+
declare module '@vingy/vueltip' {
25+
export interface CustomVueltipData {
26+
sum: number
27+
}
28+
}

packages/vueltip/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,62 @@ v-tooltip="{
182182
placement: 'right' // Placement: 'top', 'bottom', 'left', 'right', etc.
183183
}"
184184
```
185+
186+
## Custom Data
187+
188+
You can extend the tooltip content with custom typed data for use in your tooltip component:
189+
190+
**1. Create a type declaration file (e.g., `vueltip.d.ts`):**
191+
192+
```ts
193+
declare module '@vingy/vueltip' {
194+
interface CustomVueltipData {
195+
userId?: number
196+
userName?: string
197+
severity?: 'info' | 'warning' | 'error'
198+
metadata?: Record<string, unknown>
199+
}
200+
}
201+
```
202+
203+
**2. Use custom data in your directive:**
204+
205+
```vue
206+
<button
207+
v-tooltip="{
208+
text: 'User profile',
209+
custom: {
210+
userId: 123,
211+
userName: 'John Doe',
212+
severity: 'info',
213+
},
214+
}"
215+
>
216+
View Profile
217+
</button>
218+
```
219+
220+
**3. Access custom data in your Tooltip component:**
221+
222+
```vue
223+
<script setup>
224+
import { useVueltip } from '@vingy/vueltip'
225+
226+
const { content, show } = useVueltip({
227+
/* ... */
228+
})
229+
</script>
230+
231+
<template>
232+
<div v-if="show">
233+
{{ content?.text }}
234+
235+
<!-- Access your custom data -->
236+
<span v-if="content?.custom?.userId">
237+
User ID: {{ content.custom.userId }}
238+
</span>
239+
</div>
240+
</template>
241+
```
242+
243+
TypeScript will validate that your `custom` object matches the declared `CustomVueltipData` interface.

packages/vueltip/src/directive.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,29 @@ import {
88
setContent,
99
} from './state'
1010
import type {
11-
Binding,
1211
Content,
1312
Modifier,
1413
TooltipDirective,
14+
Value,
1515
} from './types.ts'
1616
import { ensureKey } from './utils'
1717

18-
const toContent = (value: Binding): Content => {
18+
const toContent = (value: Value): Content => {
1919
if (value == null) return { text: value }
2020
if (typeof value === 'string') return { text: value }
21-
if (value.text == null) return { text: value.text }
22-
if (typeof value.text === 'string')
23-
return { text: value.text }
24-
return value.text
21+
const { placement: _, ...rest } = value
22+
return rest
2523
}
2624
const extractPlacement = (
27-
binding: DirectiveBinding<Binding, Modifier, Placement>,
25+
binding: DirectiveBinding<Value, Modifier, Placement>,
2826
) => {
2927
const { value, arg } = binding
3028

3129
if (
3230
value &&
3331
typeof value !== 'string' &&
34-
'placement' in value
32+
'placement' in value &&
33+
value.placement != null
3534
) {
3635
return value.placement
3736
}

packages/vueltip/src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ export { useVueltip } from './composables'
22
export { vueltipDirective } from './directive'
33
export { setOptions } from './options'
44
export { vueltipPlugin } from './plugin'
5-
export type { Content } from './types'
5+
export type {
6+
Content,
7+
CustomVueltipData,
8+
} from './types'

packages/vueltip/src/types.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,23 @@ import type {
55
import { Maybe } from '@vingy/shared/types'
66
import type { Directive, ShallowRef } from 'vue'
77

8+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
9+
export interface CustomVueltipData {}
10+
811
export interface Content {
912
text: Maybe<string>
13+
custom?: CustomVueltipData
1014
}
11-
export type Binding =
15+
export type Value =
1216
| Maybe<string>
13-
| {
14-
text: Maybe<string | Content>
15-
placement: Placement
16-
}
17+
| (Content & {
18+
placement?: Placement
19+
})
1720
export type Modifier = 'x' | 'y' | 'none' | 'both'
1821

1922
export type TooltipDirective = Directive<
2023
HTMLElement,
21-
Binding,
24+
Value,
2225
Modifier,
2326
Placement
2427
>

0 commit comments

Comments
 (0)