Skip to content

Commit 7a387de

Browse files
authored
feat(ui): NDrawer component (#435)
1 parent 5582824 commit 7a387de

8 files changed

Lines changed: 92 additions & 121 deletions

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<script setup lang="ts">
2+
import { ref } from 'vue'
3+
import { onClickOutside, useElementSize } from '@vueuse/core'
4+
5+
const props = withDefaults(defineProps<{
6+
modelValue?: boolean
7+
top?: HTMLElement | string
8+
left?: HTMLElement | string
9+
autoClose?: boolean
10+
transition?: 'right' | 'bottom' | 'top'
11+
}>(), {
12+
transition: 'right',
13+
})
14+
15+
const emit = defineEmits<{
16+
(e: 'close'): void
17+
}>()
18+
19+
const el = ref<HTMLElement>()
20+
21+
const { height } = useElementSize(() => props.top as HTMLElement, undefined, { box: 'border-box' })
22+
23+
const width = typeof props.left === 'string' && props.left.startsWith('#')
24+
? document.querySelector(props.left)?.getBoundingClientRect().width
25+
: useElementSize(() => props.left as HTMLElement, undefined, { box: 'border-box' }).width
26+
27+
onClickOutside(el, () => {
28+
if (props.modelValue && props.autoClose)
29+
emit('close')
30+
}, {
31+
ignore: ['a', 'button', 'summary', '[role="dialog"]'],
32+
})
33+
34+
const transitionType = {
35+
right: {
36+
'enter-from-class': 'transform translate-x-1/1',
37+
'leave-to-class': 'transform translate-x-1/1',
38+
},
39+
top: {
40+
'enter-from-class': 'transform translate-y--1/1',
41+
'leave-to-class': 'transform translate-y--1/1',
42+
},
43+
bottom: {
44+
'enter-from-class': 'transform translate-y-1/1',
45+
'leave-to-class': 'transform translate-y-1/1',
46+
},
47+
}
48+
</script>
49+
50+
<template>
51+
<Transition
52+
v-bind="transitionType[transition]"
53+
enter-active-class="duration-200 ease-in"
54+
enter-to-class="opacity-100"
55+
leave-active-class="duration-200 ease-out"
56+
leave-from-class="opacity-100"
57+
>
58+
<div
59+
v-if="modelValue"
60+
ref="el"
61+
:border="`${transition === 'right' ? 'l' : transition === 'bottom' ? 't' : 'b'} base`"
62+
flex="~ col gap-1"
63+
:class="{ 'right-0': transition === 'right' || transition === 'bottom' }"
64+
absolute bottom-0 z-10 z-20 of-auto text-sm glass-effect
65+
:style="{
66+
top: transition === 'bottom' ? 'auto' : `${height}px`,
67+
left: transition === 'right' && !width ? 'auto' : `${width}px`,
68+
}"
69+
v-bind="$attrs"
70+
>
71+
<NIconButton absolute right-2 top-2 z-20 text-xl icon="carbon-close" @click="$emit('close')" />
72+
<div relative h-full w-full of-auto>
73+
<slot />
74+
</div>
75+
</div>
76+
</Transition>
77+
</template>

packages/devtools/client/components/ComponentsGraph.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,10 @@ function setFilter() {
259259
</div>
260260
</div>
261261
</NCard>
262-
<DrawerRight
262+
<NDrawer
263263
:model-value="!!(selected && selected.component)"
264-
:navbar="navbar"
265-
w-80
264+
:top="navbar"
265+
border="t l base" w-80
266266
@close="selected = undefined"
267267
>
268268
<div v-if="selected && selected.component" py4 pt4 flex="~ col">
@@ -277,6 +277,6 @@ function setFilter() {
277277
</NButton>
278278
</div>
279279
</div>
280-
</DrawerRight>
280+
</NDrawer>
281281
</div>
282282
</template>

packages/devtools/client/components/DataSchemaDrawer.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ function copyToClipboard() {
7272

7373
<template>
7474
<Teleport v-if="language" to="body">
75-
<DrawerRight :model-value="!!input?.input" auto-close max-w-screen w-2xl n-code-block @close="input = null">
75+
<NDrawer :model-value="!!input?.input" auto-close max-w-screen w-2xl n-code-block @close="input = null">
7676
<div border="b base" flex="~ items-center gap-2" sticky left-0 right-0 top-0 z-1 p3 bg-base>
7777
<p mr-2>
7878
Schema
@@ -106,6 +106,6 @@ function copyToClipboard() {
106106
<NIconButton icon="carbon-copy" border="~ base" mr-6 p3.1 @click="copyToClipboard()" />
107107
</div>
108108
<NCodeBlock v-if="generatedJson" :lang="shikiLanguage" :code="generatedJson" />
109-
</DrawerRight>
109+
</NDrawer>
110110
</Teleport>
111111
</template>

packages/devtools/client/components/DrawerBottom.vue

Lines changed: 0 additions & 54 deletions
This file was deleted.

packages/devtools/client/components/DrawerRight.vue

Lines changed: 0 additions & 54 deletions
This file was deleted.

packages/devtools/client/components/TimelineView.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,17 @@ function toggleView() {
9393
@select="s => selected = s"
9494
/>
9595
</div>
96-
<DrawerBottom
96+
<NDrawer
9797
:model-value="!!selected"
9898
auto-close
99+
transition="bottom"
100+
left="#nuxt-devtools-side-nav"
99101
@close="selected = undefined"
100102
>
101103
<div min-h-50 px3 py2>
102104
<TimelineDetailsFunction v-if="selected?.type === 'function'" :record="selected" />
103105
<TimelineDetailsRoute v-else-if="selected?.type === 'route'" :record="selected" />
104106
</div>
105-
</DrawerBottom>
107+
</NDrawer>
106108
</div>
107109
</template>

packages/devtools/client/pages/modules/assets.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,14 @@ const navbar = ref<HTMLElement>()
125125
:item="item"
126126
/>
127127
</div>
128-
<DrawerRight
128+
<NDrawer
129129
:model-value="!!selected"
130130
auto-close w-120
131-
:navbar="navbar"
131+
:top="navbar"
132132
@close="selected = undefined"
133133
>
134134
<AssetDetails v-if="selected" v-model="selected" />
135-
</DrawerRight>
135+
</NDrawer>
136136
</div>
137137
</template>
138138

packages/devtools/client/pages/modules/server-routes.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ function capitalize(str: string) {
178178
</NPanelGrids>
179179
</template>
180180
</PanelLeftRight>
181-
<DrawerRight v-model="inputDefaultsDrawer" auto-close max-w-xl min-w-xl @close="inputDefaultsDrawer = false">
181+
<NDrawer v-model="inputDefaultsDrawer" auto-close max-w-xl min-w-xl @close="inputDefaultsDrawer = false">
182182
<div>
183183
<div p4 border="b base">
184184
<span text-lg>Default Inputs</span>
@@ -195,5 +195,5 @@ function capitalize(str: string) {
195195
<ServerRouteInputs v-model="inputDefaults[tab]" py0 :default="{ type: 'string' }" />
196196
</NSectionBlock>
197197
</div>
198-
</DrawerRight>
198+
</NDrawer>
199199
</template>

0 commit comments

Comments
 (0)