useTour 사용법
한 단계에 걸쳐 단일 포포버를 다시 고정하여 가이드 투어를 구성하는 구성 가능.
Usage
자동으로 가져온 useTour 컴포지블을 사용하여 단계 간에 앵커가 이동하는 단일 [Popover](/docs/components/popoverxph08x로 가이드 투어를 구동합니다. 컴포지션은 단계 상태를 소유하고 각 단계의 target를 <UPopover>에 바인딩된 xph03x로 분석하며 내용과 탐색을 완전히 제어할 수 있습니다.
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>
각 단계는 Popover가 앵커하는 target를 필요로 합니다. CSS 선택기, 요소, 가상 요소(getBoundingClientRect가 있는 모든 것) 또는 ref/getter를 허용합니다. 단계를 뷰포트의 중앙에 고정시키려면 null를 전달합니다. 단계의 다른 필드(title, body, side, ...x)를 통해 사용할 수 있으며 변경되지 않습니다.
<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>
- Popover의 반응형
reference소품을 기반으로 제작되므로 활성 단계가 변경되면 Popover가 부드럽게 위치를 조정합니다. - 단계가 활성화되면 활성 대상이 자동으로 뷰로 스크롤됩니다.
- 콘텐츠를 직접 렌더링하기 때문에 유지할 추가 테마나 로케일은 없습니다.
API
useTour(steps, options?)
매개 변수
steps
MaybeRefOrGetter<TourStep[]> required
둘러보기 단계 목록입니다. 정적 배열,
ref 또는 반응 단계의 게터일 수 있습니다.target
MaybeRefOrGetter<string | ReferenceElement | null | undefined>
단계가 앵커되는 요소입니다. CSS 선택기(
'#id', '.class' 또는 #id로 해석되는 벌거 벗은 ID), 요소, 가상 요소 또는 참조/getter를 반환합니다. null를 사용하여 단계를 뷰포트의 가운데에 배치합니다.[key: string]
any
추가 필드(
title, body, side, ...)는 current를 통해 전달되고 사용할 수 있습니다.options
UseTourOptions
둘러보기에 대한 구성 옵션.
initialStep
number
둘러보기가 시작되는 단계 색인입니다.
loop
boolean
마지막 단계 후에 첫 번째 단계로 돌아갑니다.
scrollIntoView
boolean | ScrollIntoViewOptions
단계가 활성화되면 대상을 보기로 스크롤합니다.
Return (### Return) (0)
open
Ref<boolean>
투어가 현재 열려 있는지 여부입니다.
index
Ref<number>
단계 범위에 클램프된 현재 단계 인덱스입니다.
current
ComputedRef<TourStep | undefined>
현재 단계 개체 또는 단계가 없는 경우
undefined입니다.reference
ComputedRef<ReferenceElement | undefined>
<UPopover :reference>로 전달할 현재 단계에 대해 해결된 앵커입니다.total
ComputedRef<number>
전체 단계 수입니다.
hasNext
ComputedRef<boolean>
다음 단계가 있는지 여부입니다.
hasPrev
ComputedRef<boolean>
이전 단계가 있는지 여부입니다.
start
(index?: number) => void
선택적으로 지정된 색인에서 둘러보기를 엽니다.
next
() => void
다음 단계로 이동합니다.
loop 옵션에 따라 끝에서 루프 또는 완료합니다.prev
() => void
이전 단계로 이동합니다.
goTo
(index: number) => void
특정 단계로 이동하여 둘러보기를 엽니다.
finish
() => void
둘러보기를 닫습니다.