Categories
Vuetify

Vuetify — Slide Group and Window

Vuetify is a popular UI framework for Vue apps.

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

Slide Group Centered Active Item

We can center the selected item on the slid group with the center-active prop:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-sheet class="mx-auto" elevation="8" max-width="800">
          <v-slide-group v-model="model" class="pa-4" center-active show-arrows>
            <v-slide-item v-for="n in 15" :key="n" v-slot:default="{ active, toggle }">
              <v-card
                :color="active ? 'primary' : 'grey lighten-1'"
                class="ma-4"
                height="200"
                width="100"
                @click="toggle"
              >
                <v-row class="fill-height" align="center" justify="center">
                  <v-scale-transition>
                    <v-icon
                      v-if="active"
                      color="white"
                      size="48"
                      v-text="'mdi-close-circle-outline'"
                    ></v-icon>
                  </v-scale-transition>
                </v-row>
              </v-card>
            </v-slide-item>
          </v-slide-group>
        </v-sheet>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    model: undefined,
  }),
};
</script>

Now when we click on an item, it’ll always be centered.

Windows

The v-window component lets us transition content from one pane to another.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-card flat tile>
          <v-window v-model="onboarding" vertical>
            <v-window-item v-for="n in length" :key="`card-${n}`">
              <v-card color="grey" height="200">
                <v-row class="fill-height" align="center" justify="center" tag="v-card-text">
                  <h1 style="font-size: 5rem;" class="white--text">Slide {{ n }}</h1>
                </v-row>
              </v-card>
            </v-window-item>
          </v-window>

          <v-card-actions class="justify-space-between">
            <v-btn text @click="prev">
              <v-icon>mdi-chevron-left</v-icon>
            </v-btn>
            <v-item-group v-model="onboarding" class="text-center" mandatory>
              <v-item v-for="n in length" :key="`btn-${n}`" v-slot:default="{ active, toggle }">
                <v-btn :input-value="active" icon @click="toggle">
                  <v-icon>mdi-record</v-icon>
                </v-btn>
              </v-item>
            </v-item-group>
            <v-btn text @click="next">
              <v-icon>mdi-chevron-right</v-icon>
            </v-btn>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    length: 6,
    onboarding: 0,
  }),

  methods: {
    next() {
      this.onboarding =
        this.onboarding + 1 === this.length ? 0 : this.onboarding + 1;
    },
    prev() {
      this.onboarding =
        this.onboarding - 1 < 0 ? this.length - 1 : this.onboarding - 1;
    },
  },
};
</script>

We have the v-window component with the v-model to get and set the index of the slide we’re on.

v-card is what we’re scrolling through.

The v-card-actions component has the navigation controls for moving between slides.

The vertical prop makes the slides display vertically.

The slides are moved with the next and prev methods by changing the onboarding value, which is bound to the v-model to change the slide.

Reverse

We can reverse the v-window component with the reverse component:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-card flat tile>
          <v-window v-model="onboarding" vertical reverse>
            <v-window-item v-for="n in length" :key="`card-${n}`">
              <v-card color="grey" height="200">
                <v-row class="fill-height" align="center" justify="center" tag="v-card-text">
                  <h1 style="font-size: 5rem;" class="white--text">Slide {{ n }}</h1>
                </v-row>
              </v-card>
            </v-window-item>
          </v-window>

          <v-card-actions class="justify-space-between">
            <v-btn text @click="prev">
              <v-icon>mdi-chevron-left</v-icon>
            </v-btn>
            <v-item-group v-model="onboarding" class="text-center" mandatory>
              <v-item v-for="n in length" :key="`btn-${n}`" v-slot:default="{ active, toggle }">
                <v-btn :input-value="active" icon @click="toggle">
                  <v-icon>mdi-record</v-icon>
                </v-btn>
              </v-item>
            </v-item-group>
            <v-btn text @click="next">
              <v-icon>mdi-chevron-right</v-icon>
            </v-btn>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    length: 6,
    onboarding: 0,
  }),

  methods: {
    next() {
      this.onboarding =
        this.onboarding + 1 === this.length ? 0 : this.onboarding + 1;
    },
    prev() {
      this.onboarding =
        this.onboarding - 1 < 0 ? this.length - 1 : this.onboarding - 1;
    },
  },
};
</script>

Now the slides move in reverse when we click on the navigation controls.

Categories
Vuetify

Vuetify — Images

Vuetify is a popular UI framework for Vue apps.

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

Images

We can add images with the v-img component.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-img src="https://picsum.photos/510/300?random" aspect-ratio="1.7"></v-img>
        <v-img src="https://picsum.photos/510/300?random" aspect-ratio="2"></v-img>
        <v-img src="https://picsum.photos/510/300?random" aspect-ratio="1.4"></v-img>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
  methods: {
    next() {
      alert("You clicked next");
    },
  },
};
</script>

to add images with the v-img component.

src has the URL of the image.

aspect-ratio has the aspect ratio of the image.

Height

We can change the height with the height and max-height props.

For example, we can write:

<template>
  <v-container class="fill-height" fluid style="min-height: 434px">
    <v-fade-transition mode="out-in">
      <v-row key="0">
        <v-col cols="6">
          <v-card>
            <v-img src="https://picsum.photos/350/165?random" height="125" class="grey darken-4"></v-img>
            <v-card-title class="title">height</v-card-title>
          </v-card>
        </v-col>

        <v-col cols="6">
          <v-card>
            <v-img
              src="https://picsum.photos/350/165?random"
              height="125"
              contain
              class="grey darken-4"
            ></v-img>
            <v-card-title class="title">height with contain</v-card-title>
          </v-card>
        </v-col>

        <v-col cols="6">
          <v-card>
            <v-img
              src="https://picsum.photos/350/165?random"
              max-height="125"
              class="grey darken-4"
            ></v-img>
            <v-card-title class="title">max-height</v-card-title>
          </v-card>
        </v-col>

        <v-col cols="6">
          <v-card>
            <v-img
              src="https://picsum.photos/350/165?random"
              max-height="125"
              contain
              class="grey darken-4"
            ></v-img>
            <v-card-title class="title">max-height with contain</v-card-title>
          </v-card>
        </v-col>
      </v-row>
    </v-fade-transition>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

contain prevents the image from being cropped if it doesn’t fit.

Fixed Ratio

We can set the aspect ratio if we want to change the aspect ratio of the image.

For example, we can write:

<template>
  <v-container fluid>
    <v-slider v-model="width" min="200" max="500" step="1"></v-slider>
    <v-navigation-drawer :width="width" :value="true" stateless>
      <v-img :aspect-ratio="16/9" src="https://cdn.vuetifyjs.com/images/parallax/material.jpg"></v-img>

      <v-list>
        <template v-for="(item, i) in items">
          <v-divider v-if="item.divider" :key="i"></v-divider>
          <v-list-item v-else :key="item.title">
            <v-list-item-action>
              <v-icon>{{ item.icon }}</v-icon>
            </v-list-item-action>
            <v-list-item-title>{{ item.title }}</v-list-item-title>
          </v-list-item>
        </template>
      </v-list>
    </v-navigation-drawer>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    width: 300,
    items: [
      { icon: "inbox", title: "Inbox" },
      { icon: "star", title: "Starred" },
    ],
  }),
};
</script>

We have width prop to change the width.

And we render the icons with the v-list component.

The aspect-ratio prop makes the aspect ratio of the image fixed.

Placeholder

We can add a placeholder slot to add a placeholder content inside.

For example, we can write:

<template>
  <v-container fluid>
    <v-row align="center" justify="center">
      <v-img
        src="https://bad.src/not/valid"
        lazy-src="https://picsum.photos/id/11/100/60"
        aspect-ratio="1"
        class="grey lighten-2"
        max-width="500"
        max-height="300"
      >
        <template v-slot:placeholder>
          <v-row class="fill-height ma-0" align="center" justify="center">
            <v-progress-circular indeterminate color="grey lighten-5"></v-progress-circular>
          </v-row>
        </template>
      </v-img>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

We have an src prop that is invalid, so the placeholder image will be shown.

lazy-src has the URL of the placeholder.

And we use the placeholder slot to put a circular progress display over the placeholder image.

Conclusion

We can display images with placeholders and more.

Categories
Vuetify

Vuetify — Image Gradients and Lists

Vuetify is a popular UI framework for Vue apps.

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

Gradients

We add the gradient prop can be used to apply a gradient overlay to the image.

For example, we can write:

<template>
  <v-container fluid>
    <v-row>
      <v-col cols="6" sm="4">
        <v-img
          src="https://cdn.vuetifyjs.com/images/parallax/material2.jpg"
          gradient="to top right, rgba(100,115,201,.33), rgba(25,32,72,.7)"
        ></v-img>
      </v-col>

      <v-col cols="6" sm="4">
        <v-img src="https://cdn.vuetifyjs.com/images/parallax/material2.jpg">
          <div class="fill-height bottom-gradient"></div>
        </v-img>
      </v-col>

      <v-col cols="6" sm="4">
        <v-img src="https://cdn.vuetifyjs.com/images/parallax/material2.jpg">
          <div class="fill-height repeating-gradient"></div>
        </v-img>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

to add an image with a div below it with the gradient.

Grid

We can put v-img components in a grid.

For example, we can write:

<template>
  <v-row>
    <v-col cols="12" sm="6" offset-sm="3">
      <v-card>
        <v-container fluid>
          <v-row>
            <v-col v-for="n in 9" :key="n" class="d-flex child-flex" cols="4">
              <v-card flat tile class="d-flex">
                <v-img
                  :src="`https://picsum.photos/500/300?image=${n * 5 + 10}`"
                  :lazy-src="`https://picsum.photos/10/6?image=${n * 5 + 10}`"
                  aspect-ratio="1"
                  class="grey lighten-2"
                >
                  <template v-slot:placeholder>
                    <v-row class="fill-height ma-0" align="center" justify="center">
                      <v-progress-circular indeterminate color="grey lighten-5"></v-progress-circular>
                    </v-row>
                  </template>
                </v-img>
              </v-card>
            </v-col>
          </v-row>
        </v-container>
      </v-card>
    </v-col>
  </v-row>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

We create v-row and v-col to contain the images.

v-img is in the v-card so that it’s placed properly.

The placeholder slot has the circular progress display to show when the image loads.

Lists

We can use the v-list component to add lists to our app.

For example, we can write:

<template>
  <v-row>
    <v-col cols="12">
      <v-card class="mx-auto" max-width="300" tile>
        <v-list disabled>
          <v-subheader>REPORTS</v-subheader>
          <v-list-item-group v-model="item" color="primary">
            <v-list-item v-for="(item, i) in items" :key="i">
              <v-list-item-icon>
                <v-icon v-text="item.icon"></v-icon>
              </v-list-item-icon>
              <v-list-item-content>
                <v-list-item-title v-text="item.text"></v-list-item-title>
              </v-list-item-content>
            </v-list-item>
          </v-list-item-group>
        </v-list>
      </v-card>
    </v-col>
  </v-row>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    item: 1,
    items: [
      { text: "Real-Time", icon: "mdi-clock" },
      { text: "Audience", icon: "mdi-account" },
      { text: "Conversions", icon: "mdi-flag" },
    ],
  }),
};
</script>

We have a list with the v-list component.

v-list-item display the items.

v-list-item-icon places the icon to the left of the text.

v-list-item-content adds the content.

v-list-item-title has the title text.

Conclusion

We can add gradients to images and lists with Vuetify.

Categories
Vuetify

Vuetify — Icons

Vuetify is a popular UI framework for Vue apps.

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

Material Design Icons

Vuetify comes with many icons.

We can install Material Design icons by running:

npm install material-design-icons-iconfont -D

Then in src/plugins/vuetify.js , we add:

import 'material-design-icons-iconfont/dist/material-design-icons.css'

And then we can add them with the v-icon component:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-container fluid>
          <v-row justify="space-around" class="mb-2">
            <span class="group pa-2">
              <v-icon>home</v-icon>
              <v-icon>event</v-icon>
              <v-icon>info</v-icon>
            </span>
          </v-row>
        </v-container>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

Font Awesome Icons

We can install Font Awesome icons by running:

npm install @fortawesome/fontawesome-free -D

Then in src/plugins/vuetify.js , we add:

import '@fortawesome/fontawesome-free/css/all.css'

so we can use the icons.

Then we can use it by writing:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-row align="center" justify="space-around">
          <v-icon>fas fa-lock</v-icon>
          <v-icon>fas fa-search</v-icon>
          <v-icon>fas fa-list</v-icon>
          <v-icon>fas fa-edit</v-icon>
          <v-icon>fas fa-tachometer-alt</v-icon>
          <v-icon>fas fa-circle-notch fa-spin</v-icon>
        </v-row>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

Button Icons

We can add icons to buttons.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <div>
          <v-btn class="ma-2" color="primary" dark>
            Accept
            <v-icon dark right>mdi-checkbox-marked-circle</v-icon>
          </v-btn>

          <v-btn class="ma-2" color="red" dark>
            Decline
            <v-icon dark right>mdi-cancel</v-icon>
          </v-btn>

          <v-btn class="ma-2" dark>
            <v-icon dark left>mdi-minus_circle</v-icon>Cancel
          </v-btn>
        </div>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

to add an icon beside the icon text.

Clickable

We can bind to any click event with v-icon .

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-card>
          <v-toolbar color="pink" dark dense flat>
            <v-toolbar-title class="body-2">Upcoming Changes</v-toolbar-title>
          </v-toolbar>
          <v-card-text>Lorem ipsum.</v-card-text>

          <v-card-actions>
            <v-spacer></v-spacer>
            <v-icon large @click="next">mdi-chevron-right</v-icon>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
  methods: {
    next() {
      alert("You clicked next");
    },
  },
};
</script>

We set the @click directive to next so that the next method will be called when we click on the icon.

Conclusion

We can add Material Design and Font Awesome icons to our app.

Also, Vuetify comes with built-in icons.

Categories
Vuetify

Vuetify — Hover

Vuetify is a popular UI framework for Vue apps.

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

Hover

The v-hover component lets us handle hover states for any component.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-hover v-slot:default="{ hover }">
          <v-card :elevation="hover ? 12 : 2" class="mx-auto" height="350" max-width="350">
            <v-card-text class="my-4 text-center title">Hover over me!</v-card-text>
          </v-card>
        </v-hover>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

to add the hover functionality with the v-hover component.

We can add the disabled prop to v-hover to disable hover effects.

Open/Close Delay

We can set a delay when opening or closing the hover effect with the open-delay and close-delay props.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-hover v-slot:default="{ hover }" open-delay="200">
          <v-card :elevation="hover ? 12 : 2" class="mx-auto" height="350" max-width="350">
            <v-card-text class="my-4 text-center title">Hover over me!</v-card-text>
          </v-card>
        </v-hover>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

to set a 200ms open delay.

Hover List

We can make a hover list with the v-hover component.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-container class="pa-4 text-center">
          <v-row class="fill-height" align="center" justify="center">
            <template v-for="(item, i) in items">
              <v-col :key="i" cols="12" md="4">
                <v-hover v-slot:default="{ hover }">
                  <v-card :elevation="hover ? 12 : 2" :class="{ 'on-hover': hover }">
                    <v-img :src="item.img" height="225px">
                      <v-card-title class="title white--text">
                        <v-row class="fill-height flex-column" justify="space-between">
                          <p class="mt-4 subheading text-left">{{ item.title }}</p>

<div>
                            <p
                              class="ma-0 body-1 font-weight-bold font-italic text-left"
                            >{{ item.text }}</p>
                            <p
                              class="caption font-weight-medium font-italic text-left"
                            >{{ item.subtext }}</p>
                          </div>
                        </v-row>
                      </v-card-title>
                    </v-img>
                  </v-card>
                </v-hover>
              </v-col>
            </template>
          </v-row>
        </v-container>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    items: [
      {
        title: "Title",
        text: "Text",
        subtext: "Subtext",
        img: "https://picsum.photos/200",
      },
      {
        title: "Title",
        text: "Text",
        subtext: "Subtext",
        img: "https://picsum.photos/200",
      },
      {
        title: "Title",
        text: "Text",
        subtext: "Subtext",
        img: "https://picsum.photos/200",
      },
    ],
    transparent: "rgba(255, 255, 255, 0)",
  }),
};
</script>

We have 3 slides each in their own v-card component.

They are inside a v-hover component so that we see a hover effect when our mouse is over the square.

Transitions

We can add our own transitions for v-hover .

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-hover v-slot:default="{ hover }">
          <v-card class="mx-auto" color="grey lighten-4" max-width="600">
            <v-img :aspect-ratio="16/9" src="[https://cdn.vuetifyjs.com/images/cards/kitchen.png](https://cdn.vuetifyjs.com/images/cards/kitchen.png)">
              <v-expand-transition>
                <div
                  v-if="hover"
                  class="d-flex transition-fast-in-fast-out orange darken-2 v-card--reveal display-3 white--text"
                  style="height: 100%;"
                >$100.99</div>
              </v-expand-transition>
            </v-img>
            <v-card-text class="pt-6" style="position: relative;">
              <v-btn absolute color="orange" class="white--text" fab large right top>
                <v-icon>mdi-cart</v-icon>
              </v-btn>
              <div class="font-weight-light grey--text title mb-2">Perfect meal</div>
            </v-card-text>
          </v-card>
        </v-hover>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

<style>
.v-card--reveal {
  align-items: center;
  bottom: 0;
  justify-content: center;
  opacity: 0.5;
  position: absolute;
  width: 100%;
}
</style>

to add a v-expand-transition to create our hover effect.

We display the price when we hover over the image.

The styles make the overlay text centered and translucent.

Conclusion

We can add hover effect with the v-hover component.

The transition is built-in but we can also customize to what we want.