Friday, January 24, 2025

Vuetify: Building UI Apps with Material Design

Vuetify is a responsive framework in Vue that is based on Material Design. It already has a good range of components and solid documentation. This article will provide a complete tutorial for creating a small application to read data from an account in GitHub.

Creating the Application

We basically need Node, version 8 or higher, and a text editor such as Visual Studio Code. With all this ready, we can create the Vuetify project choosing the most diverse templates available.

Let’s use the Webpack template, creating the project through the following command:

npx vue-cli init vuetifyjs/webpack vuetifyproject

Answer the questions and wait for all dependencies to be installed. After that, go to the project directory and execute "code ." to open the Visual Studio Code, and npm run dev to run the project in developer mode. The browser will open with the project design.

Directory Structure

Whenever I’m studying a new framework, I like to thoroughly analyze the structure of directories it works on. With this, I have the necessary base to expand my system by creating the components in the right place, as well as knowing their limitations. Knowing the framework well, before using it in a real project, is fundamental to the success of your project.

At the first level of the project directory, we have:

  • build: Contains the files responsible for the project build process. All .js, .vue, .css files are “compiled” into a very small set of files, are minified and impossible to read for a human being.
  • config: It is in the config directory that we create some project settings, such as the back-end API access URL. This article explains how the process works.
  • node_modules: When we run npm install, all project libraries are downloaded from the internet to this directory. Do not change anything in this directory, whenever you want to download a new version of some library, change the package.json file and run npm install again.
  • src: The src directory contains all the project code. It will be detailed later in this article.
  • static: This directory contains images and files that will not be “compiled” in the project, but will be present in the final output. Any file added here will be literally copied to the final project.

In addition to these directories, we have important files at the root of the project:

  • index.html: Contains a div with the id app. This is where everything starts in the application, where Vue will be instantiated.
  • package.json: Contains various information about the project, such as defining the commands that the node can execute, the npm packages to be installed, and more.
  • .esointrc.js: Contains information about how ESLint should behave in the project.

Now let’s take a look at the src directory, which is where we store all the project files.

  • assets: Contains files that will be transpiled to JavaScript and injected into the project. You can add here a logo or small images of the project. Do not add photos or very large images as everything will become JavaScript! For large images, such as photos, use the static directory.
  • components: Initially we add the Vue components in this directory, which does not have to be a default. In very large projects we can divide the components into several levels. In this project, we will continue to use the simple structure, so any project .vue component will be added in this directory.
  • router: This directory has only the index.js file that contains the routes of each component of the project, since Vuetify uses the Vue Router.

And the files:

  • App.vue: This is the main component of the application, which “draws” all the features we have seen in the execution of the project. The floating menus, the header, footer, and body of the application. We will give special attention to this file soon.
  • main.js: This file imports and creates the Vue instance, associating it with that div id='app'. The router is also started, where the other Vue files will be instantiated. Possibly you will change this file at some point in the project by adding more libraries.

VApp

This is the component that comprises the entire Vuetify application. This component is practically mandatory in a Vuetify application, and through it you can create several types of designs. Let’s take a few more steps from VApp. A basic application can contain the following code:

<v-app>
  <v-navigation-drawer app></v-navigation-drawer>
  <v-toolbar app></v-toolbar>
  <v-content>
    <v-container fluid>
      <router-view></router-view>
    </v-container>
  </v-content>
  <v-footer app></v-footer>
</v-app>

VNavigationDrawer

It is a component capable of drawing a menu, where this menu is integrated to the Vue Router. In the application, we have the Navigation Drawer defined as follows:

<v-navigation-drawer
      persistent
      :mini-variant="miniVariant"
      :clipped="clipped"
      v-model="drawer"
      enable-resize-watcher
      fixed
      app
    >

Persistent Property

The persistent property defines how it behaves when the page loads. If it is persistent, the component will be displayed as soon as the page loads (unless it is a mobile device). If you don’t want this behavior, leaving the component invisible on page load, change from persistent to temporary.

Property MiniVariant

This property “condenses” the menu so that it stays only with the icons. For example:

mini-variant: true
mini-variant: false

In the case of the application, we have the use of :mini-variant with a colon at the beginning to indicate that the property is observing a variable in the this.data.miniVariant of the Vue. This property is toggled through a button in the toolbar menu.

Clipped Property

Determines whether the Drawer Panel  (let’s call it a menu) is on the toolbar or under it.

Again a bind :clipped="clipped" is used for the value to be observed through this.data.clipped.

V-model Property

The v-model property of the Navigation Drawer indicates whether or not it is present in the application. You can use this property to, for example, display the menu only through a context, such as the logged-in user.

Fixed PROPERTY

This property determines whether the position of the element (in this case the Navigation Drawer) is fixed.

App Property

This property determines that the Navigation Drawer is owned by the v-app. Without it, the menu does not belong to the application as a whole. This is because we can create a Navigation Drawer that belongs to some internal menu and that is of any screen, and not of the app.

Other Important Properties

  • dark: Uses the “dark” theme, which can be combined with the dark of other components.
  • height: The height of the component, whose default is ‘100%’
  • light: Another variation of theme
  • mobile-break-point: Informs the width in pixels of the definition of what is mobile or not. The default value is 1264, if the width of the app is less than that, the component behaves like a mobile.
  • permanent: The component is permanently visible on the screen.
  • right: Position the component on the right side of the screen
  • stateless: Removes all automatic component control against screen interactions, width, and change of route. All control would be manual.
  • touchless: Disables touch events on the mobile device, such as dragging it to the far side, causing the component to appear on the screen.
  • Value: Controls component visibility.

Configuring the Menu

The Navigation Drawer internal menu can be configured in different ways. In this specific case, we have:

<v-navigation-drawer>
  <v-list>
    <v-list-tile
      value="true"
      v-for="(item, i) in items"
      :key="i">
      <v-list-tile-action>
        <v-icon v-html="item.icon"></v-icon>
      </v-list-tile-action>
      <v-list-tile-content>
        <v-list-tile-title v-text="item.title"></v-list-tile-title>
      </v-list-tile-content>
    </v-list-tile>
  </v-list>
</v-navigation-drawer>

We then have a VList in conjunction with a VListTile, and in this we have the v-for iterating in a list called items. This list is created in this.data, see:

<script>
export default {
  data() {
    return {
      clipped: false,
      drawer: true,
      fixed: false,
      items: [{
        icon: 'bubble_chart',
        title: 'HtmlGoodies'
      }],
      miniVariant: false,
      right: true,
      rightDrawer: false,
      title: 'Vuetify.js'
    }
  },
  name: 'App'
}
</script>

At first, we only have one item, called “HtmlGoodies.” In the component, after using v-for, we have a v-list-tile-action and a v-list-tile-content both using the items list data.

Creating Integration with the Vue Router

So far we have only one item in VueRouter, defined in the file src/router/index.js:

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
})

And we need to add a link to this route in the right menu. First, we must change the v-list-tile of the Navigation Drawer by adding the to property, as follows:

<v-list-tile
          value="true"
          v-for="(item, i) in items"
          :key="i"
          :to="item.to"
        >

The to, native property of v-list-tile integrates with the Vue Router and the <router-link>, thus providing access to Vue routing. Finally, change the list of items to:

...
items: [{
  icon: 'bubble_chart',
  title: 'Hello World',
  to: '/'
}],
... 

Note that we add the to property in the item, which works in conjunction with the <v-list-tile>. Now if we add another item, for example:

items: [{
        icon: 'bubble_chart',
        title: 'Hello World',
        to: '/'
      },
      {
        icon: 'vpn_key',
        title: 'Login',
        to: '/login'
      } ], 

Of course, clicking this item will not load any pages, because the component has not yet been created.

Conclusion

As we saw, Vuetify is a powerful framework for building smart, yet responsive and fast, SPA and web applications. It allows the developer to focus on other needs and issues, rather than spending loads of time adjusting layouts, CSS and components. It’s easy and embraces all the Vue.js and Material Design power together. So, go ahead, take it for a test drive!

About the Author

Diogo Souza works as a Java Developer at PagSeguro and has worked for companies such as Indra Company, Atlantic Institute and Ebix LA. He is also an Android trainer, speaker at events on Java and mobile world.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Popular Articles

Featured