Before you can master design, you must first master the fundamentals

Last week, one of my readers sent in a question:&nbsp;<strong>How do I become a better visual designer?</strong>

Last week, one of my readers sent in a question: How do I become a better visual designer?


As I was thinking about how to answer this question, my mind wandered to my experience with learning Mandarin Chinese. Recently, I decided to teach myself Mandarin. When it comes to learning a new language, you first have to start with the fundamentals. Nouns, pronouns, and verbs form the basis for conveying more complex ideas.

Language is a way that people communicate concepts to one another. Visual design is a visual language. And learning visual design is no different from learning a new language.

Good visual designs aren’t born. They are made. The key to becoming a better visual designer is rigor. You will only improve as a visual designer if you make a conscious effort.

Here are some fundamentals you should master so you can take your visual design to the next level.

Fundamental #1: Go back to the basics with type

You can tell a lot about a designer by looking at their typography. This is because type is a fundamental basis for design.



You can create entire designs with just type. You can also base designs on type, taking subtle queues from the fonts that you choose. In order to improve the typography in your designs, first start by learning the basics.

Develop a vocabulary for describing type. Learn about what terms like tracking, kerning, and leading mean. The article A Beautifully Illustrated Glossary Of Typographic Terms You Should Know is a great visual resource for learning those terms.

Then, if you want a comprehensive understanding of how to apply typography to the web, read Web Typography: The Elements of Typographic Style Applied to the Web.

Finally, learn how to pair fonts together. A great resource for this is FontWolfand FontPair. Being able to pair fonts together will dramatically change the dynamics of your design.

For a more in depth exploration of typography, you can read my article: Typography can make your design… Or break it.

Fundamental #2: Use space to create balance

Spacing helps establish vertical and horizontal motion in your designs. It’s pivotal for creating visual hierarchy and forming association between elements.

You can always look at sites like Behance and Dribbble for inspiration on how to space elements. But it’s important to develop your own intuition for using space to create balance and visual harmony.

When studying typography, you may have noticed the importance of spacing in type. Adjusting the kerning and leading for fonts is a great exercise for developing your eye for spacing. For this reason, I recommend you try KernType, a game where you compare your kerning solution to a typographer’s solution.

Another exercise that will help develop your eye is the following: Take an existing design, draw an x and y axis, simplify the design into basic shapes, analyze how the design is balanced, and then rearrange the elements. Pay close attention to how negative space affects the balance of the elements.

Fundamental #3: Use size to establish visual hierarchy

When it comes to creating visual hierarchy, sizing is second to none. By using size to convey visual relationships between elements, you can establish flow.

Sizing is one of the reasons why grids are useful. You can use grids to help you size elements using ratios to convey importance.

Once you have determined a size for an element, keep it the same across all instances of it. In design, consistency is king.

Here’s an exercise that will help develop your eye for sizing.

The key is asking for feedback.


Sketch or wireframe a landing page. Then ask a friend to look at your design. Get them to circle the elements that stand out the most. Afterwards, have them number the circled elements based on visual weight. Are the results what you expected?

When doing this exercise, keep the following questions in mind:

  • What is the conversion goal of the landing page? How can you optimize to meet your goal?
  • What is the relationship between different elements? What elements do you want to emphasize?
  • Does your layout successfully guide a user’s eye through the page?

Fundamental #4: Use color to convey meaning

Color plays many roles. It conveys meaning, creates emotional resonance, and brings unity to designs.

For a deep dive into color, you can read my article Designing in Color. Here are a few key points from the article.

  • Identify the purpose of your design before choosing a color palette. Good design align its color palette with its purpose.
  • Identify your audience. People perceive colors differently. Colors have different effects on people based on their personal preference, cultural upbringing, and experiences.
  • When choosing a color palette, simplicity is key. Choose a neutral background color. Then choose a primary and secondary accent color. Finally based on your other colors, choose an error and success color for your different UI states.

Once you have a good grasp on the basics of color theory, color comes down to experimentation and iteration. Actively try break out of your comfort zone and try new color palettes.


Here’s an exercise that will help develop your eye for color.

Spend time compiling color palettes for things around you like photographs, magazines, and your favorite shows. Then take an existing design and apply new color palettes to it.


Take note of how it changes the mood and tone of the design. Does it change the meaning as well?

Treat your work as a craft, in that there is always something that you can improve. Rely on yourself to be the motivation to become a better designer.

What are you strategies for improving as a designer? Leave me a note or send me a tweet on Twitter.

If you enjoyed this article, you might also enjoy CSS in Javascript with Aphrodite, a library by Khan Academy.

CSS in Javascript: The future of component based styling


This week, I want to introduce you to the concept of CSS in Javascript with Aphrodite by Khan Academy. Aphrodite lets…

medium.com


By : Jonathan Z. White










Build a Stopwatch app with SwiftUI

Build a Stopwatch app with SwiftUI

In this article I will show you how to build a stopwatch app using SwiftUI. In this post I will show you how to create custom views using SwiftUI as well as some basic layout and using “ObjectBinding”.

I know we are building a stopwatch app, but I am not going to go through the actual StopWatch code logic as I feel that is out of scope for this tutorial. This tutorial is more about building the apps UI with SwiftUI.

In the above picture you can see what the app will look like when we are done. It is nothing special, but it is functional.

When the app is complete, you will be able to start the stop watch, record laps times(this will only be in memory), pause the stop watch and reset it.

So now that we know what it needs to look like and what the functionality is, we can start building it.

Step 1: Add the StopWatch class to your project

I created this class for this tutorial only. I would not classify it as production ready as it has not been tested properly, the code is also not too great. It is for demonstration purposes only.

You can find the StopWatch class here. Or you can download the gist here.

Step 2: Add the timer Text()

In your main ContentView inside the body variable we need to add a VStack. Your code should look like this:

struct ContentView : View {
    @ObjectBinding var stopWatch = StopWatch()
    
    var body: some View {
        VStack {
            // Code here
        }
    }
}

That VStack will hold all of our UI. Now that we have our VStack we can add in our Text view to display the timer text.

With SwiftUI the parent view cannot force a size on the child/children view, so we will need to do most of the styling on the Text view that we add. Add the following code inside the VStack that we added in just now.

Text(self.stopWatch.stopWatchTime)
    .font(.custom("courier", size: 70))
    .frame(width: UIScreen.main.bounds.size.width,
           height: 300,
           alignment: .center)

In the above code we are creating a new Text view. We set the default text to be 00:00:00 which will be updated later on with the proper value.

After that we start with the styling. I changed the font to courier, this works better as it is a monospace font, when I used the standard system font the text would shake because it was changing all the time. We also set the size to be 70 so that it is nice and big. The next thing we do is update the frame. We want the width to be the full width of the screen but we also want it to be quite tall, so we set the height to 300. Technically you can leave the .center alignment out as that is the default setting.

Your app should now look like this:

Not exactly what we want, but it is a start.

Step 3: Create the buttons view

Before we carry on with the layout, we need to create the buttons. This will be a new custom view. The buttons functionality as well as text will change depending on the state of the stopwatch.

For example, when the timer is stopped, we will have two buttons, one will be to reset the timer and the other will be to start the timer. If the timer is busy timing, those buttons will change to a lap button and a pause button.

Because the app is super small, I have put the logic in the button. If the app was bigger, I would strip out the logic from the button and use something else to create the button that I need based on the parameters I pass to it.

What do the buttons require?

Each button needs to take in two actions and two strings. They also need to have a color and they need to know if the timer is paused or not.

The code

To do this, create a new struct called StopWatchButton and have it conform to the View protocol as below:

struct StopWatchButton : View {
    var body: some View {
        // Buttons coming soon
    }
}

We can now add in the properties just above the body property.

Change your struct to look like this now:

struct StopWatchButton : View {
    var actions: [() -> Void]
    var labels: [String]
    var color: Color
    var isPaused: Bool    var body: some View {
        // Buttons coming soon
    }
}

Great, we can now add the button logic in the body.

The first thing that we need to add is a button width variable in the body. This value is quite random, but it works for our needs.

Your body property should now look like this:

var body: some View {
    let buttonWidth = (UIScreen.main.bounds.size.width / 2) - 12
}

This will give an error but don’t worry, we will sort that out now.

We will now create the button view. It is not too complicated. A basic Button in SwiftUI takes two arguments, one is the action and the other is the label view. In our action and label parameters we will check if the timer is paused and based on that we will know what function to call and what Text view we need to display.

Update your body variable to look like the below:

var body: some View {
    let buttonWidth = (UIScreen.main.bounds.size.width / 2) - 12
    
    return Button(action: {
            if self.isPaused {
                self.actions[0]()
            } else {
                self.actions[1]()
            }
        }) {
            if isPaused {
                Text(self.labels[0])
                    .color(Color.white)
                    .frame(width: buttonWidth,
                           height: 50)
            } else {
                Text(self.labels[1])
                    .color(Color.white)
                    .frame(width: buttonWidth,
                           height: 50)
            }
        }
        .background(self.color)
    }
}

In the above code you can see what we are doing. In the action section(the first closure) we check the isPaused property. If it is true then we use the first action in our actions array, otherwise we use the second action.

The same is true for the label. If isPaused is true, we will use the first string from our labels array, otherwise we use the second string.

Other than that, each Text view has the same styling, we could create our own custom text view for that, but this is pretty simple so I don't see much of a need for that right now. If we were going to use text views that were the same as these elsewhere then I would definitely create a custom text view.

One thing to note is how the Text view frame is being set and not the buttons frame. As I mentioned earlier, SwiftUI requires us to set the frame on the child view as the parent cannot tell the child what to do.

The last thing that we do is we set the background color for the button.

The final code for the StopWatchButton should look like this:

struct StopWatchButton : View {
    var actions: [() -> Void]
    var labels: [String]
    var color: Color
    var isPaused: Bool
    
    var body: some View {
        let buttonWidth = (UIScreen.main.bounds.size.width / 2) - 12
        
        return Button(action: {
            if self.isPaused {
                self.actions[0]()
            } else {
                self.actions[1]()
            }
        }) {
            if isPaused {
                Text(self.labels[0])
                    .color(Color.white)
                    .frame(width: buttonWidth,
                           height: 50)
            } else {
                Text(self.labels[1])
                    .color(Color.white)
                    .frame(width: buttonWidth,
                           height: 50)
            }
        }
        .background(self.color)
    }
}

Step 4: Adding the buttons

Ok, most of the complicated stuff is now out of our way and we can get back to laying out our UI.

The next thing that we need to do is to add the two instances of our new StopWatchButton. Before we do that we need to create an HStack that can wrap our buttons.

Update your ContentView struct to look like the below:

struct ContentView : View {
    @ObjectBinding var stopWatch = StopWatch()
    
    var body: some View {
        VStack {
            Text(self.stopWatch.stopWatchTime)
                .font(.custom("courier", size: 70))
                .frame(width: UIScreen.main.bounds.size.width,
                       height: 300,
                       alignment: .center)
            
            HStack{
                // Our buttons will go here
            }
        }
     }
 }

As you can see. Nothing much has changed except that we now have an HStack below our Text view that will display the current timers string value.

Inside that HStack you need to add the following code:

StopWatchButton(actions: [self.stopWatch.reset, self.stopWatch.lap],
                labels: ["Reset", "Lap"],
                color: Color.red,
                isPaused: self.stopWatch.isPaused())StopWatchButton(actions: [self.stopWatch.start, self.stopWatch.pause],
                labels: ["Start", "Pause"],
                color: Color.blue,
                isPaused: self.stopWatch.isPaused())

After adding that code, your app should look like this:

This might be a bit confusing. In the above code we are creating two new instances of our StopWatchButton.

As discussed earlier these buttons have four properties. The first property will be the functions that we want to call depending on the isPaused state. The first button that we create will be our Reset/Lap and our second button will be our Start/Pause button. In the image you cannot see the Lap button and the Pause button, but if you run the app and click on the Start button, you will be able to see the Lap and Pause button. Please note, if you run the app and you tap on the Lap button, nothing will happen visually. The code will be working correctly, but in the next step I will show you how to get the lap times to show up in the list.

Step 5: Displaying the lap times

This next part is pretty simple. All we have is a VStack that wraps around a Text view and a List view.

Below the HStack that we created in the previous step, add the following code:

VStack(alignment: .leading) {
    Text("Laps")
        .font(.title)
        .padding()List { 
        ForEach(self.stopWatch.laps.identified(by: \.uuid)) { (lapItem) in
            Text(lapItem.stringTime)
        }
    }
}

Now that you have added that, your app should look something like this:

Please note that these screen shots are being taken in Xcode, if you run the app, you will see the cells of the List.

Ok, so what is happening in that code. The first thing that is different is that the VStack is taking an argument for alignment. The reason that I have done this is because if we remove it, the Laps text view will be centered on the screen, and I preferred it to be on the left hand side.

Inside the VStack we add a Text view. We set the font size to be of .title size, has it is a section heading in our app. We also add padding to the Text view. This gives it a nice amount of spacing so that it is separated from the buttons above.

The final part is to add the List view. List views require a unique identifier for each cell. Unfortunately, each lapItem would not have a uniquely identifying property, so I had to add a uuid property which gets used in the ForEach. We then have access to the lapItem. We can now add in another Text view in which we can display each of the lap times that we have stored. To do this we simply access the stringTime property on the lapTime object that we have, and pass that to the Text view.

If you build and run the app now, you should be able to start the stopwatch, tap the Lap button and see the lap times show up in the bottom List. You should also be able to tap the Pause button and have the stopwatch pause, and once it is paused you should be able to tap the Reset button which will reset the stopwatch time as well as remove all the lap times from the List.

This is what the final code looks like:

import SwiftUIstruct StopWatchButton : View {
    var actions: [() -> Void]
    var labels: [String]
    var color: Color
    var isPaused: Bool
    
    var body: some View {
        let buttonWidth = (UIScreen.main.bounds.size.width / 2) - 12
        
        return Button(action: {
            if self.isPaused {
                self.actions[0]()
            } else {
                self.actions[1]()
            }
        }) {
            if isPaused {
                Text(self.labels[0])
                    .color(Color.white)
                    .frame(width: buttonWidth,
                           height: 50)
            } else {
                Text(self.labels[1])
                    .color(Color.white)
                    .frame(width: buttonWidth,
                           height: 50)
            }
        }
        .background(self.color)
    }
}struct ContentView : View {
    @ObjectBinding var stopWatch = StopWatch()
    
    var body: some View {
        VStack {
            Text(self.stopWatch.stopWatchTime)
                .font(.custom("courier", size: 70))
                .frame(width: UIScreen.main.bounds.size.width,
                       height: 300,
                       alignment: .center)
            
            HStack{
                StopWatchButton(actions: [self.stopWatch.reset, self.stopWatch.lap],
                                labels: ["Reset", "Lap"],
                                color: Color.red,
                                isPaused: self.stopWatch.isPaused())StopWatchButton(actions: [self.stopWatch.start, self.stopWatch.pause],
                                labels: ["Start", "Pause"],
                                color: Color.blue,
                                isPaused: self.stopWatch.isPaused())
            }VStack(alignment: .leading) {
                Text("Laps")
                    .font(.title)
                    .padding()List {
                    ForEach(self.stopWatch.laps.identified(by: \.uuid)) { (lapItem) in
                        Text(lapItem.stringTime)
                    }
                }
            }
        }
    }
}

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Building a Component Library with Angular and Storybook

Building a Component Library with Angular and Storybook

Learn how to build a component library with Angular and Storybook to create modular and reusable components that can be shared across projects.

Learn how to build a component library with Angular and Storybook to create modular and reusable components that can be shared across projects.

Storybook is a UI component explorer that visualizes components in different states. Storybook enables structured UI development, testing, and documentation for the major JavaScript frameworks.

Building a Component Library with Angular and Storybook

Before we start

I have a habit of using short hands of script commands and flags so here are a some that I might use in this article:

npm install -> npm i
ng test -> ng t
ng generate ->  ng g
ng generate library -> ng g lib

Component Library

The goal is to have a component library that we can explore with Storybook. For this, I’m creating a library with a button component.

Workspace

The Angular CLI is constantly getting better and the functionality I’m using here came with versions six and seven of Angular.

Make sure you have Angular CLI installed globally with:

npm i -g @angular/[email protected]

To begin with I’m going to create an empty workspace called ng-ui.

I don’t want to have an application and for that the --create-application flag is used with the ng new command. Setting this to false creates an empty workspace with no initial app.

ng new ng-ui --create-application=false

How to Build a Component Library with Angular and Storybook

For deeper knowledge in this topic read this great article by Todd Palmer:

Libraries

Now let’s create a component. Since each component is a library we can create one called button. Documentation for generate library.

ng g lib button -p ui

This creates the projects/button folder in your workspace, which contains a component and a service inside an NgModule. We don’t need the service so we can delete its files.

Component Library

The workspace configuration file, angular.json, is updated with a project of type library.

Build a Component Library with Angular and Storybook

As we can see, the architect has build, test, and lint so we can then use those commands.

ng build button
ng test button
ng lint button

The public API for your library is maintained in the public-api.ts file in your library folder. Anything exported from this file is made public when your library is imported into an application. Use an NgModule to expose services and components.

If you are using an older CLI you might have snake_case instead of kebab-case for this file: public_api.ts

Building a Component Library with Angular and Storybook

I have written two articles that go more into detail about creating libraries, adding useful things to them, and using them in other projects:

Button

import { Component, Input } from '@angular/core';

@Component({
  selector: 'lib-button',
  template: `
    {{text}}
  `
})
export class ButtonComponent {
  @Input() text: string;
  @Input() disabled: boolean;
}

Now we can build the button library.

ng build button

And now let’s also pack it so we can install it in other projects. For this, I’m going to pack it to a tarball. Since we need to be in the button directory when we run npm pack we can create a script for it.

"scripts": {
  ...
  "pack_button": "cd dist/button && npm pack",
  ...
}

Now we can use npm run pack_button to get a tarball called button-0.0.1.tgz.

Or if you want to publish it to a repository use npm publish instead of pack.

For deeper knowledge on building and packaging you can read this great article by Todd Palmer:

If you are into scripting and automation like I am then you can read this article where I explain how to automate your process with multiple libraries**.**

Let’s see how we can use our button component in Storybook next.

Storybook

Storybook is an environment for defining, developing, and testing UI components. It started as react-storybook but it is now open for other frameworks as well. Storybook is open source with a strong community behind it. Hundreds of contributors, tens of thousands of stars on GitHub, and millions of monthly downloads ensures a bright future.

It’s open source and totally free to use.

Setup

Now, let’s add Storybook to our project. It comes with a CLI tool that makes it really easy to add so let’s use it to initialize our project to a storybook project. Here I use npx so I don’t have to install it globally.

npx @storybook/cli init

It detects that our project is an Angular project and sets things up accordingly.

component library

All the necessary configurations, devDependencies, and npm scripts are added to our project. It also created src/stories/index.stories.ts with example stories.

component library

Since we didn’t have an application in our workspace we have to change the path to the TypeScript configuration file in storybook/tsconfig.json so that it instead extends the one in the root folder.

"extends": "../tsconfig.json"

Startup

We can now run storybook.

npm run storybook

This will start a local webpack server on port 6006 and you can visit the generated storybook by going to http://localhost:6006/. What you’ll see is an example Storybook that was generated from an index.stories.ts file under a stories folder at the root of the project.

build a component library with Angular CLI

You can see the generated sample stories in /stories/index.stories.ts.

There are two levels to the tree structure of Storybook. The component is defined by storiesOf and we use add for showing different views of it. You can add as many stories per component as you need.

build a component library with Angular CLI

And we can click to the corresponding button in the Storybook tree view.

build a component library with Angular CLI

Let’s delete these examples and create a story for the button we created in our library. To be able to use it we must first install it from the tarball we created.

Integration

We want to use the button library in our application so we use npm install like this:

npm i dist/button/button-0.0.1.tgz

Now if we open package.json we should see that the library is added to the dependencies.

"button": "file:dist/button/button-0.0.1.tgz"

If you instead published it to a repository you can install it as normal.

npm i button

Stories

Storybook is all about writing stories. A story usually contains a single state of one component, almost like a visual test case.

Let’s add a couple of stories to our button component. We have two input properties that we can test. For the first story, we send in ‘hello’ to the text property and get a normal button with hello written on it.

For the second story, we send in true to the disabled property and get a disabled button in the Storybook.

import { storiesOf } from '@storybook/angular';
import { ButtonComponent } from 'lib-button';

storiesOf('button', module)
  .add('basic', () => ({
    component: ButtonComponent,
    props: {
      text: 'hello'
    }
  }))
  .add('disabled', () => ({
    component: ButtonComponent,
    props: {
      text: 'disabled',
      disabled: true
    }
}));

how to build a component library with Angular CLI

build a component library with Angular CLI

By adding stories for all permutations of the properties of the component we get visual tests for each use-case. We can test and play with our component in an isolated environment. And this also enables designers to work on styling the components that are used in the application.

Conclusion

We’ve seen how and why you should consider using Storybook with Angular. By visualizing your UI component library, Storybook can help both developers and designers become more productive. And by writing stories we can also test all use-cases of the components.

How to design and build a carousel feature in VueJS

How to design and build a carousel feature in VueJS

Carousel, slideshow or slider, however you call it, this class of UI elements is essential to modern web development. Let's build on in VueJS!

A carousel, slideshow, or slider — however you call it this class of UI — has become one of the core elements used in modern web development. Today, it’s almost impossible to find any Website or UI library which doesn’t come with one or another kind of carousel.

Why, though? In fact, carousels really deserve their popularity. They allow users to skim through available content without vertical scrolling or heavy mouse movements. Consequently, users save time and can focus on the displayed content as Carousels keep cognitive load to a minimum.

This is reason enough to learn how to build a Carousel in VueJS!

All my tutorials gravitate around Progressive Vue Apps. This one is no exception! Making progressive apps means delivering a UX for mobile users close to native apps, including excellent performance, native features like push notifications, offline experience and much more. In a world where the majority of users experience the Web via mobile devices, there is no excuse left to not build progressive apps!

Of course you can still use the Carousel in any Vue app. You also don’t need any prior experience with VueJS or Progressive Web Apps for this tutorial!

What’s our Vision for the Carousel?

First thing we will do is to get an overview over what kind of components we want to build.

There are a few very straightforward ones:

  • Card → it holds the information of each carousel element.
  • Carousel → parent which holds all logic
  • ArrowButton → helps to navigate between multiple cards.
  • Indicator → shows the number of cards and which is currently visible.

Initial Setup

If you want to learn how to set up a project, this section is for you. In case you do not, just continue with the next section.

vue init pwa vue-pwa-carousel

We will be prompted to pick a preset — I recommend the following configuration:

? Project name vue-pwa-carousel
? Project short name: fewer than 12 characters to not be truncated on homescreens (default: same as name) vue-pwa-carousel
? Project description A simple tax calculator 
? Author Fabian Hinsenkamp
? Vue build runtime
? Install vue-router? No
? Use ESLint to lint your code? No
? Pick an ESLint preset Standard
? Setup unit tests with Karma + Mocha? No
? Setup e2e tests with Nightwatch? No

Run yarn in the root folder of the project to install all dependencies. Now we have a project set-up which includes the basic technologies we need to build our carousel. Moreover, it already includes a Service Worker which pre-caches all our static files and allows users to access the app even when they are offline.

You can check out how the template app looks like by running yarn start.

To test how the carousel looks on mobile, we need to expose our development build to mobile devices through a public URL. There are many ways to do so, but here we use ngrok as it’s easy to set up and just does its job.

yarn global add ngrok

Next, we need to run our dev server and ngrok in two separate terminals.

Let’s build the Card!

To save you some boring adjustments to the template app, just check out this branch00_basicSetup. It includes all data and styles we need to make this app meaningful and pretty.

The Card really does one thing: it shows the currently selected data. Which is, in our case, an image, a headline and some text.

Clearly, we do not want to build multiple cards with hard-coded content. Instead, we want to dynamically pass the data to the card and simply render it.

Based on that knowledge, we can now create our Card.vue file in the src/components folder. Moreover, we can already define the basic html structure and names and their types of the properties we want to pass to the card.

<template>
  <div class="card">
    <img
      class="card-icon"
      alt="card icon"
    />
    <div class='card-content'></div>
  </div>
</template>
<script>
export default {
  name: "Card",
  props: {
    headline: String,
    imgName: String,
    text: String
  }
};
</script>

Attention: we store all icons we want to display locally in our assets folder. That means that our path remains the same, but we need to dynamically change the file names which are supposed to be rendered. Consequently, all properties are of type String.

Next, we make the Card render the headline and the related text. Therefore, we use the most basic way of data-binding within VueJS — the mustache tag.

It’s basically just curly braces around our prop variables. As soon as data comes in, {{headline}} and {{text}} will be replace with the related data object. This is always true, also when new data comes in, after is has rendered other data before.

Rendering the image dynamically is a bit more tricky. Remember, we do not pass the actual icon but only its file name.

So we basically want to consume the image as a module, like any other component. A static image we could consume by importing it in the script block and assign it to a variable. However, we do have changing path. As our app uses webpack there is a fantastic shorthand available to load these dynamically as follows:

:src="require(`@/assets/svg/${imgName}`)"

The : syntax is the Vue-way to dynamically bind attributes to an expression. You might already have seen the v-bind: prefix which : is the shorthand for.

Now our template block is completed and looks as follows.

<template>
  <div class="card">
    <img
      class="card-icon"
      :src="require(`@/assets/svg/${imgName}`)"
      alt="card icon"
    />
    <div class='card-content'>
      <h3 class='headline'>{{headline}}</h3>
      <p>{{text}}</p>
    </div>
  </div>
</template>

To finalise our Card component, we simply need to add the prepared styled to the bottom of the file.

<style src="../assets/styles/Card.css" scoped>

Last thing we need to do for this section is to check if the Card actually works.

<template>
...
 <main>
      <h1>{{ headline }}</h1>
      <Card
        class="current-element"
        :headline="cards[0].headline"
        :text="cards[0].text"
        :imgName="cards[0].imgName"
      />
...
</template>
<script>
...
import Card from "./components/Card";
export default {
  name: "app",
  components: { Imprint, Card },
...
</script>

So let’s simply add it the our App.vue component. However, keep in mind that we will have to move the component into the Carousel component in the next section.

We add the following to the <template> and <script> blocks of App.vue.

What a fantastic result! Especially, since we can already dynamically change whatever the Card should display!

Next, we build the Carousel to have a dedicated component to manage all logic around showing different Cards based on user inputs.

Check out the branch 01_Card to if you want to start from here or compare your implementation.

Let’s build the Carousel

The Carousel will be our reusable parent component. It will encapsulate all relevant components and logic.

Like with the Card before, we should focus on building the component in a way that it can handle a change in data gracefully. For example, it should be capable of handling varying numbers of cards being passed to it.

Next we will see how this approach translates into Code. First we start with creating a Carousel component and make the Card a child of Carousel.

<template>
 <div>
  <div class="card-carousel">
   <Card
    class="current-element"
    :headline="currentElement.headline"
    :infoText="currentElement.infoText"
    :imgName="currentElement.imgName"
   />
  </div>
 </div>
</template>

The template block of the new component hosts the Card, wrapped in two wrapper elements. We will see later why these are necessary.

As we will pass data of multiple Cards to the Carousel, we need to specify that only the currentElement is rendered.

In the following <script> block we need to define which of the passed Cards is the currentElement by default.

<script>
export default {
  name: "Carousel",
  props: { cards: Array },
  components: { Card },
  data() {
    return {
      currentElementIndex: 0
    };
  },
  computed: {
    currentElement() {
      return this.cards[this.currentElementIndex];
    }
  }
};
</script>

Therefore, we define the currentElementIndex initially to be 0. VueJS comes with a feature that allows us to compute variables dynamically. We use it to select the data of the card that should render initially.

Now we only need to replace the Card with the Carousel in our App.vue file. To put a bit more structure and meaning to our final page, let’s wrap the carousel in another section element and place it before the other section.

<template>
...
 <div class="section">
  <h2>{{this.sections[0].headline}}</h2>
  <Carousel :cards="cards" />
 </div>
...
<template>

That’s our basic implementation. It is not quite a Carousel yet but we are about to change this by adding the arrow buttons to switch between the objects we pass in the cards array to our Carousel.

Check out the 02_Carousel to see the complete code for this section. If you coded along you should see the following in front of you.

Let’s build the ArrowButton

Now we build the ArrowButton component, which receives its methods and the type of arrow icon from its parent. The implementation itself is strait forward.

<template>
  <button class="btn" @click="onClick">
    <img
      class="icon"
      :src="require(`@/assets/svg/${arrowType}.svg`)"
      :alt="arrowType + ' arrow'"
    >
  </button>
</template>
<script>
export default {
  name: "ArrowButton",
  props: { arrowType: String, onClick: Function }
};
</script>
<style src="../assets/styles/ArrowButton.css" scoped/>

The component is only responsible for rendering the correct styles and the icon. All logic related to the Buttons is added to the Carousel. That way, we have created a truly generic component we could use in any context where we want to use a button with an arrow icon.

<script>
...
export default {
...
 computed: {
   ...
    reachedMaxLeft() {
      return this.currentElementIndex === 0;
    },
    reachedMaxRight() {
      return this.currentElementIndex === this.cards.length - 1;
    }
  },
  methods: {
    showNextElement() {
      this.currentElementIndex++;
    },
    showPrevElement() {
      this.currentElementIndex--;
    }
  }
};
</script>

Now, within Carousel, we add two methods to navigate between our card data objects. Methods are just another exported object within the <script> block.

These simply increase or decrease the currentElementIndex by 1. We use the index to compute the currentElement variable, so every time one of the methods is called the next card is displayed. We also add some restrictive conditions, as we want the Carousel not to loop.

Now we only need to add the ArrowButtons to basically complete our Carousel!

<template>
  <div>
    <div class="card-carousel">
      <ArrowButton
        arrowType="left"
        :onClick="showPrevElement"
        :disabled="this.reachedMaxLeft"
      />
      ...
    </div>
  </div>
</template>

Here you see how we use the methods and computed values to implement one of our ArrowButtons. Try to implement the second one below the Card component.

In case you get stuck or something just looks wrong, checkout the 03_ArrowButton branch. If everything worked out though, your carousel should look like the following:

Let’s build Indicators!

The last feature we’re going to add are the Indicators. These help users to understand how many Cards there are and which one they are currently looking at. Additionally, these allow the user to select individual Cards directly.

<template>
  <ul>
    <li
      v-for="(_, index) in elements"
      class="dot"
      :key="index"
      :class="{'dot-selected': currentElementIndex === index}"
    >
      <button
        class="indicator-btn"
        @click='showElement(index)'
        :disabled=" currentElementIndex === index"
      />
    </li>
  </ul>
</template>

<script>
export default {
  name: "Indicators",
  props: { elements: Array, currentElementIndex: Number, showElement: Function }
};
</script>
<style src="../assets/styles/Indicators.css" scoped/>

The component receives three properties. The array of elementswe use to create a <li>element for each card data object.

currentElementIndexis required to add a CSS class that highlights the indicator related to the current card. Moreover, it is used to disable the button for the current card. That way we prevent it from being selectable is via the tab keys. That way, we provide at least a minimum of accessibility.

showElement is the method which is called when a user clicks on an indicator. It’s passed from outside to keep the component as focused as possible. How an element is shown is clearly no concern of Indicators.

<template>
  <div>
    <div class="card-carousel">
     ...
    </div>
    <Indicators
      :elements="this.cards"
      :currentElementIndex="this.currentElementIndex"
      :showElement="this.showElement"
    />
  </div>
</template>
<script>
export default {
  ...
  methods: {
  ...
    showElement(elementIndex) {
      this.currentElementIndex = elementIndex;
    }
  }
};
</script>

When we add the Indicators to Carousel.vue it becomes clear why we created two wrappers for the Card. Semantic and clear HTML is vital, especially for large projects with a high level of complexity.

You can check out the complete code at branch 04_Indicators.

Let’s add swipe

Last but not least, we make our Carousel mobile friendly. A good progressive web app doesn’t start by caching static files, but with responsiveness.

As we do lack space on small screens, we hide the ArrowButtons and allow users to swipe in order to browse the Cards. Here the Indicators also do pay off again, as they function in mobile as the main indicator that users can swipe to see more cards.

Therefore we add the following library:

yarn add vue2-touch-events

Next we add the new v-touch attribute and a handler method to the Card. This takes care of the events emitted by swipes.

<template>
 ...
  <Card
    ...
    v-touch:swipe="this.swipeHandler"
    ...
  />
 ...
</template>
<script>
...
export default {
...
  methods: {
    swipeHandler(direction) {
      if (direction === "right" && !this.reachedMaxLeft) {
        this.prevElement();
      }
      if (direction === "left" && !this.reachedMaxRight) {
        this.nextElement();
      }
  }
};
</script>

Conclusion

Fantastic, we made it! We had the vision of building an encapsulated and reusable Carousel component, and we did!

Learn More

Build a Basic CRUD App with Laravel and Vue

Build a Simple CRUD App with Spring Boot and Vue.js

Full Stack Developers: Everything You Need to Know

ES5 to ESNext — here’s every feature added to JavaScript since 2015

Vuejs 2 Authentication Tutorial

Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

Nuxt.js - Vue.js on Steroids

Vue.js Fast Crash Course

The Complete JavaScript Course 2018: Build Real Projects!

JavaScript: Understanding the Weird Parts

MERN Stack Front To Back: Full Stack React, Redux & Node.js

Top Vue.js Developers in USA

Top Vue.js Developers in USA

Vue.js is an extensively popular JavaScript framework with which you can create powerful as well as interactive interfaces. Vue.js is the best framework when it comes to building a single web and mobile apps.

We, at HireFullStackDeveloperIndia, implement the right strategic approach to offer a wide variety through customized Vue.js development services to suit your requirements at most competitive prices.

Vue.js is an open-source JavaScript framework that is incredibly progressive and adoptive and majorly used to build a breathtaking user interface. Vue.js is efficient to create advanced web page applications.

Vue.js gets its strength from the flexible JavaScript library to build an enthralling user interface. As the core of Vue.js is concentrated which provides a variety of interactive components for the web and gives real-time implementation. It gives freedom to developers by giving fluidity and eases the integration process with existing projects and other libraries that enables to structure of a highly customizable application.

Vue.js is a scalable framework with a robust in-build stack that can extend itself to operate apps of any proportion. Moreover, vue.js is the best framework to seamlessly create astonishing single-page applications.

Our Vue.js developers have gained tremendous expertise by delivering services to clients worldwide over multiple industries in the area of front-end development. Our adept developers are experts in Vue development and can provide the best value-added user interfaces and web apps.

We assure our clients to have a prime user interface that reaches end-users and target the audience with the exceptional user experience across a variety of devices and platforms. Our expert team of developers serves your business to move ahead on the path of success, where your enterprise can have an advantage over others.

Here are some key benefits that you can avail when you decide to hire vue.js developers in USA from HireFullStackDeveloperIndia:

  • A team of Vue.js developers of your choice
  • 100% guaranteed client satisfaction
  • Integrity and Transparency
  • Free no-obligation quote
  • Portal development solutions
  • Interactive Dashboards over a wide array of devices
  • Vue.js music and video streaming apps
  • Flexible engagement model
  • A free project manager with your team
  • 24*7 communication with your preferred means

If you are looking to hire React Native developers in USA, then choosing HireFullStackDeveloperIndia would be the best as we offer some of the best talents when it comes to Vue.js.

Building a Chat application using Flexbox

Building a Chat application using Flexbox

In this article we are going to focus on building a basic sidebar, and the main chat window inside our chat shell. See below.

In this article we are going to focus on building a basic sidebar, and the main chat window inside our chat shell. See below.

Chat shell with a fixed width sidebar and expanded chat window

This is the second article in this series. You can check out the previous articlefor setting up the shell OR you can just** **check out the **chat-shell **branch from the following repository.

https://github.com/lyraddigital/flexbox-chat-app.git

Open up the chat.html file. You should have the following HTML.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Chat App</title>
    <link rel="stylesheet" type="text/css" media="screen" href="css/chat.css" />
</head>
<body>
    <div id="chat-container">
    </div>
</body>
</html>

Now inside of the **chat-container div **add the following HTML.

<div id="side-bar">
</div>
<div id="chat-window">
</div>

Now let’s also add the following CSS under the #chat-container selector in the chat.css file.

#side-bar {
    background: #0048AA;
    border-radius: 10px 0 0 10px;
}
#chat-window {
    background: #999;
    border-radius: 0 10px 10px 0;
}

Now reload the page. You should see the following:-

Chat shell with sidebar and chat window before sizing

So what happened? Where is our sidebar and where is our chat window? I expected to see a blue side bar and a grey chat window, but it’s no where to be found. Well it’s all good. This is because we have no content inside of either element, so it can be 0 pixels wide.

Sizing Flex Items

So now that we know that our items are 0 pixels wide, let’s attempt to size them. We’ll attempt to try this first using explicit widths.

Add the following width property to the #side-bar rule, then reload the page.

width: 275px;

Hmm. Same result. It’s still a blank shell. Oh wait I have to make sure the height is 100% too. So we better do that too. Once again add the following property to the #side-bar rule, then reload the page.

height: 100%;

Side bar with explicit width and height set

So now we have our sidebar that has grown to be exactly 275 pixels wide, and is 100% high. So that’s it. We’re done right? Wrong. Let me ask you a question. How big is the chat window? Let’s test that by adding some text to it. Try this yourself just add some text. You should see something similar to this.

Chat window is not where we expect it to be.

So as you can see the chat window is only as big as the text that’s inside of it, and it is not next to the side bar. And this makes sense because up until now the chat shell is not a flex container, and just a regular block level element.

So let’s make our chat shell a flex container. Set the following display property for the **#chat-window selector. **Then reload the page.

display: flex;

Chat window is in the right place, but wrong size

So as you can see by the above illustration, we can see it’s now next to the side bar, and not below it. But as you can see currently it’s only as wide as the text that’s inside of it.

But we want it to take up the remaining space of the chat shell. Well we know how to do this, as we did it in the previous article. Set the **flex-grow property to 1 **on the #chat-window selector. Basically copy and paste the property below and reload the page.

flex-grow: 1;

Chat shell with chat window that has grown

So now we have the chat window taking up the remaining space of the chat shell. Next, let’s remove the background property, and also remove all text inside the chat-window div if any still exists. You should now see the result below.

Final output — With explicit width and height for the side bar

But are we done? Technically yes, but before we move on, let’s improve things a little bit.

Understanding the default alignment

If you remember, before we had defined our chat shell to be a flex container, we had to make sure we set the height of the side bar to be 100%. Otherwise it was 0 pixels high, and as a result nothing was displayed. With that said, try removing the height property from the #side-bar selector and see what happens when you reload the page. Yes that’s right, it still works. The height of the sidebar is still 100% high.

So what happened here? Why do we no longer have to worry about setting the height to 100%? Well this is one of the cool things Flexbox gives you for free. By default every flex item will **stretch **vertically to fill in the entire height of the flex container. We can in fact change this behaviour, and we will see how this is done in a future article.

Setting the size of the side bar properly

So another feature of Flexbox is being able to set the size of a flex item by using the flex-basis property. The flex-basis property allows you to specify an initial size of a flex item, before any growing or shrinking takes place. We’ll understand more about this in an upcoming article.

For now I just want you to understand one important thing. And that is using width to specify the size of the sidebar is not a good idea. Let’s see why.

Say that potentially, if the screen is mobile we want the side bar to now appear across the top of the chat shell, acting like a top bar instead. We can do this by changing the direction flex items can flex inside a flex container. For example, add the following CSS to the #chat-container selector. Then reload the page.

flex-direction: column;

Sidebar gone — It’s 0 pixels high when using column direction

So as you can see we are back to a blank shell. So firstly let’s understand what we actually did here. By setting the flex-direction property to column, we changed the direction of how the flex items flex. By default flex items will flex from left to right. However when we set flex-direction to column, it changes this behaviour forcing flex items to flex from top to bottom instead. On top of this, when the direction of flex changes, the sizing and alignment of flex items changes as well.

When flexing from left to right, we get a height of 100% for free as already mentioned, and then we made sure the side bar was set to be 275 pixels wide, by setting the width property.

However now that we a flexing from top to bottom, the width of the flex item by default would be 100% wide, and you would need to specify the height instead. So try this. Add the following property to the #side-bar selector to set the height of the side bar. Then reload the page.

height: 275px;

Sidebar with a fixed width and height

Now we are seeing the side bar again, as we gave it a fixed height too. But we still have that fixed width. That’s not what we wanted. We want the side bar (ie our new top bar) here to now be 100% wide. Comment out the width for a moment and reload the page again.

Sidebar rotated to now be on top

So now we were able to move our side bar so it appears on top instead, acting like a top bar. Which as previously mentioned might be suited for mobile device widths. But to do this we had to swap the value of width to be the value of height. Wouldn’t it be great if this size was preserved regardless of which direction our items are flexing.

Try this, remove all widths and height properties from the #side-bar selectorand write the following instead. Then reload the page.

flex-basis: 275px;

As you can see we get the same result. Now remove the **flex-direction property from the #chat-container selector. **Then once again reload the page.

Final output using flex-basis property

Once again we are back to our final output. But now we also have the flexibility to easily change the side bar to be a top bar if we need to, by just changing the direction items can flow. Regardless of the direction of flex, the size of our side bar / top bar is preserved.

Conclusion

Ok so once again we didn’t build much, but we did cover a lot of concepts about Flexbox around sizing. We will cover more concepts in the next article where we layout out the elements in our side bar.