Categories
Vuetify

Vuetify — Timeline Customization

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Reverse Direction

We can reverse the direction of the timeline items with the reverse prop:

<template>
  <v-timeline align-top :dense="$vuetify.breakpoint.smAndDown" reverse>
    <v-timeline-item
      v-for="(item, i) in items"
      :key="i"
      :color="item.color"
      :icon="item.icon"
      fill-dot
    >
      <v-card :color="item.color" dark>
        <v-card-title class="title">Lorem Ipsum Dolor</v-card-title>
        <v-card-text class="white text--primary">
          <p>Lorem ipsum dolor sit amet.</p>
          <v-btn :color="item.color" class="mx-0" outlined>Button</v-btn>
        </v-card-text>
      </v-card>
    </v-timeline-item>
  </v-timeline>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    items: [
      {
        color: "red lighten-2",
        icon: "mdi-star",
      },
      {
        color: "purple darken-1",
        icon: "mdi-book-variant",
      },
      {
        color: "green lighten-1",
        icon: "mdi-airballoon",
      },
    ],
  }),
};
</script>

Timeline Card

We can place a v-card in a v-timeline-item component.

A caret will appear on the side of the card.

For example, we can write:

<template>
  <v-timeline>
    <v-timeline-item v-for="n in 3" :key="n" color="red lighten-2" large>
      <template v-slot:opposite>
        <span>Foo</span>
      </template>
      <v-card class="elevation-2">
        <v-card-title class="headline">Lorem ipsum</v-card-title>
        <v-card-text>Lorem ipsum dolor sit amet.</v-card-text>
      </v-card>
    </v-timeline-item>
  </v-timeline>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

The opposite slot has some text.

And the cards will be displayed on the side opposite of the opposite slot.

Dense Alert

We can make the timeline smaller with the dense prop.

For example, we can write:

<template>
  <v-card class="mx-auto" max-width="600">
    <v-card-title class="blue-grey white--text">
      <span class="title">Logs</span>
    </v-card-title>
    <v-card-text class="py-0">
      <v-timeline dense>
        <v-slide-x-reverse-transition group hide-on-leave>
          <v-timeline-item v-for="item in items" :key="item.id" :color="item.color" small fill-dot>
            <v-alert
              :value="true"
              :color="item.color"
              :icon="item.icon"
              class="white--text"
            >Lorem ipsum dolor sit amet.</v-alert>
          </v-timeline-item>
        </v-slide-x-reverse-transition>
      </v-timeline>
    </v-card-text>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    items: [
      {
        id: 1,
        color: "red lighten-2",
        icon: "mdi-star",
      },
      {
        id: 2,
        color: "purple darken-1",
        icon: "mdi-book-variant",
      },
      {
        id: 3,
        color: "green lighten-1",
        icon: "mdi-airballoon",
      },
    ],
  }),
};
</script>

We added the dense prop to the v-timeline to display items in a compressed form.

The entries will all be on the right side and they’re smaller than the default size.

Opposite Slot

The opposite slot lets us put items to the opposite side of the timeline item.

For example, we can write:

<template>
  <v-timeline>
    <v-timeline-item v-for="(year, i) in years" :key="i" :color="year.color" small>
      <template v-slot:opposite>
        <span :class="`headline font-weight-bold ${year.color}--text`" v-text="year.year"></span>
      </template>
      <div class="py-4">
        <h2 :class="`headline font-weight-light mb-4 ${year.color}--text`">Lorem ipsum</h2>
        <div>Lorem ipsum dolor sit amet.</div>
      </div>
    </v-timeline-item>
  </v-timeline>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    years: [
      {
        color: "cyan",
        year: "1960",
      },
      {
        color: "green",
        year: "1970",
      },
      {
        color: "pink",
        year: "1980",
      },
    ],
  }),
};
</script>

We have the opposite slot to add items to the opposite side of our main timeline item content.

Conclusion

We can add timeline items in various ways with Vuetify.

Categories
Vuetify

Vuetify — Timeline Avatar and Tooltips

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Timeline Avatar Dots

The dots on the timeline can be avatars.

For example, we can write:

<template>
  <v-timeline>
    <v-timeline-item v-for="n in 3" :key="n" large>
      <template v-slot:icon>
        <v-avatar>
          <img src="http://i.pravatar.cc/64" />
        </v-avatar>
      </template>
      <template v-slot:opposite>
        <span>Tus eu perfecto</span>
      </template>
      <v-card class="elevation-2">
        <v-card-title class="headline">Lorem ipsum</v-card-title>
        <v-card-text>Lorem ipsum dolor sit amet.</v-card-text>
      </v-card>
    </v-timeline-item>
  </v-timeline>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

We put the avatar icon in the icon slot to show it.

Colored Dots

The dots can be colored.

To change the color, we set the value for the color prop on the v-timeline-item :

<template>
  <v-card class="mx-auto" max-width="400">
    <v-card-text class="py-0">
      <v-timeline align-top dense>
        <v-timeline-item color="pink" small>
          <v-row class="pt-1">
            <v-col cols="3">
              <strong>5pm</strong>
            </v-col>
            <v-col>
              <strong>New Icon</strong>
              <div class="caption">Mobile App</div>
            </v-col>
          </v-row>
        </v-timeline-item>

        <v-timeline-item color="teal lighten-3" small>
          <v-row class="pt-1">
            <v-col cols="3">
              <strong>3-4pm</strong>
            </v-col>
            <v-col>
              <strong>Meeting</strong>
              <div class="caption mb-2">Hangouts</div>
            </v-col>
          </v-row>
        </v-timeline-item>

        <v-timeline-item color="pink" small>
          <v-row class="pt-1">
            <v-col cols="3">
              <strong>12pm</strong>
            </v-col>
            <v-col>
              <strong>Lunch break</strong>
            </v-col>
          </v-row>
        </v-timeline-item>

        <v-timeline-item color="teal lighten-3" small>
          <v-row class="pt-1">
            <v-col cols="3">
              <strong>9-11am</strong>
            </v-col>
            <v-col>
              <strong>Go Home</strong>
              <div class="caption">Web App</div>
            </v-col>
          </v-row>
        </v-timeline-item>
      </v-timeline>
    </v-card-text>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

Tooltips

We can add tooltips with the v-tooltip component.

For instance, we can write:

<template>
  <div class="text-center">
    <v-tooltip left>
      <template v-slot:activator="{ on, attrs }">
        <v-btn color="primary" dark v-bind="attrs" v-on="on">Left</v-btn>
      </template>
      <span>Left tooltip</span>
    </v-tooltip>
  </div>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

The v-tooltip component has the activator slot to let us place the component for activating the tooltip.

The left prop places the tooltip on the left.

The placement of the toolbar can also be changed with the top , bottom , and right props.

We just pass the on event listeners to the v-on directive and the attrs object to the v-bind directive.

Visibility

We can change the visibility of the tooltip with v-model .

For example, we can write:

<template>
  <v-container fluid class="text-center">
    <v-row class="flex" justify="space-between">
      <v-col cols="12">
        <v-btn @click="show = !show">toggle</v-btn>
      </v-col>

     <v-col cols="12" class="mt-12">
        <v-tooltip v-model="show" top>
          <template v-slot:activator="{ on, attrs }">
            <v-btn icon v-bind="attrs" v-on="on">
              <v-icon color="grey lighten-1">mdi-cart</v-icon>
            </v-btn>
          </template>
          <span>Programmatic tooltip</span>
        </v-tooltip>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    show: false,
  }),
};
</script>

We have a Toggle button to toggle the show prop to toggle the tooltip.

v-model on the v-tooltip controls the tooltip.

Conclusion

We can add avatars and timelines and add tooltips with Vuetify.

Categories
Vuetify

Vuetify — Tabs with Other Components

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Align Tabs with Toolbar Title

We can align tabs with the toolbar title.

To do that, we write:

<template>
  <v-card>
    <v-toolbar color="cyan" dark flat>
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
      <v-toolbar-title>App</v-toolbar-title>
      <v-spacer></v-spacer>
      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
      <template v-slot:extension>
        <v-tabs v-model="tab" centered slider-color="yellow" align-with-title>
          <v-tab v-for="i in 3" :key="i" :href="`#tab-${i}`">Item {{ i }}</v-tab>
        </v-tabs>
      </template>
    </v-toolbar>

    <v-tabs-items v-model="tab">
      <v-tab-item v-for="i in 3" :key="i" :value="`tab-${i}`">
        <v-card flat>
          <v-card-text v-text="'hello world'"></v-card-text>
        </v-card>
      </v-tab-item>
    </v-tabs-items>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      tab: null,
    };
  },
};
</script>

We add the align-with-title prop to align the title with toolbar title.

Dynamic Tabs

We can add tabs that can be dynamically added or removed.

For example, we can write:

<template>
  <v-card>
    <v-tabs v-model="tab" background-color="red lighten-2" dark>
      <v-tab v-for="n in length" :key="n">Item {{ n }}</v-tab>
    </v-tabs>
    <v-card-text class="text-center">
      <v-btn text @click="length--">Remove Tab</v-btn>
      <v-divider class="mx-4" vertical></v-divider>
      <v-btn text @click="length++">Add Tab</v-btn>
    </v-card-text>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    length: 10,
    tab: null,
  }),

  watch: {
    length(val) {
      this.tab = val - 1;
    },
  },
};
</script>

We change the length state to add or remove tabs.

We can do that because we’re using length to render the number of tabs with v-for .

Also, we watch the length so that we change to the last tab once a tab is added or removed.

With Search

We can also add tabs with a search box.

To do that, we write:

<template>
  <v-card>
    <v-toolbar color="purple" dark flat prominent>
      <v-text-field
        append-icon="mic"
        class="mx-4"
        flat
        hide-details
        label="Search"
        prepend-inner-icon="search"
        solo-inverted
      ></v-text-field>

      <template v-slot:extension>
        <v-tabs v-model="tabs" centered>
          <v-tab v-for="n in 3" :key="n">Item {{ n }}</v-tab>
        </v-tabs>
      </template>
    </v-toolbar>

    <v-tabs-items v-model="tabs">
      <v-tab-item>
        <v-card flat>
          <v-card-text>Lorem ipsum dolor sit amet.</v-card-text>
        </v-card>
      </v-tab-item>
      <v-tab-item>
        <v-card flat>
          <v-card-title class="headline">Title</v-card-title>
          <v-card-text>
            <p>Duis lobortis massa imperdiet quam.</p>
          </v-card-text>
        </v-card>
      </v-tab-item>
      <v-tab-item>
        <v-card flat>
          <v-card-title class="headline">Title</v-card-title>
          <v-card-text>
            <p>Maecenas ullamcorpe.</p>
          </v-card-text>
        </v-card>
      </v-tab-item>
    </v-tabs-items>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    tabs: null,
    text: "Lorem ipsum dolor sit amet.",
  }),
};
</script>

The v-text-field is added above the extension slot so that we can see the search box above the tabs.

Conclusion

Tabs can be added to toolbars and added with other elements.

Categories
Vuetify

Vuetify — Tabs Customization

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Custom Icons

We can change the tab scrolling icons with the prev-icon and next-icon props:

<template>
  <v-card>
    <v-tabs
      v-model="tab"
      background-color="primary"
      show-arrows
      dark
      next-icon="mdi-arrow-right-bold-box-outline"
      prev-icon="mdi-arrow-left-bold-box-outline"
    >
      <v-tab v-for="item in items" :key="item.tab">{{ item.tab }}</v-tab>
    </v-tabs>

    <v-tabs-items v-model="tab">
      <v-tab-item v-for="item in items" :key="item.tab">
        <v-card flat>
          <v-card-text>{{ item.content }}</v-card-text>
        </v-card>
      </v-tab-item>
    </v-tabs-items>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      tab: null,
      items: [
        { tab: "One", content: "Tab 1 Content" },
        { tab: "Two", content: "Tab 2 Content" },
        { tab: "Three", content: "Tab 3 Content" },
        { tab: "Four", content: "Tab 4 Content" },
        { tab: "Five", content: "Tab 5 Content" },
      ],
    };
  },
};
</script>

We changed the icons to a bold arrow instead of a regular arrow.

Icons and Text

The tab links can have both an icon and text.

For instance, we can write:

<template>
  <v-card>
    <v-tabs v-model="tab" background-color="deep-purple accent-4" centered dark icons-and-text>
      <v-tabs-slider></v-tabs-slider>

       <v-tab href="#tab-1">
        Recents
        <v-icon>mdi-phone</v-icon>
      </v-tab>

      <v-tab href="#tab-2">
        Favorites
        <v-icon>mdi-heart</v-icon>
      </v-tab>

      <v-tab href="#tab-3">
        Map
        <v-icon>mdi-account-box</v-icon>
      </v-tab>
    </v-tabs>

    <v-tabs-items v-model="tab">
      <v-tab-item v-for="i in 3" :key="i" :value="`tab-${i}`">
        <v-card flat>
          <v-card-text>hello world</v-card-text>
        </v-card>
      </v-tab-item>
    </v-tabs-items>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      tab: null,
    };
  },
};
</script>

We have the v-icon inside the v-tab component to add the icon.

The icon will show above the text.

Right-Aligned Tabs

The tabs can be aligned to the right.

For example, we can write:

<template>
  <v-card>
    <v-tabs background-color="white" color="deep-purple accent-4" right>
      <v-tab>Foo</v-tab>
      <v-tab>Bar</v-tab>
      <v-tab>Baz</v-tab>

      <v-tab-item v-for="n in 3" :key="n">
        <v-container fluid>
          <v-row>
            <v-col v-for="i in 6" :key="i" cols="12" md="4">
              <v-img
                :src="`https://picsum.photos/500/300?image=${i}`"
                :lazy-src="`https://picsum.photos/10/6?image=${i}`"
                aspect-ratio="1"
              ></v-img>
            </v-col>
          </v-row>
        </v-container>
      </v-tab-item>
    </v-tabs>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      tab: null,
    };
  },
};
</script>

The right prop makes the tab links align to the right.

Tab and Toolbar

We can put v-tabs inside the extension slow of the v-toolbar .

This will make it show at the bottom of the toolbar.

To do that, we write:

<template>
  <v-card>
    <v-toolbar color="cyan" dark flat>
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
      <v-toolbar-title>App</v-toolbar-title>
      <v-spacer></v-spacer>
      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
      <template v-slot:extension>
        <v-tabs v-model="tab" centered slider-color="yellow">
          <v-tab v-for="i in 3" :key="i" :href="`#tab-${i}`">Item {{ i }}</v-tab>
        </v-tabs>
      </template>
    </v-toolbar>

    <v-tabs-items v-model="tab">
      <v-tab-item v-for="i in 3" :key="i" :value="`tab-${i}`">
        <v-card flat>
          <v-card-text v-text="'hello world'"></v-card-text>
        </v-card>
      </v-tab-item>
    </v-tabs-items>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      tab: null,
    };
  },
};
</script>

The extension slot lets us place the tab links inside the toolbar.

Conclusion

We can add tabs with icons and in different positions.

Categories
Vuetify

Vuetify — Desktop Tabs

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Desktop Tabs

Tab actions can be represented with single icons.

For example, we can write:

<template>
  <v-card>
    <v-toolbar flat>
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
      <v-toolbar-title>App</v-toolbar-title>
      <v-spacer></v-spacer>
      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
      <template v-slot:extension>
        <v-tabs v-model="tabs" fixed-tabs>
          <v-tabs-slider></v-tabs-slider>
          <v-tab href="#mobile-tabs-5-1" class="primary--text">
            <v-icon>mdi-phone</v-icon>
          </v-tab>
          <v-tab href="#mobile-tabs-5-2" class="primary--text">
            <v-icon>mdi-heart</v-icon>
          </v-tab>
          <v-tab href="#mobile-tabs-5-3" class="primary--text">
            <v-icon>mdi-account-box</v-icon>
          </v-tab>
        </v-tabs>
      </template>
    </v-toolbar>

    <v-tabs-items v-model="tabs">
      <v-tab-item v-for="i in 3" :key="i" :value="`mobile-tabs-5-${i}`">
        <v-card flat>
          <v-card-text v-text="text"></v-card-text>
        </v-card>
      </v-tab-item>
    </v-tabs-items>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    tabs: null,
    text: "Lorem ipsum dolor sit amet.",
  }),
};
</script>

We add the v-icon without the text within the v-tab component to add tabs with only icons.

Tabs With Menu

We can add a menu to hold additional tabs.

When we click them, we’ll see the active one moved to the tab bar from the menu.

This can be done with our own logic.

To do that, we write:

<template>
  <v-card>
    <v-toolbar color="deep-purple accent-4" dark flat>
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
      <v-toolbar-title>App</v-toolbar-title>
      <v-spacer></v-spacer>
      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>

      <template v-slot:extension>
        <v-tabs v-model="currentItem" fixed-tabs slider-color="white">
          <v-tab v-for="item in items" :key="item" :href="`#tab-${item}`">{{ item }}</v-tab>

          <v-menu v-if="more.length" bottom left>
            <template v-slot:activator="{ on, attrs }">
              <v-btn text class="align-self-center mr-4" v-bind="attrs" v-on="on">
                more
                <v-icon right>mdi-menu-down</v-icon>
              </v-btn>
            </template>

            <v-list class="grey lighten-3">
              <v-list-item v-for="item in more" :key="item" @click="addItem(item)">{{ item }}</v-list-item>
            </v-list>
          </v-menu>
        </v-tabs>
      </template>
    </v-toolbar>

    <v-tabs-items v-model="currentItem">
      <v-tab-item v-for="item in items.concat(more)" :key="item" :value="`tab-${item}`">
        <v-card flat>
          <v-card-text>
            <h2>{{ item }}</h2>
            {{ text }}
          </v-card-text>
        </v-card>
      </v-tab-item>
    </v-tabs-items>
  </v-card>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    currentItem: "tab-Web",
    items: ["Web", "Offers", "Videos", "Hames"],
    more: ["News", "Maps", "Books", "Flights", "Play"],
    text:
      "Lorem ipsum dolor sit amet.",
  }),

  methods: {
    addItem(item) {
      const removed = this.items.splice(0, 1);
      this.items.push(...this.more.splice(this.more.indexOf(item), 1));
      this.more.push(...removed);
      this.$nextTick(() => {
        this.currentItem = `tab-${item}`;
      });
    },
  },
};
</script>

In the extension slot, we have the v-tab component with the tabs displayed on the tab bar.

And the v-menu has the additional tab buttons.

When we click on the ones on the menu, the addItem method to remove the entry from the menu and put that on the tab bar by adding it to the items array.

The menu is created with the v-btn component by passing it in the on with the v-on attribute and v-bind has the attributes for the styling the menu button.

v-on has the listeners to make the menu open and close.

Conclusion

We can make tab buttons display in a menu and move it to the tab bar when clicked.