Utilisation
Utilisation
Utilisez le composable useTour importé automatiquement pour conduire une visite guidée avec un seul Popover dont l'ancre se déplace entre les étapes. Le composable possède l'état de l'étape et résout le target de chaque étape en un reference que vous liez à <UPopover>, tout en gardant un contrôle total sur le contenu et la navigation.
Dashboard
Overview of your workspace.
Profile
Manage your account.
Settings
Configure your preferences.
<script setup lang="ts">
const dashboard = useTemplateRef('dashboard')
const profile = useTemplateRef('profile')
const settings = useTemplateRef('settings')
const tour = useTour([
{
target: () => dashboard.value,
title: 'Welcome aboard',
body: 'The popover re-anchors to each target as you step through the tour.'
},
{
target: () => profile.value,
title: 'Make it yours',
body: 'You own the content and the buttons — no extra theme or locale to maintain.',
side: 'right' as const
},
{
target: () => settings.value,
title: 'You\'re all set',
body: 'Press Finish to close the tour.'
}
])
</script>
<template>
<div class="w-full space-y-4">
<div class="flex justify-end">
<UButton icon="i-lucide-wand-sparkles" @click="tour.start()">
Start tour
</UButton>
</div>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div ref="dashboard" class="p-4 rounded-lg border border-default bg-elevated/50">
<p class="font-medium text-highlighted">
Dashboard
</p>
<p class="text-sm text-muted">
Overview of your workspace.
</p>
</div>
<div ref="profile" class="p-4 rounded-lg border border-default bg-elevated/50">
<p class="font-medium text-highlighted">
Profile
</p>
<p class="text-sm text-muted">
Manage your account.
</p>
</div>
<div ref="settings" class="p-4 rounded-lg border border-default bg-elevated/50">
<p class="font-medium text-highlighted">
Settings
</p>
<p class="text-sm text-muted">
Configure your preferences.
</p>
</div>
</div>
<UPopover
:open="tour.open.value"
:reference="tour.reference.value"
:content="{ side: tour.current.value?.side, sideOffset: 8 }"
:dismissible="false"
arrow
>
<template #content>
<div class="p-4 max-w-xs space-y-2">
<div class="flex items-center justify-between gap-4">
<p class="font-semibold text-highlighted">
{{ tour.current.value?.title }}
</p>
<span class="text-xs text-muted tabular-nums">
{{ tour.index.value + 1 }} / {{ tour.total.value }}
</span>
</div>
<p class="text-sm text-muted">
{{ tour.current.value?.body }}
</p>
<div class="flex items-center justify-between pt-2">
<UButton
color="neutral"
variant="outline"
size="sm"
:disabled="!tour.hasPrev.value"
@click="tour.prev()"
>
Back
</UButton>
<UButton size="sm" @click="tour.next()">
{{ tour.hasNext.value ? 'Next' : 'Finish' }}
</UButton>
</div>
</div>
</template>
</UPopover>
</div>
</template>
<script setup lang="ts">
import { useTemplateRef } from 'vue'
const dashboard = useTemplateRef('dashboard')
const profile = useTemplateRef('profile')
const settings = useTemplateRef('settings')
const tour = useTour([
{
target: () => dashboard.value,
title: 'Welcome aboard',
body: 'The popover re-anchors to each target as you step through the tour.'
},
{
target: () => profile.value,
title: 'Make it yours',
body: 'You own the content and the buttons — no extra theme or locale to maintain.',
side: 'right' as const
},
{
target: () => settings.value,
title: 'You\'re all set',
body: 'Press Finish to close the tour.'
}
])
</script>
<template>
<div class="w-full space-y-4">
<div class="flex justify-end">
<UButton icon="i-lucide-wand-sparkles" @click="tour.start()">
Start tour
</UButton>
</div>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div ref="dashboard" class="p-4 rounded-lg border border-default bg-elevated/50">
<p class="font-medium text-highlighted">
Dashboard
</p>
<p class="text-sm text-muted">
Overview of your workspace.
</p>
</div>
<div ref="profile" class="p-4 rounded-lg border border-default bg-elevated/50">
<p class="font-medium text-highlighted">
Profile
</p>
<p class="text-sm text-muted">
Manage your account.
</p>
</div>
<div ref="settings" class="p-4 rounded-lg border border-default bg-elevated/50">
<p class="font-medium text-highlighted">
Settings
</p>
<p class="text-sm text-muted">
Configure your preferences.
</p>
</div>
</div>
<UPopover
:open="tour.open.value"
:reference="tour.reference.value"
:content="{ side: tour.current.value?.side, sideOffset: 8 }"
:dismissible="false"
arrow
>
<template #content>
<div class="p-4 max-w-xs space-y-2">
<div class="flex items-center justify-between gap-4">
<p class="font-semibold text-highlighted">
{{ tour.current.value?.title }}
</p>
<span class="text-xs text-muted tabular-nums">
{{ tour.index.value + 1 }} / {{ tour.total.value }}
</span>
</div>
<p class="text-sm text-muted">
{{ tour.current.value?.body }}
</p>
<div class="flex items-center justify-between pt-2">
<UButton
color="neutral"
variant="outline"
size="sm"
:disabled="!tour.hasPrev.value"
@click="tour.prev()"
>
Back
</UButton>
<UButton size="sm" @click="tour.next()">
{{ tour.hasNext.value ? 'Next' : 'Finish' }}
</UButton>
</div>
</div>
</template>
</UPopover>
</div>
</template>
Chaque étape requiert un target auquel le popover s'ancre. Il accepte un sélecteur CSS, un élément, un élément virtuel (tout ce qui contient getBoundingClientRect), ou un ref/getter renvoyant l'un de ceux-ci. Passez null pour ancrer l'étape au centre de la fenêtre d'affichage. Tout autre champ sur une étape (title, body, side,...) est passé intact et disponible via current.
<script setup lang="ts">
const card = useTemplateRef('card')
const tour = useTour([
{ target: '#cta', title: 'Get started' },
{ target: () => card.value, title: 'Profile', side: 'right' },
{ target: null, title: 'All set' }
])
</script>
<template>
<UButton @click="tour.start()">Start tour</UButton>
<UPopover :open="tour.open.value" :reference="tour.reference.value" :dismissible="false">
<template #content>
<!-- your content + buttons -->
<UButton :disabled="!tour.hasPrev.value" @click="tour.prev()">Back</UButton>
<UButton @click="tour.next()">{{ tour.hasNext.value ? 'Next' : 'Finish' }}</UButton>
</template>
</UPopover>
</template>
- Construit sur le prop
referenceréactif du Popover, le popover se repositionne en douceur lorsque l'étape active change. - La cible active est défilée automatiquement dans la vue lorsqu 'une étape devient active.
- Puisque vous affichez le contenu vous-même, il n'y a pas de thème ou de paramètres régionaux supplémentaires à gérer.
api
useTour(steps, options?)x{lang="ts-type"}
Paramètres
ref, ou un getter pour les étapes réactives.'#id', '.class' ou un identifiant nu résolu comme #id), un élément, un élément virtuel ou un ref/getter renvoyant un élément. Utilisez null pour centrer l'étape dans la fenêtre d'affichage.title, body, side,...) sont transmis et disponibles via current.retour
undefined lorsqu 'il n'y a pas de step.<UPopover :reference>.loop.