N
Nuxt3w ago
Lennox

Transition of drawer state

Hey, I want to make a Drawer that can have multiple states/menus. Example: First screen should be buttons of what to do (upload as pdf or png) and then it should switch to the new menu. Switching kind of works. But the size of the drawer doesn't animate but rather jumps around. how to fix? I'm using ui3
<UDrawer
should-scale-background
title="Upload"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
v-model:open="drawerOpenState"
>
<UButton
icon="i-heroicons-plus"
class="bottom-14 left-1/2 fixed shadow-sm rounded-full -translate-x-1/2 cursor-pointer transform"
color="primary"
size="xl"
variant="solid"
/>

<template #body>
<div class="transition-all">
<div key="menu-0" class="h-64" v-if="drawerMenuState === 0">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 1">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
<div key="menu-1" class="h-32" v-else-if="drawerMenuState === 1">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 0">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
</div>
</template>
</UDrawer>
<UDrawer
should-scale-background
title="Upload"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
v-model:open="drawerOpenState"
>
<UButton
icon="i-heroicons-plus"
class="bottom-14 left-1/2 fixed shadow-sm rounded-full -translate-x-1/2 cursor-pointer transform"
color="primary"
size="xl"
variant="solid"
/>

<template #body>
<div class="transition-all">
<div key="menu-0" class="h-64" v-if="drawerMenuState === 0">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 1">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
<div key="menu-1" class="h-32" v-else-if="drawerMenuState === 1">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 0">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
</div>
</template>
</UDrawer>
5 Replies
kapa.ai
kapa.ai3w ago
Hi @Lennox. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- I understand you're trying to create a drawer with multiple states/menus that transition smoothly between different heights. The issue you're experiencing is that the drawer size jumps rather than animates when switching between states. The problem is that while you have a transition-all class on your outer div, you're not using Vue's transition component to properly handle the animation between your different menu states. Additionally, the drawer component itself needs to adapt to the changing content height. Here's how you can fix this: 1. Use Vue's built-in <Transition> component to handle the animation between states 2. Make sure your height transitions are properly set up Here's a modified version of your code:
<UDrawer
should-scale-background
title="Upload"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
v-model:open="drawerOpenState"
>
<UButton
icon="i-heroicons-plus"
class="bottom-14 left-1/2 fixed shadow-sm rounded-full -translate-x-1/2 cursor-pointer transform"
color="primary"
size="xl"
variant="solid"
/>
<template #body>
<div>
<Transition name="menu-transition" mode="out-in">
<div :key="`menu-${drawerMenuState}`" class="transition-all duration-300">
<div v-if="drawerMenuState === 0" class="h-64">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 1">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
<div v-else-if="drawerMenuState === 1" class="h-32">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 0">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
</div>
</Transition>
</div>
</template>
</UDrawer>
<UDrawer
should-scale-background
title="Upload"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
v-model:open="drawerOpenState"
>
<UButton
icon="i-heroicons-plus"
class="bottom-14 left-1/2 fixed shadow-sm rounded-full -translate-x-1/2 cursor-pointer transform"
color="primary"
size="xl"
variant="solid"
/>
<template #body>
<div>
<Transition name="menu-transition" mode="out-in">
<div :key="`menu-${drawerMenuState}`" class="transition-all duration-300">
<div v-if="drawerMenuState === 0" class="h-64">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 1">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
<div v-else-if="drawerMenuState === 1" class="h-32">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 0">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
</div>
</Transition>
</div>
</template>
</UDrawer>
Then add these CSS transitions to your component's style section:
<style>
.menu-transition-enter-active,
.menu-transition-leave-active {
transition: all 0.3s ease;
}
.menu-transition-enter-from,
.menu-transition-leave-to {
opacity: 0;
transform: translateY(10px);
}
</style>
<style>
.menu-transition-enter-active,
.menu-transition-leave-active {
transition: all 0.3s ease;
}
.menu-transition-enter-from,
.menu-transition-leave-to {
opacity: 0;
transform: translateY(10px);
}
</style>
This approach uses Vue's transition component with the mode="out-in" property to ensure that the first element transitions out before the second transitions in, which helps with the height animation. The :key attribute ensures Vue properly recognizes when to trigger the transition. The approach is similar to how transitions are handled in Nuxt as described in the JavaScript Hooks documentation, though simplified for your specific use case. If you need more complex transitions, you might want to look into using the transition hooks that Nuxt provides for more advanced animations. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@564190948863508486> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Lennox
LennoxOP3w ago
@kapa.ai no, it should just animate the size of the wrapper inside the body
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I understand you want to animate the size of the wrapper inside the drawer body when switching between menu states. The issue is that the drawer isn't smoothly transitioning its height when the content changes. Based on the knowledge sources, we can use the transition configuration from Nuxt UI's components to achieve this. The accordion component in Nuxt UI has a similar behavior for expanding/collapsing content with height transitions. Here's how you can modify your code to animate the height change:
<UDrawer
should-scale-background
title="Upload"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
v-model:open="drawerOpenState"
>
<UButton
icon="i-heroicons-plus"
class="bottom-14 left-1/2 fixed shadow-sm rounded-full -translate-x-1/2 cursor-pointer transform"
color="primary"
size="xl"
variant="solid"
/>
<template #body>
<div class="overflow-hidden transition-[height] duration-200 ease-out">
<div v-if="drawerMenuState === 0" class="h-64">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 1">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
<div v-else-if="drawerMenuState === 1" class="h-32">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 0">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
</div>
</template>
</UDrawer>
<UDrawer
should-scale-background
title="Upload"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
v-model:open="drawerOpenState"
>
<UButton
icon="i-heroicons-plus"
class="bottom-14 left-1/2 fixed shadow-sm rounded-full -translate-x-1/2 cursor-pointer transform"
color="primary"
size="xl"
variant="solid"
/>
<template #body>
<div class="overflow-hidden transition-[height] duration-200 ease-out">
<div v-if="drawerMenuState === 0" class="h-64">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 1">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
<div v-else-if="drawerMenuState === 1" class="h-32">
<div class="w-1/2">
<!-- file and submit -->
<p @click="drawerMenuState = 0">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Porro
saepe suscipit aperiam! Hic architecto libero debitis similique!
Eaque laudantium vero ab iusto? Ut dolores facilis illo molestias
ex consequuntur vitae.
</p>
</div>
</div>
</div>
</template>
</UDrawer>
I've applied the transition classes from the Nuxt UI accordion component configuration which specifically handles height transitions. The key classes are: - overflow-hidden - Prevents content from spilling out during transition - transition-[height] - Specifically transitions the height property - duration-200 - Sets the transition duration - ease-out - Sets the easing function This approach should allow the drawer to smoothly animate its height when switching between your different menu states. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@564190948863508486> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?