Skip to content

Commit 5ec5866

Browse files
committed
docs(Discovery): isolate activator and step unregistration
Activators and steps share IDs by design but have independent lifecycles. Previously, unregister() removed from both registries, so closing a drawer (unmounting an activator) would also remove the step registration. Add optional `type` parameter to unregister() so each component type only removes from its own registry. This fixes the delay prop not working on subsequent visits to a step.
1 parent 0220ea7 commit 5ec5866

30 files changed

+1423
-819
lines changed

apps/docs/src/App.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { IN_BROWSER, useWindowEventListener } from '@vuetify/v0'
77
88
// Components
9-
import { Discovery } from './components/discovery'
9+
import DocsHighlight from '@/components/docs/DocsHighlight.vue'
1010
1111
// Composables
1212
import { useScrollPersist } from './composables/useScrollPersist'
@@ -72,7 +72,7 @@
7272
<DocsVueLink />
7373

7474
<!-- Discovery overlay -->
75-
<Discovery.Highlight />
75+
<DocsHighlight />
7676
</template>
7777

7878
<style>

apps/docs/src/components.d.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ declare module 'vue' {
4242
AppSettingsThemeEditor: typeof import('./components/app/settings/AppSettingsThemeEditor.vue')['default']
4343
AppSettingsToggle: typeof import('./components/app/settings/AppSettingsToggle.vue')['default']
4444
AppSettingsToggleSection: typeof import('./components/app/settings/AppSettingsToggleSection.vue')['default']
45+
AppSettingsTour: typeof import('./components/app/settings/AppSettingsTour.vue')['default']
4546
AppSkillFilter: typeof import('./components/app/AppSkillFilter.vue')['default']
4647
AppThemePreview: typeof import('./components/app/AppThemePreview.vue')['default']
4748
AppThemeSelector: typeof import('./components/app/AppThemeSelector.vue')['default']
@@ -74,11 +75,14 @@ declare module 'vue' {
7475
DocsBrowserSupport: typeof import('./components/docs/DocsBrowserSupport.vue')['default']
7576
DocsCodeActions: typeof import('./components/docs/DocsCodeActions.vue')['default']
7677
DocsCodeGroup: typeof import('./components/docs/DocsCodeGroup.vue')['default']
78+
DocsDiscoveryStep: typeof import('./components/docs/DocsDiscoveryStep.vue')['default']
7779
DocsExample: typeof import('./components/docs/DocsExample.vue')['default']
7880
DocsFaq: typeof import('./components/docs/DocsFaq.vue')['default']
7981
DocsFaqItem: typeof import('./components/docs/DocsFaqItem.vue')['default']
8082
DocsFeedback: typeof import('./components/docs/DocsFeedback.vue')['default']
8183
DocsHeaderAnchor: typeof import('./components/docs/DocsHeaderAnchor.vue')['default']
84+
DocsHighlight: typeof import('./components/docs/DocsHighlight.vue')['default']
85+
DocsKbd: typeof import('./components/docs/DocsKbd.vue')['default']
8286
DocsLastCommit: typeof import('./components/docs/DocsLastCommit.vue')['default']
8387
DocsMarkup: typeof import('./components/docs/DocsMarkup.vue')['default']
8488
DocsMermaid: typeof import('./components/docs/DocsMermaid.vue')['default']
@@ -98,7 +102,6 @@ declare module 'vue' {
98102
DocsToc: typeof import('./components/docs/DocsToc.vue')['default']
99103
DocsVueLink: typeof import('./components/docs/DocsVueLink.vue')['default']
100104
FaqList: typeof import('./components/docs/FaqList.vue')['default']
101-
GuidedTourOverlay: typeof import('./components/skillz/GuidedTourOverlay.vue')['default']
102105
HomeCta: typeof import('./components/home/HomeCta.vue')['default']
103106
HomeDemo: typeof import('./components/home/HomeDemo.vue')['default']
104107
HomeEcosystem: typeof import('./components/home/HomeEcosystem.vue')['default']
@@ -109,14 +112,5 @@ declare module 'vue' {
109112
HomeIntegrations: typeof import('./components/home/HomeIntegrations.vue')['default']
110113
RouterLink: typeof import('vue-router')['RouterLink']
111114
RouterView: typeof import('vue-router')['RouterView']
112-
SkillCard: typeof import('./components/skillz/SkillCard.vue')['default']
113-
SkillHint: typeof import('./components/skillz/SkillHint.vue')['default']
114-
SkillNav: typeof import('./components/skillz/SkillNav.vue')['default']
115-
SkillPlayground: typeof import('./components/skillz/SkillPlayground.vue')['default']
116-
SkillProgress: typeof import('./components/skillz/SkillProgress.vue')['default']
117-
SkillTutorial: typeof import('./components/skillz/SkillTutorial.vue')['default']
118-
TourHighlight: typeof import('./components/tour/TourHighlight.vue')['default']
119-
TourRoot: typeof import('./components/tour/TourRoot.vue')['default']
120-
TourTooltip: typeof import('./components/tour/TourTooltip.vue')['default']
121115
}
122116
}

apps/docs/src/components/app/AppAskInline.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<script setup lang="ts">
22
// Composables
3-
import { useAsk } from '@/composables/useAsk'
3+
import { useAskSheet } from '@/composables/useAskSheet'
44
55
// Utilities
66
import { shallowRef } from 'vue'
77
8-
const { ask } = useAsk()
8+
const { ask } = useAskSheet()
99
const question = shallowRef('')
1010
1111
function onSubmit () {

apps/docs/src/components/app/AppBar.vue

Lines changed: 18 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
<script setup lang="ts">
22
// Framework
3-
import { Atom, useBreakpoints, useDocumentEventListener, useFeatures, useHotkey, useStorage, useTheme } from '@vuetify/v0'
3+
import { Atom, useBreakpoints, useFeatures, useStorage, useTheme } from '@vuetify/v0'
44
55
// Components
66
import { Discovery } from '@/components/discovery'
77
88
// Composables
9-
import { useDiscovery } from '@/composables/useDiscovery'
109
import { useSearch } from '@/composables/useSearch'
1110
import { useSettings } from '@/composables/useSettings'
1211
1312
// Utilities
14-
import { nextTick, ref, toRef, watch } from 'vue'
13+
import { toRef, watch } from 'vue'
1514
import { useRoute } from 'vue-router'
1615
1716
// Types
@@ -29,10 +28,9 @@
2928
const isHomePage = toRef(() => route.path === '/')
3029
3130
const breakpoints = useBreakpoints()
32-
const discovery = useDiscovery()
3331
const features = useFeatures()
3432
const theme = useTheme()
35-
const { open: openSearch } = useSearch()
33+
const search = useSearch()
3634
const { showSkillFilter, showThemeToggle, showSocialLinks } = useSettings()
3735
3836
const devmode = features.get('devmode')!
@@ -45,24 +43,6 @@
4543
? 'https://cdn.vuetifyjs.com/docs/images/logos/vzero-logo-dark.png'
4644
: 'https://cdn.vuetifyjs.com/docs/images/logos/vzero-logo-light.png',
4745
)
48-
49-
discovery.on('start:open-search', () => {
50-
const once = useDocumentEventListener('keydown', (event: KeyboardEvent) => {
51-
if (!event.ctrlKey || event.key !== 'k') return
52-
nextTick(() => {
53-
discovery.next()
54-
once()
55-
})
56-
})
57-
})
58-
59-
discovery.on('back:open-search', () => {
60-
console.log('back to open-search')
61-
})
62-
63-
discovery.on('complete:open-search', () => {
64-
console.log('completed open-search')
65-
})
6646
</script>
6747

6848
<template>
@@ -93,40 +73,21 @@
9373
<AppIcon :icon="app.drawer ? 'close' : 'menu'" />
9474
</button>
9575

96-
<Discovery.Root step="open-search">
97-
<Discovery.Activator class="rounded-2xl" step="open-search">
98-
<button
99-
aria-label="Search (Ctrl+K)"
100-
class="inline-flex items-center gap-1.5 md:bg-glass-surface rounded-full md:border md:border-divider md:pl-1.5 md:pr-1.5 md:py-1.5 hover:border-primary/50 transition-colors"
101-
title="Search (Ctrl+K)"
102-
type="button"
103-
@click="openSearch"
104-
>
105-
<span class="shrink-0 size-6 rounded-full bg-primary text-on-primary flex items-center justify-center">
106-
<AppIcon icon="search" size="12" />
107-
</span>
108-
<span class="hidden md:inline text-sm text-on-surface-variant">Search the docs...</span>
109-
<kbd class="hidden md:inline-flex shrink-0 px-1.5 py-0.5 rounded bg-surface-tint text-on-surface-tint text-[10px] font-mono items-center rounded-r-lg">Ctrl+K</kbd>
110-
</button>
111-
</Discovery.Activator>
112-
113-
<Discovery.Content class="p-4 bg-surface border border-divider rounded-xl shadow-xl max-w-xs">
114-
<div class="flex justify-between items-center">
115-
<Discovery.Title class="text-lg font-semibold text-on-surface mb-1">Open Search</Discovery.Title>
116-
<Discovery.Progress class="text-xs text-on-surface-variant mb-2" />
117-
</div>
118-
119-
<Discovery.Description class="text-sm text-on-surface-variant mb-4">
120-
Press <kbd class="px-1.5 py-0.5 rounded bg-surface-tint text-on-surface-tint text-xs font-mono">Ctrl+K</kbd> to open the search dialog.
121-
</Discovery.Description>
122-
123-
<div class="flex justify-end">
124-
<Discovery.Skip class="px-3 py-1.5 text-sm text-on-surface-variant hover:text-on-surface">
125-
Skip tour
126-
</Discovery.Skip>
127-
</div>
128-
</Discovery.Content>
129-
</Discovery.Root>
76+
<Discovery.Activator class="rounded-2xl" step="open-search">
77+
<button
78+
aria-label="Search (Ctrl+K)"
79+
class="inline-flex items-center gap-1.5 md:bg-glass-surface rounded-full md:border md:border-divider md:pl-1.5 md:pr-1.5 md:py-1.5 hover:border-primary/50 transition-colors"
80+
title="Search (Ctrl+K)"
81+
type="button"
82+
@click="search.open()"
83+
>
84+
<span class="shrink-0 size-6 rounded-full bg-primary text-on-primary flex items-center justify-center">
85+
<AppIcon icon="search" size="12" />
86+
</span>
87+
<span class="hidden md:inline text-sm text-on-surface-variant">Search the docs...</span>
88+
<kbd class="hidden md:inline-flex shrink-0 px-1.5 py-0.5 rounded bg-surface-tint text-on-surface-tint text-[10px] font-mono items-center rounded-r-lg">Ctrl+K</kbd>
89+
</button>
90+
</Discovery.Activator>
13091
</div>
13192

13293
<div class="flex align-center items-center gap-3">

apps/docs/src/components/app/AppMain.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
import DocsToc from '../docs/DocsToc.vue'
66
77
// Composables
8-
import { useAsk } from '@/composables/useAsk'
8+
import { useAskSheet } from '@/composables/useAskSheet'
99
import { useRouterLinks } from '@/composables/useRouterLinks'
1010
import { useSettings } from '@/composables/useSettings'
1111
1212
// Utilities
1313
import { computed, shallowRef, toRef, useTemplateRef } from 'vue'
1414
15-
const { isOpen: isAskOpen } = useAsk()
15+
const { isOpen: isAskOpen } = useAskSheet()
1616
const { prefersReducedMotion } = useSettings()
1717
const page = shallowRef<{ frontmatter?: Record<string, unknown> }>()
1818
const mainRef = useTemplateRef<HTMLElement>('main')
Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
<script setup lang="ts">
2+
// Components
3+
import { Discovery } from '@/components/discovery'
4+
25
// Composables
36
import { useSettings } from '@/composables/useSettings'
47
@@ -13,15 +16,17 @@
1316
</script>
1417

1518
<template>
16-
<button
17-
aria-label="Open settings"
18-
class="bg-surface-tint text-on-surface-tint pa-1 inline-flex rounded hover:bg-surface-variant transition-all cursor-pointer"
19-
title="Settings"
20-
type="button"
21-
@click="toggle"
22-
@focus="preload"
23-
@mouseenter="preload"
24-
>
25-
<AppIcon icon="cog" />
26-
</button>
19+
<Discovery.Activator class="rounded-lg" step="open-settings">
20+
<button
21+
aria-label="Open settings"
22+
class="bg-surface-tint text-on-surface-tint pa-1 inline-flex rounded hover:bg-surface-variant transition-all cursor-pointer"
23+
title="Settings"
24+
type="button"
25+
@click="toggle"
26+
@focus="preload"
27+
@mouseenter="preload"
28+
>
29+
<AppIcon icon="cog" />
30+
</button>
31+
</Discovery.Activator>
2732
</template>

apps/docs/src/components/app/AppSettingsSheet.vue

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
<script setup lang="ts">
2+
// Framework
3+
import { useFeatures, useStorage } from '@vuetify/v0'
4+
25
// Composables
36
import { useCustomThemes } from '@/composables/useCustomThemes'
4-
import { useDiscovery } from '@/composables/useDiscovery'
57
import { useSettings } from '@/composables/useSettings'
68
79
// Utilities
810
import { onUnmounted, useTemplateRef, watch } from 'vue'
911
10-
// Stores
11-
12-
const discovery = useDiscovery()
12+
const features = useFeatures()
13+
const storage = useStorage()
1314
const { close, reset, hasChanges, lineWrap, showInlineApi, collapsibleNav } = useSettings()
1415
15-
function startTour () {
16-
close()
17-
discovery.start('docs-intro')
18-
}
16+
const devmode = features.get('devmode')!
1917
2018
const { isEditing: isEditingTheme, clearPreview } = useCustomThemes()
2119
@@ -34,13 +32,15 @@
3432
el.focus()
3533
})
3634
35+
watch(() => devmode.isSelected.value, isSelected => {
36+
storage.set('devmode', isSelected)
37+
})
38+
3739
function onKeydown (e: KeyboardEvent) {
3840
if (e.key === 'Escape') {
3941
close()
4042
}
4143
}
42-
43-
startTour()
4444
</script>
4545

4646
<template>
@@ -72,22 +72,8 @@
7272
</header>
7373

7474
<!-- Content -->
75-
<div class="flex-1 overflow-y-auto p-4 space-y-6">
76-
<!-- Tour -->
77-
<div class="pb-2 border-b border-divider">
78-
<button
79-
class="w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-surface-variant transition-colors text-on-surface"
80-
type="button"
81-
@click="startTour"
82-
>
83-
<AppIcon class="text-primary" icon="school" size="20" />
84-
<div class="flex-1 text-left">
85-
<div class="text-sm font-medium">Take the tour</div>
86-
<div class="text-xs text-on-surface-variant">Learn how to use the docs</div>
87-
</div>
88-
<AppIcon class="text-on-surface-variant" icon="arrow-right" size="16" />
89-
</button>
90-
</div>
75+
<div class="flex-1 overflow-y-auto p-4 space-y-4">
76+
<AppSettingsTour v-if="devmode.isSelected.value" />
9177

9278
<!-- Theme -->
9379
<AppSettingsTheme />
@@ -134,7 +120,19 @@
134120
<AppSettingsHeaderButtons />
135121

136122
<!-- Reset -->
137-
<div v-if="hasChanges" class="pt-2 border-t border-divider text-end">
123+
<div v-if="hasChanges" class="pt-2 pb-4 border-t border-divider flex justify-between">
124+
<button
125+
aria-label="Enter Developer Mode"
126+
class="inline-flex items-center gap-1 text-xs hover:text-error focus-visible:text-error focus-visible:underline focus-visible:outline-none transition-colors"
127+
:class="[devmode.isSelected.value ? 'text-error' : 'text-on-surface/40' ]"
128+
type="button"
129+
@click="devmode.toggle()"
130+
>
131+
Devmode
132+
133+
<AppIcon v-if="devmode.isSelected.value" icon="vuetify-0" size="12" />
134+
</button>
135+
138136
<button
139137
aria-label="Reset all settings to defaults"
140138
class="text-xs text-on-surface/40 hover:text-error hover:underline focus-visible:text-error focus-visible:underline focus-visible:outline-none transition-colors"

apps/docs/src/components/app/settings/AppSettingsSkillLevel.vue

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
<script setup lang="ts">
2+
// Components
3+
import { Discovery } from '@/components/discovery'
4+
25
// Composables
36
import { useLevelFilterContext } from '@/composables/useLevelFilter'
47
@@ -12,7 +15,7 @@
1215
</script>
1316

1417
<template>
15-
<section>
18+
<Discovery.Activator as="section" class="rounded-lg" :padding="8" step="skill-level">
1619
<h3 class="flex items-center gap-2 text-sm font-medium text-on-surface-variant mb-3">
1720
<AppIcon icon="tune" size="16" />
1821
<span>Skill Level</span>
@@ -29,15 +32,16 @@
2932
>
3033
<span
3134
class="w-5 h-5 rounded border-2 flex items-center justify-center shrink-0"
32-
:class="isSelected(level) ? levelConfig[level].bg : 'border-divider'"
35+
:class="isSelected(level) ? levelConfig[level]!.bg : 'border-divider'"
3336
>
34-
<AppIcon v-if="isSelected(level)" :class="levelConfig[level].text" icon="check" size="12" />
37+
<AppIcon v-if="isSelected(level)" :class="levelConfig[level]!.text" icon="check" size="12" />
3538
</span>
36-
<span>{{ levelConfig[level].label }}</span>
39+
<span>{{ levelConfig[level]!.label }}</span>
3740
</button>
3841
</div>
42+
3943
<p class="text-xs text-on-surface-variant/60 mt-2">
4044
Filter documentation by complexity level
4145
</p>
42-
</section>
46+
</Discovery.Activator>
4347
</template>

0 commit comments

Comments
 (0)