valaxy-theme-press 1.0.0-beta.2 → 1.0.0-rc.10

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.
@@ -1,34 +1,192 @@
1
1
  <script lang="ts" setup>
2
- import { useFrontmatter } from 'valaxy'
2
+ import type { MenuItem } from 'valaxy'
3
+ import { onKeyStroke, useEventListener, useMediaQuery, useThrottleFn } from '@vueuse/core'
4
+ import { onContentUpdated, useFrontmatter, useOutline } from 'valaxy'
5
+ import { computed, nextTick, onMounted, ref } from 'vue'
6
+ import { useI18n } from 'vue-i18n'
3
7
  import { usePressAppStore } from '../stores/app'
4
8
  import PressOutline from './PressOutline.vue'
5
9
 
6
10
  const frontmatter = useFrontmatter()
7
11
  const press = usePressAppStore()
12
+ const { headers } = useOutline()
13
+ const { t } = useI18n()
14
+ const isOverlayAside = useMediaQuery('(max-width: 1279px)')
15
+
16
+ const aside = ref<HTMLElement>()
17
+ const trigger = ref<HTMLButtonElement>()
18
+ const currentSection = ref(1)
19
+ const readingProgress = ref(0)
20
+
21
+ function flattenHeaders(items: MenuItem[]): MenuItem[] {
22
+ return items.flatMap(item => [
23
+ item,
24
+ ...flattenHeaders(item.children || []),
25
+ ])
26
+ }
27
+
28
+ const flatHeaders = computed(() => flattenHeaders(headers.value))
29
+ const totalSections = computed(() => flatHeaders.value.length)
30
+ const readingPercent = computed(() => Math.round(readingProgress.value * 100))
31
+ const readingProgressDasharray = computed(() => `${readingProgress.value} ${1 - readingProgress.value}`)
32
+ const triggerLabel = computed(() => t('theme.outlineTriggerLabel', {
33
+ current: currentSection.value,
34
+ total: totalSections.value,
35
+ progress: readingPercent.value,
36
+ }))
37
+
38
+ function getHeaderElement(link: string) {
39
+ const hash = link.slice(link.indexOf('#') + 1)
40
+
41
+ try {
42
+ return document.getElementById(decodeURIComponent(hash))
43
+ }
44
+ catch {
45
+ return document.getElementById(hash)
46
+ }
47
+ }
48
+
49
+ function updateReadingState() {
50
+ if (!totalSections.value)
51
+ return
52
+
53
+ const pageOffset = 134
54
+ let activeSection = 1
55
+
56
+ for (const [index, header] of flatHeaders.value.entries()) {
57
+ const element = getHeaderElement(header.link)
58
+
59
+ if (element && element.getBoundingClientRect().top <= pageOffset)
60
+ activeSection = index + 1
61
+ }
62
+
63
+ const scrollContainer = document.scrollingElement || document.documentElement
64
+ const scrollableHeight = scrollContainer.scrollHeight - scrollContainer.clientHeight
65
+ const scrollTop = scrollContainer.scrollTop
66
+ const isAtEnd = scrollableHeight - scrollTop <= 1
67
+
68
+ currentSection.value = activeSection
69
+
70
+ if (scrollableHeight <= 0 || isAtEnd) {
71
+ readingProgress.value = 1
72
+ return
73
+ }
74
+
75
+ readingProgress.value = Math.min(1, Math.max(0, scrollTop / scrollableHeight))
76
+ }
77
+
78
+ const updateReadingStateThrottled = useThrottleFn(updateReadingState, 80, true)
79
+
80
+ function closeAside(restoreFocus = false) {
81
+ if (!press.rightSidebar.isOpen)
82
+ return
83
+
84
+ press.rightSidebar.toggle(false)
85
+
86
+ if (restoreFocus)
87
+ nextTick(() => trigger.value?.focus())
88
+ }
89
+
90
+ function toggleAside() {
91
+ const shouldOpen = !press.rightSidebar.isOpen
92
+ press.rightSidebar.toggle(shouldOpen)
93
+
94
+ if (shouldOpen) {
95
+ nextTick(() => {
96
+ const links = aside.value?.querySelectorAll<HTMLElement>('.outline-link')
97
+ links?.item(currentSection.value - 1)?.focus()
98
+ })
99
+ }
100
+ }
101
+
102
+ function onAsideClick(event: MouseEvent) {
103
+ if ((event.target as HTMLElement).closest('.outline-link'))
104
+ closeAside()
105
+ }
106
+
107
+ onKeyStroke('Escape', () => closeAside(true))
108
+ useEventListener('scroll', updateReadingStateThrottled, { passive: true })
109
+ useEventListener('resize', updateReadingStateThrottled)
110
+ onMounted(() => nextTick(updateReadingState))
111
+ onContentUpdated(() => {
112
+ closeAside()
113
+ nextTick(updateReadingState)
114
+ })
8
115
  </script>
9
116
 
10
117
  <template>
11
118
  <button
12
- class="toc-btn shadow-lg fixed press-icon-btn z-99 lt-md:hidden! xl:hidden!"
13
- right="5" bottom="24"
14
- @click="press.rightSidebar.toggle()"
119
+ v-if="frontmatter.toc !== false && headers.length"
120
+ ref="trigger"
121
+ type="button"
122
+ class="toc-btn lt-md:hidden! xl:hidden!"
123
+ :class="{ active: press.rightSidebar.isOpen }"
124
+ :aria-label="triggerLabel"
125
+ :aria-expanded="press.rightSidebar.isOpen"
126
+ aria-controls="press-page-outline"
127
+ @click="toggleAside"
15
128
  >
16
- <div i-ri-file-list-line />
129
+ <svg
130
+ class="toc-progress"
131
+ viewBox="0 0 100 48"
132
+ preserveAspectRatio="none"
133
+ aria-hidden="true"
134
+ >
135
+ <rect
136
+ class="toc-progress-track"
137
+ x="1"
138
+ y="1"
139
+ width="98"
140
+ height="46"
141
+ rx="23"
142
+ pathLength="100"
143
+ />
144
+ <rect
145
+ v-show="readingProgress > 0 && readingProgress < 1"
146
+ class="toc-progress-value"
147
+ x="1"
148
+ y="1"
149
+ width="98"
150
+ height="46"
151
+ rx="23"
152
+ pathLength="1"
153
+ :stroke-dasharray="readingProgressDasharray"
154
+ />
155
+ </svg>
156
+ <span
157
+ v-show="readingProgress >= 1"
158
+ class="toc-progress-complete"
159
+ aria-hidden="true"
160
+ />
161
+ <span i-ri-list-unordered aria-hidden="true" />
162
+ <span class="toc-label">{{ t('theme.outlineButtonLabel') }}</span>
17
163
  </button>
18
164
 
19
- <ValaxyOverlay :show="press.rightSidebar.isOpen" @click="press.rightSidebar.toggle()" />
165
+ <ValaxyOverlay :show="press.rightSidebar.isOpen" @click="closeAside(true)" />
20
166
 
21
167
  <aside
22
- class="press-aside lt-xl:fixed shadow xl:(shadow-none hover:shadow-none) hover:shadow-lg"
168
+ id="press-page-outline"
169
+ ref="aside"
170
+ class="press-aside lt-xl:fixed"
23
171
  flex="~ col grow"
24
172
  p="l-0 xl:l-8" text="center"
25
173
  z="$"
174
+ :aria-label="t('theme.outlineTitle')"
175
+ :aria-hidden="isOverlayAside && !press.rightSidebar.isOpen ? 'true' : undefined"
176
+ :aria-modal="isOverlayAside && press.rightSidebar.isOpen ? 'true' : undefined"
26
177
  :class="press.rightSidebar.isOpen && 'open'"
178
+ :inert="isOverlayAside && !press.rightSidebar.isOpen"
179
+ :role="isOverlayAside ? 'dialog' : undefined"
180
+ @click="onAsideClick"
27
181
  >
28
182
  <div class="aside-curtain" />
29
183
  <div class="aside-container lt-xl:fixed" flex="~ col">
30
184
  <div class="aside-content overflow-auto" flex="~ col">
31
- <PressOutline v-if="frontmatter.toc !== false" />
185
+ <PressOutline
186
+ v-if="frontmatter.toc !== false"
187
+ :closable="isOverlayAside"
188
+ @close="closeAside(true)"
189
+ />
32
190
  <div class="flex-grow" />
33
191
  <div v-if="$slots.default" class="custom-container">
34
192
  <slot />
@@ -46,7 +204,8 @@ const press = usePressAppStore()
46
204
  bottom: 0;
47
205
  right: 0;
48
206
  z-index: var(--pr-z-aside);
49
- width: var(--va-aside-width);
207
+ width: min(320px, calc(100vw - 24px));
208
+ box-shadow: -12px 0 40px rgb(0 0 0 / 0.12);
50
209
  transform: translateX(100%);
51
210
  transition: box-shadow var(--va-transition-duration), opacity var(--va-transition-duration),
52
211
  transform var(--va-transition-duration) cubic-bezier(0.19, 1, 0.22, 1);
@@ -64,6 +223,7 @@ const press = usePressAppStore()
64
223
  top: 0;
65
224
  margin-top: calc(var(--pr-nav-height) * -1 - 20px);
66
225
  padding-top: calc(var(--pr-nav-height) + 20px);
226
+ width: 100%;
67
227
  height: 100vh;
68
228
  background-color: var(--va-c-bg);
69
229
  }
@@ -72,7 +232,7 @@ const press = usePressAppStore()
72
232
  position: fixed;
73
233
  bottom: 0;
74
234
  z-index: 10;
75
- width: 220px;
235
+ width: 100%;
76
236
  height: 32px;
77
237
  background: linear-gradient(transparent,var(--va-c-bg) 70%);
78
238
  }
@@ -83,12 +243,113 @@ const press = usePressAppStore()
83
243
  }
84
244
 
85
245
  .press-aside {
246
+ width: var(--va-aside-width);
247
+ box-shadow: none;
86
248
  transform: translateX(0);
87
249
  }
88
250
  }
89
251
 
90
252
  .toc-btn {
91
- color: var(--va-c-bg);
92
- background-color: var(--va-c-primary);
253
+ position: fixed;
254
+ right: max(20px, env(safe-area-inset-right));
255
+ bottom: max(24px, calc(env(safe-area-inset-bottom) + 20px));
256
+ z-index: calc(var(--pr-z-backdrop) - 1);
257
+ display: inline-flex;
258
+ align-items: center;
259
+ gap: 7px;
260
+ border: 0;
261
+ border-radius: 999px;
262
+ padding: 0 14px 0 13px;
263
+ min-width: 48px;
264
+ height: 48px;
265
+ color: var(--pr-c-text-1);
266
+ background-color: var(--va-c-bg-elevated);
267
+ box-shadow: 0 4px 14px rgb(0 0 0 / 0.08), 0 1px 3px rgb(0 0 0 / 0.06);
268
+ transition:
269
+ box-shadow var(--va-transition-duration),
270
+ color var(--va-transition-duration),
271
+ transform var(--va-transition-duration);
272
+
273
+ &:focus-visible {
274
+ outline: 2px solid var(--va-c-brand);
275
+ outline-offset: 3px;
276
+ }
277
+
278
+ &:active {
279
+ transform: scale(0.98);
280
+ }
281
+
282
+ > [class*='i-ri-'] {
283
+ position: relative;
284
+ z-index: 1;
285
+ flex: none;
286
+ width: 18px;
287
+ height: 18px;
288
+ }
289
+ }
290
+
291
+ .toc-label {
292
+ position: relative;
293
+ z-index: 1;
294
+ letter-spacing: 0.01em;
295
+ line-height: 1;
296
+ font-size: 13px;
297
+ font-weight: 600;
298
+ white-space: nowrap;
299
+ }
300
+
301
+ .toc-progress {
302
+ position: absolute;
303
+ inset: 0;
304
+ width: 100%;
305
+ height: 100%;
306
+ overflow: visible;
307
+ pointer-events: none;
308
+ }
309
+
310
+ .toc-progress-track,
311
+ .toc-progress-value {
312
+ fill: none;
313
+ vector-effect: non-scaling-stroke;
314
+ }
315
+
316
+ .toc-progress-track {
317
+ stroke: color-mix(in srgb, var(--pr-c-text-2) 24%, transparent);
318
+ stroke-width: 1px;
319
+ transition: stroke var(--va-transition-duration);
320
+ }
321
+
322
+ .toc-progress-value {
323
+ stroke: var(--va-c-brand);
324
+ stroke-width: 2px;
325
+ stroke-linecap: round;
326
+ transition: stroke-dasharray 120ms linear;
327
+ }
328
+
329
+ .toc-progress-complete {
330
+ position: absolute;
331
+ inset: 0;
332
+ border: 2px solid var(--va-c-brand);
333
+ border-radius: inherit;
334
+ pointer-events: none;
335
+ }
336
+
337
+ @media (hover: hover) and (pointer: fine) {
338
+ .toc-btn:hover {
339
+ color: var(--va-c-brand);
340
+ box-shadow: 0 6px 18px rgb(0 0 0 / 0.1), 0 1px 4px rgb(0 0 0 / 0.08);
341
+ transform: translateY(-1px);
342
+ }
343
+
344
+ .toc-btn:hover .toc-progress-track {
345
+ stroke: color-mix(in srgb, var(--va-c-brand) 40%, var(--pr-c-text-2));
346
+ }
347
+ }
348
+
349
+ @media (prefers-reduced-motion: reduce) {
350
+ .toc-btn,
351
+ .toc-progress-value {
352
+ transition: none;
353
+ }
93
354
  }
94
355
  </style>
@@ -48,6 +48,11 @@ const { hasSidebar } = useSidebar()
48
48
  color: var(--va-c-text-lighter);
49
49
  }
50
50
 
51
+ .press-footer :deep(a) {
52
+ text-decoration: underline;
53
+ text-underline-offset: 2px;
54
+ }
55
+
51
56
  .message { order: 2; }
52
57
  .copyright { order: 1; }
53
58
  </style>
@@ -1,6 +1,6 @@
1
1
  <script lang="ts" setup>
2
2
  import { isClient, useScrollLock } from '@vueuse/core'
3
- import MarkdownIt from 'markdown-it'
3
+ import { createMarkdownExit } from 'markdown-exit'
4
4
  import { useFuseSearch } from 'valaxy'
5
5
  import { nextTick, ref, watch } from 'vue'
6
6
  import { useI18n } from 'vue-i18n'
@@ -11,7 +11,7 @@ const props = defineProps<{
11
11
 
12
12
  const emit = defineEmits(['close'])
13
13
 
14
- const md = new MarkdownIt({
14
+ const md = createMarkdownExit({
15
15
  html: true,
16
16
  linkify: true,
17
17
  })
@@ -55,7 +55,7 @@ function getResultKey(title: string | Record<string, string>): string {
55
55
  </script>
56
56
 
57
57
  <template>
58
- <Teleport to="body">
58
+ <Teleport to="#valaxy-teleports">
59
59
  <Transition
60
60
  name="modal"
61
61
  @enter="isLocked = true"
@@ -1,4 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { useSiteConfig, withBase } from 'valaxy'
3
+ import { computed } from 'vue'
2
4
  import { useI18n } from 'vue-i18n'
3
5
 
4
6
  defineProps<{
@@ -8,6 +10,10 @@ defineProps<{
8
10
  }>()
9
11
 
10
12
  const { t } = useI18n()
13
+ const siteConfig = useSiteConfig()
14
+ const iconStyle = computed(() => ({
15
+ maskImage: `url("${withBase(siteConfig.value.favicon)}")`,
16
+ }))
11
17
  </script>
12
18
 
13
19
  <template>
@@ -19,7 +25,7 @@ const { t } = useI18n()
19
25
  >
20
26
  <div class="flex justify-center items-center">
21
27
  <div class="svg-wrapper">
22
- <div class="icon" />
28
+ <div class="icon" :style="iconStyle" />
23
29
  </div>
24
30
  <span>
25
31
  {{ t(text) }}
@@ -48,8 +54,6 @@ const { t } = useI18n()
48
54
  transform-origin: center center;
49
55
  transition: all var(--va-transition-duration) ease-in-out;
50
56
 
51
- // mask
52
- mask-image: url('/favicon.svg');
53
57
  mask-size: 100% 100%;
54
58
  background-color: white;
55
59
  width: 1.2em;
@@ -1,10 +1,12 @@
1
1
  <script lang="ts" setup>
2
+ import type { Hero } from '../types'
2
3
  import { useFrontmatter } from 'valaxy'
3
4
  import { computed } from 'vue'
4
5
  import { useLocaleConfig } from '../composables'
5
6
  import PressButton from './PressButton.vue'
6
7
 
7
8
  const fm = useFrontmatter()
9
+ const hero = computed(() => fm.value.hero as Hero | undefined)
8
10
 
9
11
  const { currentLocale, currentLocaleKey, hasLocales } = useLocaleConfig()
10
12
 
@@ -20,7 +22,7 @@ function resolveLocaleLink(link: string): string {
20
22
  }
21
23
 
22
24
  const actions = computed(() => {
23
- return (fm.value.hero?.actions || []).map((action: any) => ({
25
+ return (hero.value?.actions || []).map(action => ({
24
26
  ...action,
25
27
  link: resolveLocaleLink(action.link),
26
28
  }))
@@ -28,20 +30,23 @@ const actions = computed(() => {
28
30
  </script>
29
31
 
30
32
  <template>
31
- <template v-if="fm.hero">
33
+ <template v-if="hero">
32
34
  <div text="center" m="md:t-24 t-10 md:t-20" flex="~ col" justify="center" items="center">
33
- <ValaxyLogo mb="2" />
35
+ <div v-if="hero.image" class="press-hero-image" mb="2">
36
+ <div class="press-hero-image-bg" />
37
+ <PressImage class="fly-animation h-50" :image="hero.image" />
38
+ </div>
34
39
  <h1 my="10" text="4xl md:8xl" font="black" class="gradient-text from-purple-800 to-blue-500 bg-gradient-to-r">
35
- {{ fm.hero.name }}
40
+ {{ hero.name }}
36
41
  </h1>
37
42
  </div>
38
43
 
39
- <h2 v-if="fm.hero?.text" flex="~ wrap justify-center" px="2" m="b-10" text="center 6xl" font="black" leading="tight">
40
- {{ fm.hero.text }}
44
+ <h2 v-if="hero.text" flex="~ wrap justify-center" px="2" m="b-10" text="center 6xl" font="black" leading="tight">
45
+ {{ hero.text }}
41
46
  </h2>
42
47
 
43
- <p v-if="fm.hero?.tagline" m="b-10" text="center xl" op="80">
44
- {{ fm.hero.tagline }}
48
+ <p v-if="hero.tagline" m="b-10" text="center xl" op="80">
49
+ {{ hero.tagline }}
45
50
  </p>
46
51
 
47
52
  <div v-if="actions.length" p="2" text="center" class="flex justify-center items-center">
@@ -64,3 +69,35 @@ const actions = computed(() => {
64
69
  <br>
65
70
  </template>
66
71
  </template>
72
+
73
+ <style scoped>
74
+ .press-hero-image {
75
+ position: relative;
76
+ display: inline-flex;
77
+ justify-content: center;
78
+ align-items: center;
79
+ }
80
+
81
+ .press-hero-image-bg {
82
+ position: absolute;
83
+ border-radius: 50%;
84
+ filter: blur(72px);
85
+ width: 150%;
86
+ height: 150%;
87
+ background-image: linear-gradient(-45deg, rgb(108 34 236) 50%, rgb(59 130 246) 50%);
88
+ opacity: 0.3;
89
+ transition: opacity var(--va-transition-duration-fast);
90
+ }
91
+
92
+ .press-hero-image:hover .press-hero-image-bg {
93
+ opacity: 0.4;
94
+ }
95
+
96
+ .press-hero-image :deep(img) {
97
+ position: relative;
98
+ z-index: 1;
99
+ margin: auto;
100
+ width: auto;
101
+ object-fit: contain;
102
+ }
103
+ </style>
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ import type { ThemeableImage } from '../types'
3
+ import { withBase } from 'valaxy'
4
+
5
+ defineOptions({ inheritAttrs: false })
6
+
7
+ defineProps<{
8
+ image: ThemeableImage
9
+ alt?: string
10
+ }>()
11
+ </script>
12
+
13
+ <template>
14
+ <template v-if="image">
15
+ <img
16
+ v-if="typeof image === 'string' || 'src' in image"
17
+ v-bind="typeof image === 'string' ? $attrs : { ...image, ...$attrs }"
18
+ :src="withBase(typeof image === 'string' ? image : image.src)"
19
+ :alt="alt ?? (typeof image === 'string' ? '' : image.alt || '')"
20
+ >
21
+ <template v-else>
22
+ <PressImage
23
+ class="dark"
24
+ :image="image.dark"
25
+ :alt="image.alt"
26
+ v-bind="$attrs"
27
+ />
28
+ <PressImage
29
+ class="light"
30
+ :image="image.light"
31
+ :alt="image.alt"
32
+ v-bind="$attrs"
33
+ />
34
+ </template>
35
+ </template>
36
+ </template>
37
+
38
+ <style scoped>
39
+ html:not(.dark) img.dark {
40
+ display: none;
41
+ }
42
+
43
+ .dark img.light {
44
+ display: none;
45
+ }
46
+ </style>
@@ -31,6 +31,7 @@ const { headers } = useOutline()
31
31
  <template>
32
32
  <div v-if="hasSidebar" class="press-local-nav">
33
33
  <button
34
+ type="button"
34
35
  class="menu"
35
36
  :aria-expanded="open"
36
37
  aria-controls="pr-sidebar-nav"
@@ -1,5 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import type { MenuItem } from 'valaxy'
3
+ import { onClickOutside } from '@vueuse/core'
3
4
  import { onContentUpdated } from 'valaxy'
4
5
  import { nextTick, ref } from 'vue'
5
6
 
@@ -12,31 +13,31 @@ const props = defineProps<{
12
13
 
13
14
  const open = ref(false)
14
15
  const vh = ref(0)
16
+ const dropdown = ref<HTMLDivElement>()
15
17
  const items = ref<HTMLDivElement>()
16
18
 
17
- onContentUpdated(() => {
19
+ function close() {
18
20
  open.value = false
19
- })
21
+ }
22
+
23
+ onClickOutside(dropdown, close)
24
+ onContentUpdated(close)
20
25
 
21
26
  function toggle() {
22
27
  open.value = !open.value
23
28
  vh.value = window.innerHeight + Math.min(window.scrollY - props.navHeight, 0)
24
29
  }
25
30
 
26
- function onItemClick(e: Event) {
27
- if ((e.target as HTMLElement).classList.contains('outline-link')) {
28
- // disable animation on hash navigation when page jumps
29
- if (items.value)
30
- items.value.style.transition = 'none'
31
+ function onItemClick() {
32
+ // disable animation on hash navigation when page jumps
33
+ if (items.value)
34
+ items.value.style.transition = 'none'
31
35
 
32
- nextTick(() => {
33
- open.value = false
34
- })
35
- }
36
+ nextTick(close)
36
37
  }
37
38
 
38
39
  function scrollToTop() {
39
- open.value = false
40
+ close()
40
41
  window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
41
42
  }
42
43
 
@@ -44,20 +45,32 @@ const { t } = useI18n()
44
45
  </script>
45
46
 
46
47
  <template>
47
- <div class="VPLocalNavOutlineDropdown" :style="{ '--vp-vh': `${vh}px` }">
48
- <button v-if="headers.length > 0" :class="{ open }" @click="toggle">
48
+ <div
49
+ ref="dropdown"
50
+ class="VPLocalNavOutlineDropdown"
51
+ :style="{ '--vp-vh': `${vh}px` }"
52
+ @keydown.esc="close"
53
+ >
54
+ <button
55
+ v-if="headers.length > 0"
56
+ type="button"
57
+ :class="{ open }"
58
+ :aria-expanded="open"
59
+ aria-controls="press-local-outline"
60
+ @click="toggle"
61
+ >
49
62
  {{ t('theme.outlineTitle') }}
50
- <div i-ri-arrow-right-s-line class="icon" />
63
+ <span i-ri-arrow-right-s-line class="icon" aria-hidden="true" />
51
64
  </button>
52
- <button v-else @click="scrollToTop">
65
+ <button v-else type="button" @click="scrollToTop">
53
66
  {{ t('sidebar.return_top') }}
54
67
  </button>
55
68
  <Transition name="flyout">
56
69
  <div
57
70
  v-if="open"
71
+ id="press-local-outline"
58
72
  ref="items"
59
73
  class="items"
60
- @click="onItemClick"
61
74
  >
62
75
  <div class="header">
63
76
  <a class="top-link" href="#" @click="scrollToTop">
@@ -65,7 +78,7 @@ const { t } = useI18n()
65
78
  </a>
66
79
  </div>
67
80
  <div class="py-2 bg-$vp-c-bg-soft">
68
- <PressOutlineItem :headers="headers" />
81
+ <PressOutlineItem :headers="headers" :on-click="onItemClick" />
69
82
  </div>
70
83
  </div>
71
84
  </Transition>
@@ -30,7 +30,7 @@ watch(() => props.open, (val) => {
30
30
  </script>
31
31
 
32
32
  <template>
33
- <Teleport to="body">
33
+ <Teleport to="#valaxy-teleports">
34
34
  <Transition
35
35
  name="modal"
36
36
  @enter="isLocked = true"