I am doing a sidebar in Nuxt 3 and I have separated the sidebar into two components, namely Sidebar and Hamburger.
I do not understand why does the Transition
in a component in Nuxt 3 is not working?
I am also using useState()
composable to share a state in these two components, please look at my code below:
useStates.ts
export const isNavOpen = useState<Boolean>('isNavOpen', () => false);
Hamburger.vue
<template>
<div id="hamburger" :class="{ 'active': hamburger }" @click.prevent="toggle">
<a v-ripple class="cursor-pointer block align-self-center">
<i class="pi pi-bars text-xl"></i>
</a>
</div>
</template>
<script setup lang="ts">
const hamburger = useState('isNavOpen');
const toggle = () => {
hamburger.value = !hamburger.value;
}
</script>
Sidebar.vue
<template>
<div class="sidebar">
<div class="sidebar-backdrop" @click.prevent="toggle" v-if="sidebar">
<Transition name="slide">
<div v-if="sidebar"
class="sidebar-panel">
<slot></slot>
</div>
</Transition>
</div>
</div>
</template>
<script setup lang="ts">
const sidebar = useState('isNavOpen');
const toggle = () => {
sidebar.value = !sidebar.value;
}
</script>
<style scoped>
.slide-enter-active,
.slide-leave-active
{
transition: transform 0.2s ease;
}
.slide-enter,
.slide-leave-to {
transform: translateX(-100%);
transition: all 150ms ease-in 0s
}
.sidebar-backdrop {
background-color: rgba(0,0,0,.5);
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
cursor: pointer;
}
.sidebar-panel {
overflow-y: auto;
background-color: #130f40;
position: fixed;
left: 0;
top: 0;
height: 100vh;
z-index: 999;
padding: 3rem 20px 2rem 20px;
width: 300px;
}
</style>
I thought the transition should be working in a component in Nuxt 3, please let know what did I miss out? Thank you in advanced!
I have found my solution.
Firstly, the useState should be written as like this:
export const useNavOpen = () => useState<boolean>('navOpen', () => false)
Secondly, do not wrap sidebar-backdrop
with the Transition
, the actual code should look like this:
<template>
<div class="sidebar">
<div class="sidebar-backdrop" @click.prevent="toggle" v-if="sidebar"></div>
<Transition name="slide">
<div v-if="sidebar" class="sidebar-panel">
<slot></slot>
</div>
</Transition>
</div>
</template>
Thirdly, I used slide-enter
, it should be slide-enter-from
, the actual code looks like this:
.slide-enter-active,
.slide-leave-active
{
transition: transform 0.2s ease;
}
.slide-enter-from,
.slide-leave-to {
transform: translateX(-100%);
transition: all 150ms ease-in 0s
}