forked from
npmx.dev/npmx.dev
[READ-ONLY]
a fast, modern browser for the npm registry
1<script setup lang="ts">
2import type { PackageFileTree } from '#shared/types'
3import type { RouteNamedMap } from 'vue-router/auto-routes'
4
5defineProps<{
6 tree: PackageFileTree[]
7 currentPath: string
8 baseUrl: string
9 baseRoute: Pick<RouteNamedMap['code'], 'params'>
10}>()
11
12const isOpen = shallowRef(false)
13
14// Close drawer on navigation
15const route = useRoute()
16watch(
17 () => route.fullPath,
18 () => {
19 isOpen.value = false
20 },
21)
22
23const isLocked = useScrollLock(document)
24// Prevent body scroll when drawer is open
25watch(isOpen, open => (isLocked.value = open))
26</script>
27
28<template>
29 <!-- Toggle button (mobile only) -->
30 <ButtonBase
31 variant="primary"
32 class="md:hidden fixed bottom-4 inset-ie-4 z-45"
33 :aria-label="$t('code.toggle_tree')"
34 @click="isOpen = !isOpen"
35 :classicon="isOpen ? 'i-lucide:x' : 'i-lucide:folder'"
36 />
37
38 <!-- Backdrop -->
39 <Transition
40 enter-active-class="transition-opacity duration-200"
41 enter-from-class="opacity-0"
42 enter-to-class="opacity-100"
43 leave-active-class="transition-opacity duration-200"
44 leave-from-class="opacity-100"
45 leave-to-class="opacity-0"
46 >
47 <div v-if="isOpen" class="md:hidden fixed inset-0 z-40 bg-black/50" @click="isOpen = false" />
48 </Transition>
49
50 <!-- Drawer -->
51 <Transition
52 enter-active-class="transition-transform duration-200"
53 enter-from-class="-translate-x-full"
54 enter-to-class="translate-x-0"
55 leave-active-class="transition-transform duration-200"
56 leave-from-class="translate-x-0"
57 leave-to-class="-translate-x-full"
58 >
59 <aside
60 v-if="isOpen"
61 class="md:hidden fixed inset-y-0 inset-is-0 z-50 w-72 bg-bg-subtle border-ie border-border overflow-y-auto"
62 >
63 <div
64 class="sticky top-0 z-10 bg-bg-subtle border-b border-border px-4 py-3 flex items-center justify-start"
65 >
66 <span class="font-mono text-sm text-fg-muted">{{ $t('code.files_label') }}</span>
67 <span aria-hidden="true" class="flex-shrink-1 flex-grow-1" />
68 <ButtonBase
69 :aria-label="$t('code.close_tree')"
70 @click="isOpen = false"
71 classicon="i-lucide:x"
72 />
73 </div>
74 <CodeFileTree
75 :tree="tree"
76 :current-path="currentPath"
77 :base-url="baseUrl"
78 :base-route="baseRoute"
79 />
80 </aside>
81 </Transition>
82</template>