Vuetify navigation drawer keep list item colored on click

Viewed 759

I have created a navigation drawer but cannot achieve to keep background on item click.

what i have for now is custom scoped css for the list that looks like.

enter image description here

What i want to achieve is that the background green color remains on click. and change list item backround according to whereever i click between default background and my style.

For now my code looks like.

<v-navigation-drawer
          v-model="drawer"
          :mini-variant.sync="mini"
          height="100vh"
          permanent
          color="blue-grey darken-4"
        >
          <v-list-item class="px-2">
            <v-list-item-avatar>
              <v-img src="https://randomuser.me/api/portraits/men/85.jpg" />
            </v-list-item-avatar>

            <v-list-item-title class="ListItemClass">
              John Leider
            </v-list-item-title>

            <v-btn
              icon
              @click.stop="mini = !mini"
              color="blue-grey lighten-5"
            >
              <v-icon>mdi-chevron-left</v-icon>
            </v-btn>
          </v-list-item>

          <v-list-item class="mb-1 px-2">
            <v-list-item-icon>
              <v-btn
                icon
                @click.stop="mini = !mini"
                color="blue-grey lighten-5"
              >
                <v-icon>mdi-arrow-expand-horizontal</v-icon>
              </v-btn>
            </v-list-item-icon>
          </v-list-item>
          <div
            id="divider"
            style="background-color:#f5f5f5; height: 2px; width:80%;margin: 0 auto;;"
          />

          <v-list dense>
            <v-list-item
              class="SelectedTile"
              v-for="item in items"
              :key="item.title"
              link
            >
              <v-list-item-icon>
                <v-icon color="blue-grey lighten-5">
                  {{ item.icon }}
                </v-icon>
              </v-list-item-icon>

              <v-list-item-content color="blue-grey lighten-5">
                <v-list-item-title class="ListItemClass">
                  {{ item.title }}
                </v-list-item-title>
              </v-list-item-content>
            </v-list-item>
          </v-list>
        </v-navigation-drawer>

And my style

<style scoped>
.ListItemClass {
  color: #f5f5f5;
}
.SelectedTile:hover {
    border-radius: 4px;
    background: #455A64
}
.SelectedTile:active {
    border-radius: 4px;
    background: rgba(10, 204, 117, 0.19)
}
</style>

I connot figure out how to do it.

Thanks for the help

2 Answers

If you are creating v-navigation-drawer for the whole app, it would be better if you will change something in your template.

I hope you are using vue-router to navigate between pages.

Your App.vue should look like this:

<template>
  <v-app>
    <v-navigation-drawer
      app
      ...another props
    >
      ...navigation-drawer internal data
    </v-navigation-drawer>
    
    <v-main>
      <v-container fluid>
        <router-view></router-view>
      </v-container>
    </v-main>
  </v-app>
</template>

With a template like this you can use an active-class prop inside your v-list-item component this way:

...
<v-list dense>
  <v-list-item
    class="SelectedTile"
    active-class="SelectedTile-active"
    v-for="item in items"
    :key="item.title"
    :to="item.path"
    link
  >
    <v-list-item-icon>
      <v-icon color="blue-grey lighten-5">
        {{ item.icon }}
      </v-icon>
    </v-list-item-icon>

    <v-list-item-content color="blue-grey lighten-5">
      <v-list-item-title class="ListItemClass">
        {{ item.title }}
      </v-list-item-title>
    </v-list-item-content>
  </v-list-item>
</v-list>
...
<script>
export default {
  ...
  data() {
    return {
      ...
      items: [
        { title: "First", icon: "mdi-home", path: "/first" },
        { title: "Second", icon: "mdi-send", path: "/second" },
        { title: "Third", icon: "mdi-lock", path: "/third" },
      ],
    };
  },
};
</script>

<style scoped>
.ListItemClass {
  color: #f5f5f5;
}

.SelectedTile:hover {
    border-radius: 4px;
    background: #455A64
}

.SelectedTile-active {
  border-radius: 4px;
  background: rgba(10, 204, 117, 0.19)
}
</style>

Check this demo at CodeSandbox.


If for some reason you cannot use the first method, try this:

To create a group of selectable v-list-item's you can wrap it into v-list-item-group component:

...
<v-list dense>
  <v-list-item-group
    v-model="selectedItem"
    active-class="SelectedTile-active"
    mandatory
  >
    <v-list-item
      class="SelectedTile"
      v-for="item in items"
      :key="item.title"
      link
    >
      <v-list-item-icon>
        <v-icon color="blue-grey lighten-5">
          {{ item.icon }}
        </v-icon>
      </v-list-item-icon>

      <v-list-item-content color="blue-grey lighten-5">
        <v-list-item-title class="ListItemClass">
          {{ item.title }}
        </v-list-item-title>
      </v-list-item-content>
    </v-list-item>
  </v-list-item-group>
</v-list>
...
data: () => ({
  ...
  selectedItem: 0,
})
...
<style scoped>
.ListItemClass {
  color: #f5f5f5;
}

.SelectedTile:hover {
    border-radius: 4px;
    background: #455A64
}

.SelectedTile-active {
  border-radius: 4px;
  background: rgba(10, 204, 117, 0.19)
}
</style>

But as you can see, if you are using mandatory prop in v-list-item-group component, at least one item should always be selected.

I was in the second case, without any possibilities to apply drawer globally.

Your second option work like a charm with a little adjustment

i have to put the active-class="SelectedTile-active" props at the v-list-item level

<v-navigation-drawer
  v-model="drawer"
  :mini-variant.sync="mini"
  height="100vh"
  permanent
  color="blue-grey darken-4"
>
  <v-list-item class="px-2">
    <v-list-item-avatar>
      <v-img :src="'data:'+UserData.avatardatatype+';base64,'+UserData.avatarcontent" />
      <!--<v-img src="https://randomuser.me/api/portraits/men/85.jpg" />-->
    </v-list-item-avatar>

    <v-list-item-title class="ListItemClass">
      {{ UserData.UserName }}
    </v-list-item-title>
    <v-btn
      icon
      @click.stop="mini = !mini"
      color="blue-grey lighten-5"
      class="pr-5"
    >
      <v-icon>mdi-chevron-left</v-icon>
    </v-btn>
  </v-list-item>

  <v-list-item class="mb-1 px-2">
    <v-list-item-icon>
      <v-btn
        icon
        @click.stop="mini = !mini"
        color="blue-grey lighten-5"
      >
        <v-icon>mdi-arrow-expand-horizontal</v-icon>
      </v-btn>
    </v-list-item-icon>
  </v-list-item>
  <div
    id="divider"
    style="background-color:#f5f5f5; height: 2px; width:80%;margin: 0 auto;"
  />

  <v-list shaped>
    <v-list-item-group
      v-model="selectedItem"
    >
      <template v-for="(item, i) in items">
        <v-list-item
          :key="i"
          :value="item"
          active-class="SelectedTile"
        >
          <v-list-item-icon>
            <v-icon color="blue-grey lighten-5">
              {{ item.icon }}
            </v-icon>
            <v-list-item-content color="blue-grey lighten-5">
              <v-list-item-title
                style="color:#ECEFF1;"
                class="mx-2"
                v-text="item.title"
              />
            </v-list-item-content>
          </v-list-item-icon>
        </v-list-item>
      </template>
    </v-list-item-group>
  </v-list>
</v-navigation-drawer>
Related