How to display two v-navigation-drawer next to each other and be able to hide the right one from the left one?

7.7k Views Asked by At

With Vuetify I would like to display two v-navigation-drawers next to each other and be able to hide the right one with a button within the left one. My current code (see below) displays the right drawer over the left one, but I want it to display right drawer next to the left one (see screens below).

I tried to find something useful in the official documentation and went through a few different sample templates but nothing was helpful in my case.

I was able to come up with the following code:

<template>
  <v-app dark>
    <v-navigation-drawer v-model="leftMenu" app clipped>
      <v-container ma-0 pa-0>
        <v-toolbar flat>
          <span>Some helper toolbar</span>
        </v-toolbar>
      </v-container>

      <v-container pa-1 mt-1>
        <v-layout row wrap>
          <v-list>
            <v-list-tile>
              <v-list-tile-action>
                <span><a @click.stop="toggleRightMenu"><v-icon>android</v-icon> Task Menu</a></span>
              </v-list-tile-action>
            </v-list-tile>
            <v-list-tile>
              <v-list-tile-action>
                <span><v-icon>android</v-icon> Menu Element #1</span>
              </v-list-tile-action>
            </v-list-tile>
          </v-list>
        </v-layout>
      </v-container>
    </v-navigation-drawer>

    <v-navigation-drawer v-model="rightMenu" app clipped>
      <v-container>
        <v-layout>
          <v-list>
            <v-list-tile>
              <v-list-tile-action>
                <span><v-icon>android</v-icon> Testing...</span>
              </v-list-tile-action>
            </v-list-tile>
          </v-list>
        </v-layout>
      </v-container>
    </v-navigation-drawer>

    <v-toolbar app clipped-left>
      <v-toolbar-side-icon @click="leftMenu = !leftMenu"></v-toolbar-side-icon>
      <v-toolbar-title class="headline">
        <span>Testing...</span>
      </v-toolbar-title>
      <v-spacer></v-spacer>
    </v-toolbar>

    <v-content>
      <router-view/>
    </v-content>

    <v-footer app>
      <span>Footer</span>
    </v-footer>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      leftMenu: true,
      rightMenu: false
    }
  },
  methods: {
    toggleRightMenu() {
      this.rightMenu = !this.rightMenu;
    }
  }
}
</script>

Currently I have the following: https://i.ibb.co/txdN0X8/current-drawer.png

I am looking for something like that: https://i.ibb.co/b514yyC/target-drawer.png

3

There are 3 best solutions below

8
On BEST ANSWER

The trick is to have a v-layout that fills the height and contains both of the navigation drawers.

One more thing that you need to make sure to apply is to have a z-index on both navigation drawers. Otherwise, when you toggle the right nav it will go at the top of the left nav. And when you want to toggle the left nav you actually have to toggle both.

I have created a Codepen using your data example.

<v-toolbar flat>
  <v-toolbar-side-icon @click="toggleLeftMenu"></v-toolbar-side-icon>
  <v-toolbar-title class="headline">
    <span>Testing...</span>
  </v-toolbar-title>
  <v-spacer></v-spacer>
</v-toolbar>
<v-layout fill-height>
  <v-navigation-drawer
    style="z-index: 2"
    dark
    clipped
    stateless
    v-model="leftMenu"
  >
    <v-container ma-0 pa-0>
      <v-toolbar flat>
        <span>Some helper toolbar</span>
      </v-toolbar>
    </v-container>
    <v-list>
      <v-list-tile>
        <v-list-tile-action>
          <v-icon @click="rightMenu = !rightMenu">android</v-icon>
        </v-list-tile-action>
        <v-list-tile-content>
          <v-list-tile-title>Task Menu</v-list-tile-title>
        </v-list-tile-content>
      </v-list-tile>
      <v-list-tile>
        <v-list-tile-action>
          <v-icon>android</v-icon>
        </v-list-tile-action>
        <v-list-tile-content>
          <v-list-tile-title>Menu Element #1</v-list-tile-title>
        </v-list-tile-content>
      </v-list-tile>
    </v-list>
  </v-navigation-drawer>
  <v-navigation-drawer
    dark
    style="z-index: 1"
    v-model="rightMenu"
    class="pb-0"
    stateless
  >
    <v-list>
      <v-list-tile>
        <v-list-tile-action>
          <v-icon>android</v-icon>
        </v-list-tile-action>
        <v-list-tile-content>
          <v-list-tile-title>Testing right nav</v-list-tile-title>
        </v-list-tile-content>
      </v-list-tile>
    </v-list>
  </v-navigation-drawer>
</v-layout>

Hope it helps :)

0
On

I made it like bitbucket design, one is fixed (mini-variant) and the other one is a drawer https://codepen.io/admica/pen/PoozMNw?editors=1010

<div id="app">
  <v-app id="inspire">
    <v-navigation-drawer
      
      
       mini-variant
            mini-variant-width="56"
                         app
                         clipped
                         
          
            
    >
      <v-list dense>
        <v-list-item
          v-for="item in items"
          :key="item.text"
          @click=""
        >
          <v-list-item-action>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-action>
          <v-list-item-content>
            <v-list-item-title>
              {{ item.text }}
            </v-list-item-title>
          </v-list-item-content>
        </v-list-item>
        <v-subheader class="mt-3 grey--text text--darken-1">SUBSCRIPTIONS</v-subheader>
        <v-list>
          <v-list-item
            v-for="item in items2"
            :key="item.text"
            @click=""
          >
            <v-list-item-avatar>
              <img
                :src="`https://randomuser.me/api/portraits/men/${item.picture}.jpg`"
                alt=""
              >
            </v-list-item-avatar>
            <v-list-item-title v-text="item.text"></v-list-item-title>
          </v-list-item>
        </v-list>
        <v-list-item
          class="mt-3"
          @click=""
        >
          <v-list-item-action>
            <v-icon color="grey darken-1">add_circle_outline</v-icon>
          </v-list-item-action>
          <v-list-item-title class="grey--text text--darken-1">Browse Channels</v-list-item-title>
        </v-list-item>
        <v-list-item @click="">
          <v-list-item-action>
            <v-icon color="grey darken-1">settings</v-icon>
          </v-list-item-action>
          <v-list-item-title class="grey--text text--darken-1">Manage Subscriptions</v-list-item-title>
        </v-list-item>
      </v-list>
      
      
     
    </v-navigation-drawer>
     
     

    <v-app-bar
      app
      
      color="red"
      dense
    >
      <v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
      <v-icon class="mx-3">fab fa-youtube</v-icon>
      <v-toolbar-title class="mr-5 align-center">
        <span class="title">Youtube</span>
      </v-toolbar-title>
      <v-spacer></v-spacer>
      <v-layout
        row
        align-center
        style="max-width: 650px"
      >
        <v-text-field
          :append-icon-cb="() => {}"
          placeholder="Search..."
          single-line
          append-icon="search"
          color="white"
          hide-details
        ></v-text-field>
      </v-layout>
    </v-app-bar>

    <v-content>
      
      <v-container fluid fill-height>
        <v-layout
          
          align-center
          style="position:relative"
        >
          <v-navigation-drawer
        v-model="drawer"
        
        v-if="drawer"
        
        
        
        
        
                          
        
        
      >
        <v-list-item>
          <v-list-item-avatar>
            <v-img src="https://randomuser.me/api/portraits/men/78.jpg"></v-img>
          </v-list-item-avatar>
  
          <v-list-item-content>
            <v-list-item-title>John Leider</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
  
        <v-divider></v-divider>
  
        <v-list dense>
  
          <v-list-item
            v-for="item in items"
            :key="item.title"
            link
          >
            <v-list-item-icon>
              <v-icon>{{ item.icon }}</v-icon>
            </v-list-item-icon>
  
            <v-list-item-content>
              <v-list-item-title>{{ item.title }}</v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list>
      </v-navigation-drawer>
          ahmed ali 
        </v-layout>
      </v-container>
    </v-content>
  </v-app>
</div>

2
On

You could try achieve by having 2 navigation drawers. The second one's margin-left should be equivalent to the first drawer.

Please take a look at this code pen. Hope this helps.

https://codepen.io/Jubels/pen/xeazYY?&editable=true&editors=101

<div id="app">
  <v-app id="inspire">
    <v-layout
      wrap
      style="height: 200px;"
    >
      <v-container>
        <v-layout justify-center>
          <v-btn
            color="pink"
            dark
            @click.stop="drawer = !drawer"
          >
            Toggle Drawer 1
          </v-btn>
          <v-btn
            color="pink"
            dark
            @click.stop="drawer2 = !drawer2"
          >
            Toggle Drawer 2
          </v-btn>
        </v-layout>
      </v-container>

      <v-navigation-drawer
        v-model="drawer"
        :mini-variant="mini"
        absolute
        dark
      >
        <v-list class="pa-1">
          <v-list-tile v-if="mini" @click.stop="mini = !mini">
            <v-list-tile-action>
              <v-icon>chevron_right</v-icon>
            </v-list-tile-action>
          </v-list-tile>

          <v-list-tile avatar tag="div">
            <v-list-tile-avatar>
              <img src="https://randomuser.me/api/portraits/men/85.jpg">
            </v-list-tile-avatar>

            <v-list-tile-content>
              <v-list-tile-title>John Leider</v-list-tile-title>
            </v-list-tile-content>

            <v-list-tile-action>
              <v-btn icon @click.stop="mini = !mini">
                <v-icon>chevron_left</v-icon>
              </v-btn>
            </v-list-tile-action>
          </v-list-tile>
        </v-list>

        <v-list class="pt-0" dense>
          <v-divider light></v-divider>

          <v-list-tile
            v-for="item in items"
            :key="item.title"
            @click=""
          >
            <v-list-tile-action>
              <v-icon>{{ item.icon }}</v-icon>
            </v-list-tile-action>

            <v-list-tile-content>
              <v-list-tile-title>{{ item.title }}</v-list-tile-title>
            </v-list-tile-content>
          </v-list-tile>
        </v-list>
      </v-navigation-drawer>
      <v-navigation-drawer :style="`margin-left: ${drawer ? '300px' :  '0'}`"
        v-model="drawer2"
        :mini-variant="mini"
        absolute
        dark
      >
        <v-list class="pa-1">
          <v-list-tile v-if="mini" @click.stop="mini = !mini">
            <v-list-tile-action>
              <v-icon>chevron_right</v-icon>
            </v-list-tile-action>
          </v-list-tile>

          <v-list-tile avatar tag="div">
            <v-list-tile-avatar>
              <img src="https://randomuser.me/api/portraits/men/85.jpg">
            </v-list-tile-avatar>

            <v-list-tile-content>
              <v-list-tile-title>John Leider</v-list-tile-title>
            </v-list-tile-content>

            <v-list-tile-action>
              <v-btn icon @click.stop="mini = !mini">
                <v-icon>chevron_left</v-icon>
              </v-btn>
            </v-list-tile-action>
          </v-list-tile>
        </v-list>

        <v-list class="pt-0" dense>
          <v-divider light></v-divider>

          <v-list-tile
            v-for="item in items"
            :key="item.title"
            @click=""
          >
            <v-list-tile-action>
              <v-icon>{{ item.icon }}</v-icon>
            </v-list-tile-action>

            <v-list-tile-content>
              <v-list-tile-title>{{ item.title }}</v-list-tile-title>
            </v-list-tile-content>
          </v-list-tile>
        </v-list>
      </v-navigation-drawer>
    </v-layout>
  </v-app>
</div>