In (PWA Infrastructure: Vue, Parcel & Workbox) we build a template for single-page, progressive web applications using Vue.js and Workbox. The result was funtional, but not good-looking, in this article we will work on that.
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 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 in the vuetify branch
Integrating vuetify
Integrating vuetify is actually very simple.
- Install vuetify and material design icons by running the following commands:
\>npm i -s vuetify
\>npm i -s material-design-icons-iconfont
- Import the scripts and add them to Vue by adding the following in
src\web\index.js
(just afterimport 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 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.
<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
<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
<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
<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:
and in mobile (with the navigation drawer closed, and with navigation drawer open):
Next steps
In the next post we will add some real functionality in our web app.
Top comments (2)
Yes, i was wondering why pug...
Let me explain my selection a bit more