Modern WebApps - Style: Vuetify
Tags: javascript, webdev, tutorial, vuetify
Published: 2019-05-08 19:45:35


In [(PWA Infrastructure: Vue, Parcel & Workbox)](https://dev.to/sarmis/single-page-progressive-web-applications-with-vue-js-2op8) we build a template for single-page, progressive web applications using [Vue.js](https://vuejs.org) and [Workbox](https://developers.google.com/web/tools/workbox/). The result was funtional, but not good-looking, in this article we will work on that.
<!--more-->

There are many options for making a webapp good-looking, from hand-writting your css, using a css framework, or since we already use Vue.js, using a vue components library, which has the added benefit of adding functionality. There are various vue component libraries, one of the most promising is [Vuetify.js](https://vuetifyjs.com) which implements google's material design and, thus, looks almost native in android phones.

## Resources

The code for this tutorial can be found in [project's github repo](https://github.com/sarmis/greekdev-template-vue-spa) in the **vuetify branch** 

## Integrating vuetify

Integrating vuetify is actually very simple.

1. Install vuetify and material design icons by running the following commands:

```
\>npm i -s vuetify
\>npm i -s material-design-icons-iconfont
```

1. Import the scripts and add them to Vue by adding the following in `src\web\index.js` (just after `import Vue from 'vue'`)           
```
import Vuetify from 'vuetify';
import 'vuetify/dist/vuetify.min.css' // Ensure you are using css-loader
import 'material-design-icons-iconfont'
Vue.use(Vuetify);
```


## Using vuetify

There is a lot of documentation and examples in [Vuetify.js site](https://vuetifyjs.com) but let's build a very simple web app layout.

We will only touch the `.vue` files

In `src\web\app.vue` we will add a permanent toolbat at the top and a navigation drawer at the left side of the page. We will configure the toolbar to be always visible, and the navigation drawer open by default in pages wider that 640 pixels.

``` html
<template lang="pug">
    v-app
        v-toolbar(app)
            v-toolbar-side-icon(@click="drawer=!drawer")
            v-toolbar-title Home
            v-spacer
            v-toolbar-items
                v-btn(flat to="/") home
                v-btn(flat to="/profile") profile
                v-btn(flat to="/about") about    
        
        v-navigation-drawer(v-model="drawer" app fixed mobile-break-point=640)
            v-list()               
                v-list-tile( to="/profile")
                    v-list-tile-action
                        v-icon account_circle
                    v-list-tile-title Profile
              
                v-divider
                
                v-list-tile(to="/" exact)
                    v-list-tile-action
                        v-icon home
                    v-list-tile-title Home

                v-list-tile(to="/about" exact)
                    v-list-tile-action
                        v-icon notes
                    v-list-tile-title about 
                
        v-content           
            router-view
            
</template>


<script>
    import Vue from "vue";
    import {router} from './_router.js';
    import {store} from './_store.js'
   
    export default Vue.extend({ 
        data: () => ( { 
            drawer: null 
        } ),

        store: store,
        router: router    
    });    
</script>
```

In `src\web\vues\profile.vue` we add a (dummy) login form using a `v-card` component

``` html
<template lang="pug">
    v-container(fluid fill-height)
        v-layout(justify-center)
            v-flex(xs12 sm8 md4)
            
                v-card(class="elevation-12")
                
                    v-toolbar( dark color="primary")
                        v-toolbar-title Login

                    v-card-text
                        v-form
                            v-text-field(prepend-icon="person" name="login" label="Username" type="text")
                            v-text-field(id="password" prepend-icon="lock" name="password" label="Password" type="password")

                    v-card-actions
                        v-spacer
                        v-btn(color="primary") Login

</template>

<script>
    export default {
        
    }
</script>

```

We make some minor alterations in 

`src\web\vues\home.vue`

``` html
<template lang="pug">
    v-container(fluid) 
        h1 Home
        p Welcome: {{$store.state.name}}
       
</template>


<script>
    export default {
    }
</script>
```

Finally we modify `src\web\vues\about.vue` 

``` html
<template lang="pug">
    v-container(fluid fill-height)
        v-layout(justify-center)
            v-flex(xs12 sm8 md4)
            
                v-card(class="elevation-12")
                
                    v-toolbar( dark color="primary")
                        v-toolbar-title About

                    v-card-text
                        p Let's Vuetify the template!                       

                    v-card-actions
                        v-spacer                        

</template>

<script>
    export default {
        
    }
</script>
```

## Pug ?

We opted to use `pug` instead of `html` as our markup language, it's a personal preference mainly due to being more compact ( a well structured page in pug should have about half the lines versus the html version - due to not having closing tags).


## The result

Time to see the end-result, in desktop browser:

![](./result-desktop.png)

and in mobile (with the navigation drawer closed, and with navigation drawer open):

![](./result-mobile.png)


## Next steps
In the next post we will add some real functionality in our web app.

######[Original post at greek developer](https://greekdeveloper.com/2019/vuetify-template/)