feat(Drawer): add nested prop

Resolves #4320
This commit is contained in:
Benjamin Canac
2025-07-18 15:55:24 +02:00
parent cad7c45c08
commit e2695ee7e4
4 changed files with 48 additions and 3 deletions

View File

@@ -0,0 +1,15 @@
<template>
<UDrawer :ui="{ content: 'h-full', overlay: 'bg-inverted/30' }">
<UButton label="Open" color="neutral" variant="subtle" trailing-icon="i-lucide-chevron-up" />
<template #footer>
<UDrawer nested :ui="{ content: 'h-full', overlay: 'bg-inverted/30' }">
<UButton color="neutral" variant="outline" label="Open nested" />
<template #content>
<Placeholder class="flex-1 m-4" />
</template>
</UDrawer>
</template>
</UDrawer>
</template>

View File

@@ -328,6 +328,17 @@ name: 'drawer-responsive-example'
--- ---
:: ::
### Nested drawers :badge{label="Soon" class="align-text-top"}
You can nest drawers within each other by using the `nested` prop.
::component-example
---
prettier: true
name: 'drawer-nested-example'
---
::
### With footer slot ### With footer slot
Use the `#footer` slot to add content after the Drawer's body. Use the `#footer` slot to add content after the Drawer's body.

View File

@@ -28,6 +28,20 @@ const inset = ref(false)
</template> </template>
</UDrawer> </UDrawer>
<UDrawer title="Drawer with nested" :inset="inset" :ui="{ content: 'h-full' }" should-scale-background>
<UButton color="neutral" variant="outline" label="Open nested" />
<template #footer>
<UDrawer :inset="inset" nested :ui="{ content: 'h-full' }">
<UButton color="neutral" variant="outline" label="Open nested" />
<template #content>
<Placeholder class="flex-1 m-4" />
</template>
</UDrawer>
</template>
</UDrawer>
<UDrawer title="Drawer with bottom direction" direction="bottom" :inset="inset"> <UDrawer title="Drawer with bottom direction" direction="bottom" :inset="inset">
<UButton color="neutral" variant="outline" label="Open on bottom" /> <UButton color="neutral" variant="outline" label="Open on bottom" />

View File

@@ -37,6 +37,11 @@ export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | '
* @defaultValue true * @defaultValue true
*/ */
portal?: boolean | string | HTMLElement portal?: boolean | string | HTMLElement
/**
* Whether the drawer is nested in another drawer.
* @defaultValue false
*/
nested?: boolean
class?: any class?: any
ui?: Drawer['slots'] ui?: Drawer['slots']
} }
@@ -57,7 +62,7 @@ export interface DrawerSlots {
<script setup lang="ts"> <script setup lang="ts">
import { computed, toRef } from 'vue' import { computed, toRef } from 'vue'
import { VisuallyHidden, useForwardPropsEmits } from 'reka-ui' import { VisuallyHidden, useForwardPropsEmits } from 'reka-ui'
import { DrawerRoot, DrawerTrigger, DrawerPortal, DrawerOverlay, DrawerContent, DrawerTitle, DrawerDescription, DrawerHandle } from 'vaul-vue' import { DrawerRoot, DrawerRootNested, DrawerTrigger, DrawerPortal, DrawerOverlay, DrawerContent, DrawerTitle, DrawerDescription, DrawerHandle } from 'vaul-vue'
import { reactivePick } from '@vueuse/core' import { reactivePick } from '@vueuse/core'
import { useAppConfig } from '#imports' import { useAppConfig } from '#imports'
import { usePortal } from '../composables/usePortal' import { usePortal } from '../composables/usePortal'
@@ -90,7 +95,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.drawer || {}
</script> </script>
<template> <template>
<DrawerRoot v-bind="rootProps"> <component :is="nested ? DrawerRootNested : DrawerRoot" v-bind="rootProps">
<DrawerTrigger v-if="!!slots.default" as-child :class="props.class"> <DrawerTrigger v-if="!!slots.default" as-child :class="props.class">
<slot /> <slot />
</DrawerTrigger> </DrawerTrigger>
@@ -144,5 +149,5 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.drawer || {}
</slot> </slot>
</DrawerContent> </DrawerContent>
</DrawerPortal> </DrawerPortal>
</DrawerRoot> </component>
</template> </template>