Create a dashboard with TailwindCSS - Part 1
By Dawntraoz Last updated on Sunday, 3 May 2020
Defining the project
The theme I have chosen to develop my own dashboard is about our daily activity, health.
In this dashboard you will have two main objectives, how many minutes a day you want to be active and how many steps you want to take.
With these objectives in mind, I have defined three KPIs (Key Performance Indicators), a measurable value that demonstrates how effectively a person is achieving key health objectives. These are:
- Weight loss
- Minutes active
- Steps
Defining the style guide
In this section I will show you the colors, fonts and iconography I have chosen for this dashboard.
-
Color palette
Using the tool for picking colors of Material Design, I ended up getting these two wonderful colors:
-
Font family
Source Sans Pro by Paul D. Hunt
-
Font weight, sizes and line height
For this I will use the ones that tailwind uses, so as not to reinvent the wheel.
-
Iconography
Designed by Elias Bikbulatov from Flaticon
Set up NuxtJS with TailwindCSS
Let's see the steps below:
1. Create NuxtJS app
Now that we have an approach to what we want, let's get down to business. Let's start with the installation of NuxtJS with TailwindCSS.
If it's your first project let's make sure you have node and npm installed, and in this case npx.
node -v
npm -v
npx -v
If not you will have to download node at https://nodejs.org/
Once you're ready, let's create our app!
npx create-nuxt-app <dashboard-name>
Now you will have to answer every question to customize your installation. I'll give you my example:
-
Project name: Cabbage
-
Project description: Cabbage is a dashboard to measure the progress of your health goals.
-
Author name: dawntraoz
-
Programming language: JavaScript
-
Package manager: npm
-
UI Framework (the main goal!): Tailwind CSS
-
Custom server framework: Express
-
Nuxt.js modules: Axios, PWA
-
Linting tools: ESLint, Prettier
-
Rendering mode: Universal (SSR)
I have chosen the options that interested me. If you want to see the possibilities that NuxtJS has, I recommend you to look at their installation guide.
Now we can see the options to run our application, run dev one to check everything is working properly:
# dev server at localhost:3000:
cd cabbage
npm run dev
# prod:
cd cabbage
npm run build
npm run start
# generate static project
npm run generate
If we already have a logo, we could replace the favicon, the Logo component and the icon.png, necessary for our PWA, by our own.
2. Configurate TailwindCSS
Well, with our environment already in place we’re going to configure TailwindCSS to be able to use it as we like.
The first thing I do is go to their default configuration file and copy the whole document to my file tailwind.config.js.
This doesn't add anything, it just allows us to see what we are calling to and the value it gives us, so we don't have to constantly look at the guide.
We are going to define now the specific variables of our project through the option of the theme: extend. As I explained in my post From Sketch to TailwindCSS
extend: {
colors: {
primary: {
50: '#e0f3ed',
100: '#b3e1d1',
200: '#81ceb5',
300: '#4fba98',
400: '#27ab83',
500: '#009c71',
600: '#008e65',
700: '#007e56',
800: '#006e49',
900: '#00522f'
},
complementary: {
50: '#fce5ea',
100: '#f9bdcb',
200: '#f592a9',
300: '#f06988',
400: '#ea4c6f',
500: '#e63658',
600: '#d53156',
700: '#c02c52',
800: '#ab274f',
900: '#861f48'
}
},
fontFamily: {
sans: ['Source Sans Pro', 'sans-serif']
}
}
In the case of color variables, they are new variables that we can use at the same time as those provided by tailwindcss. However, the font family is being replaced by 'Source Sans Pro', which is the font we will use in our project.
For the font to be applied we need to import it from Google Fonts, adding the code below to our tailwind.css file.
@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300i,400,400i,600,600i,700,700i&display=swap');
Once we have configured it to our needs, let's start removing the css and html added as an example by Nuxt in default.vue, index.vue, logo.vue and import our common style on tailwind.css file:
@import 'tailwindcss/screens'; /* Add Screens to work with the breakpoints easily */
@import './common-styles.css';
Create a file call common-styles.css and add your custom base styles:
/* Common Styles */
body {
@apply font-normal text-base;
}
/* - Headings */
h1,
h2,
h3,
h4,
h5,
h6 { @apply font-semibold; }
h1 {
@apply text-4xl;
}
h2 {
@apply text-3xl;
}
h3 {
@apply text-2xl;
}
h4 {
@apply text-xl;
}
h5 {
@apply text-lg;
}
h6 {
@apply text-base;
}
The important thing here is to have clear ideas and try to structure our code so that we can extend it little by little as we need to.
Start building the layout
In this project we have a sidebar where we'll add the menu and a panel on the right where we could see all the information.
To do this, we create a folder called partials in layouts and create a new component called Sidebar.vue. In it, we'll add our logo and the nuxt links to the pages we've created, for now index.vue, then we'll add styleguide.vue page.
Let’s see the code:
In the template of our component we’ll add our logo and the navigation with the list of internal links. Also, we’ll style it with the tailwind classes:
- bg-* background colors.
- p-*, py-*, px-* padding on all sides, vertical and horizontal, respectively.
- md:* indicates that we are using a media query min-width: 768px
- w-* the width of the element
<template>
<div class="bg-white py-4 px-3 md:py-6 md:px-8">
<logo class="w-10 h-10 md:w-12 md:h-12" />
<nav>
<ul class="py-4">
<li class="py-2">
<nuxt-link to="/" class="nav-link">
<!-- icon svg -->
</nuxt-link>
</li>
<li class="py-2">
<nuxt-link to="/styleguide" class="nav-link">
<!-- icon svg -->
</nuxt-link>
</li>
</ul>
</nav>
</div>
</template>
In this component we only need to import the svgs we use, I add them as vue components to be able, later, to play with them and put effects.
<script>
import Logo from '~/components/Logo.vue'
// Import icons
export default {
components: {
Logo,
// Icons
}
}
</script>
For the links I have created a class named .nav-link that adds the tailwind styles so that it can be easily reused. As you can see, to be able to add the classes that started with md:*, the media queries, I have used @screen md, which we have imported into tailwind.css before.
Links style is as a button, to make a clickable effect I have used shadow-*, the box-shadow property, and transitions. To center the icons I have used flex, my dear and faithful friend.
<style scoped>
.nav-link {
@apply transition-all duration-1000 ease-in-out block w-10 h-10 bg-white text-primary-400 rounded-full flex items-center justify-center shadow-inner;
@screen md {
@apply w-12 h-12;
}
}
.nav-link:hover,
.nuxt-link-exact-active {
@apply bg-primary-400 text-white shadow-lg;
}
</style>
Now that we have the sidebar, we have to add it in the default.vue layout and, by the way, we're going to tell it to take up all the height of the screen at least:
<template>
<div class="flex min-h-screen bg-primary-50">
<sidebar />
<nuxt class="flex-auto h-screen overflow-y-auto p-6" />
</div>
</template>
<script>
import Sidebar from '~/layouts/partials/Sidebar.vue'
export default {
components: {
Sidebar
}
}
</script>
To give a subtle transition between pages, we are going to add an animation with the classes that nuxtJS provides:
<style scoped>
.page-enter-active {
animation: acrossIn 0.4s ease-out both;
}
.page-leave-active {
animation: acrossOut 0.6s ease-in both;
}
@keyframes acrossIn {
0% {
transform: translate3d(-0.35%, 0, 0);
opacity: 0;
}
100% {
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes acrossOut {
0% {
transform: translate3d(0%, 0, 0);
opacity: 1;
}
100% {
transform: translate3d(20%, 0, 0);
opacity: 0;
}
}
</style>
This is the result:
In the next posts I will be adding new components and explaining the process, I hope it will be very helpful for you and motivate you to use TailwindCSS, it makes our life easier 🥰
I leave the repository here in case you want to take a look and not have to read the post without trying it yourself.