Wednesday, May 23, 2018

Design Better Forms

Common mistakes designers make and how to fix them




Whether it is a signup flow, a multi-view stepper, or a monotonous data entry interface, forms are one of the most important components of digital product design. This article focuses on the common dos and don’ts of form design. Keep in mind that these are general guideline and there are exceptions to every rule.

Forms should be one column


 
Multiple columns disrupt a users vertical momentum.


Top align labels


 

Users complete top aligned labeled forms at a much higher rate than left aligned labels. Top aligned labels also translate well on mobile. However, consider using left aligned labels for large data-set entry with variable optionality because they are easier to scan together, they reduce height, and prompt more consideration than top aligned labels.


Group labels with their inputs


 

Present the label and input close together, and make sure there is enough height between the fields so users don’t get confused.

Avoid all caps


 
All caps is more difficult to read and scan.


Show all selection options if under 6


 

Placing options in a selector drop-down requires two clicks, and hides the options. Use an input selector if there are over 5 options. Incorporate contextual search within the drop-down if there are over 25 options.



Resist using placeholder text as labels

It is tempting to optimize space by using placeholder text as labels. This causes many usability issues that have been summarized by Katie Sherwin of Nielsen Norman Group.



Place checkboxes (and radios) underneath each other for scannability


 
Placing checkboxes underneath each other allows easy scanning.


Make CTAs descriptive


 
A call to action should state the intent.


Specify errors inline


 
Show the user where the error occurred and provide a reason.


Use inline validation after the user fills out the field (unless it helps them while in the process)


Don’t use inline validation while the user is typing — unless it helps them — like in the case of creating a password, username, or message with a character count.



Don’t hide basic helper text


Expose basic helper text wherever possible. For complex helper text, consider placing it next to the input during its focused state.

Differentiate primary from secondary actions


There is a bigger philosophical debate regarding whether a secondary option should even be included.



Use field length as an affordance


The length of the field affords the length the answer. Employ this for fields that have a defined character count like phone numbers, zip codes, etc.



Ditch the * and denote optional fields


Users don’t always know what is implied by the required field marker (*). Instead, it is better to denote optional fields.



Group related information


Users think in batches, and long forms can feel overwhelming. By creating logical groups the user will make sense of the form much faster.


Why ask?

Omit optional fields and think of other ways to collect data. Always ask yourself if the question can be inferred, postponed, or completely excluded.
Data entry is increasingly automated. For example, mobile and wearable devices collect large amounts of data without the user’s conscious awareness. Think of ways you can leverage social, conversational UI, SMS, email, voice, OCR, location, fingerprint, biometric, etc.

Make it fun

Life is short. No one wants to fill out a form. Be conversational. Be funny. Gradually engage. Do the unexpected. It is the role of the designer to express their company’s brand to elicit an emotional reaction. If done correctly, it will increase completion rates. Just make sure you don’t violate the rules listed above.

Saturday, December 2, 2017

Angular 2 Cheat Sheet

Angular 2 Cheat Sheet

Binding

One Way Binding
<h1>{{pageTitle}}</h1>
Two Way Binding
<input [(ngMo­del­)]=­"­cus­tom­er.F­ir­stN­ame­">
Property Binding
<img [src]=­"­cus­tom­er.i­ma­geU­rl">
Attribute Binding
<button [attr.a­ri­a-l­abe­l]=­"­ok">­Ok<­/bu­tto­n>
Class Binding
<div [class.Se­lec­ted­]="S­ele­cte­d">S­ele­cte­d</­div>
ngClass
<div [ngClass]="setClasses()">
  {{customer.name}}
</div>
Style Binding
<button [style.co­lor­]="i­sSe­lected ? 'red' : 'white­'">
ngStyle
<div [ngStyle]="setStyles()">
  {{customer.name}}
</div>
Component Binding
<cu­sto­mer­-detail [customer]="currentCustomer">
<customer-detail>
Directive Binding
<div [ngClass] = "­{se­lected: isSele­cte­d}">­Cus­tom­er<­/di­v>
Event Binding
<button (click­)="s­ave­()">­Sav­e</­but­ton>
$event
<input [value]="customer.name"
 (input)="customer.name=$event.target.value">

Lifecycle Hooks

OnInit
export class Customer implements OnInit {
  ngOnInit() {}
}
OnChanges
export class Customer implements OnChanges {
  ngOnChanges() {}
}
AfterV­iewInit
export class Customer implements AfterV­iewInit {
  ngAfterViewInit() {}
}
OnDestroy
export class Customer implements OnDestroy {
  ngOnDestroy() {}
}

Pipes

Upper Case
<p>{{customer.name | upperc­ase­}}<­/p>
Lower Case
<p>{{customer.name | lowerc­ase­}}<­/p>
Date
<p>{{orderDate | date:'­med­ium­'}}­</p>
Date Format
<p>{{orderDate | date:'­yMM­Md'­'}}­</p>
Currency
<p>{{price | curren­cy}­}</­p>
Percent
<p>{{taxes | percen­t:'­1.1­-1'­}}<­/p>
Number
<p>­value | number­:'1.1-­2'}­}</­p>
JSON Debugging
<pre>{{Customer | json}}­</p­re>

Component with Inline Template


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

@Component({
  moduleId: module.id,
  selector: 'customer',
  template: `
    <h3>{{customer.name}}</h3>
  `
})

export class CustomerComponent {
  customer = { id: 100, name: 'John Smith' };
}

Structural Directives

*ngIf
<div *ngIf="currentCustomer">
  Selected {{currentCustomer.Name}}
</d­iv>
*ngFor
<ul>
  <li *ngFor­="let customer of customers">
    {{ custom­er.name }}
  </li>
</ul>
*ngSwitch
<div [ngSwitch]="orderStatus">
  <template [ngSwitchCase]="purchased"></template>
  <template [ngSwitchCase]="shipped"></template>
  <template [ngSwitchDefault]></template>
</div>

Service


//Example: customer.service.ts
import { HttpModule } from '@angular/http'

@Injectable()
export class CustomerService {
  constructor(private http: Http) { }

  getCustomers() {
    return this.http.get('api/customers')
      .map((response: Response) => <Customer[]>response.json().data)
      .catch(this.handleError);
  }

  private handleError(error: Response) {
    console.error(error);
    return Observable.throw(error.json().error || 'Service error');
  }
}

Injecting a Service


//Example: customer-list.component.ts
export class CustomerListComponent {
  customers: Customer[];
  
  constructor(private customerService: CustomerService) { }
}

Component Linked Template


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

@Component({
  moduleId: module.id,
  selector: 'customer',
  templateUrl: 'customer.component.html',
  styleUrls: ['customer.component.css']
})

export class CustomerComponent {
  customer = { id: 100, name: 'John Smith' };
}

Monday, November 27, 2017

Tutorial for Developing a Progressive Web App With ReactJS

In this tutorial, we'll learn how to create a simple React app, and use another tool to help us test it along the way. Let's get to it!

Progressive Web Apps (PWAs) have rapidly grown in popularity as essentially fast, performance-based web applications streamlined for delivering mobile app-like experiences. PWAs are built using HTML, CSS, and JavaScript to create a level of usability and performance that’s in parity to native mobile applications. They are responsive, consume lesser data and storage space, and supports push notifications and offline usage in the browser.
Building a progressive web app has now become a web development trend every enterprise wants to follow. Big players such as Twitter and Flipboard recently launched their progressive web apps to deliver mobile experiences to users, without requiring them to actually install the app. In this article, you will learn how to build a progressive web app using React. So, let’s get started.

Step 1 – Setting Up a React App

First, generate a React app with create-react-app. To do so, you need to run the following commands:
npm install -g create-react-app
create-react-app pwa-app
Now install React Router:
cd pwa-app
npm install --save react-router@3.0.5
You need to replace the “src/App.js” content using the below code to get a basic template with navigation.
import React, { Component } from 'react';
import { Router, browserHistory, Route, Link } from 'react-router';
import './App.css';
const NavBar = () => (
  <div className="navbar">
    <Link to="/">Feed</Link>
    <Link to="/profile">Profile</Link>
  </div>
);
const Template = ({ title }) => (
  <div>
    <NavBar />
    <p className="page-info">
      This is the {title} page.
    </p>
  </div>
);
const Feed = (props) => (
  <Template title="Feed"/>
);
const Profile = (props) => (
  <Template title="Profile"/>
);
class App extends Component {
  render() {
    return (
      <Router history={browserHistory}>
        <Route path="/" component={Feed}/>
        <Route path="/profile" component={Profile}/>
      </Router>
    );
  }
}
export default App;
Now, you will have to update the default styles by replacing your “src/App.css” with the below styles to make you app look clean.
.navbar {
  background-color: #01C8E5;
  text-align: center;
}
.navbar a {
  display: inline-block;
  padding: 10px;
  color: #fff;
  text-decoration: none;
}
.page-info {
  text-align: center;
  font-weight: bold;
}
Then run the “npm start” to test the app in the browser. This is a basic app with two routes. You will now convert it into a PWA.

Step 2 – Installing Lighthouse and Audit

Lighthouse is an automated, open source tool for testing applications against the PWA checklist. It facilitates audits for accessibility, performance, and more.

Test your app with Lighthouse. Click the Lighthouse icon from the top right corner in Chrome and then click on the ‘Generate Report’ button. The generated report will look like this:
Installing Lighthouse and Audit
You will have to fix all the failed audits. 

Step 3 – Registering a Service Worker

Service workers are the proxy servers that connect the app and network. With Service Worker, you will have to intercept network requests and save cached files. This will enable your app to work even when the network is unavailable. 

Create a blank worker.js file in your app’s public folder and add the following code to that file:
// Flag for enabling cache in production
var doCache = false;
var CACHE_NAME = 'pwa-app-cache';
// Delete old caches
self.addEventListener('activate', event => {
  const currentCachelist = [CACHE_NAME];
  event.waitUntil(
    caches.keys()
      .then(keyList =>
        Promise.all(keyList.map(key => {
          if (!currentCachelist.includes(key)) {
            return caches.delete(key);
          }
        }))
      )
  );
});
// This triggers when user starts the app
self.addEventListener('install', function(event) {
  if (doCache) {
    event.waitUntil(
      caches.open(CACHE_NAME)
        .then(function(cache) {
          fetch('asset-manifest.json')
            .then(response => {
              response.json();
            })
            .then(assets => {
              // We will cache initial page and the main.js
              // We could also cache assets like CSS and images
              const urlsToCache = [
                '/',
                assets['main.js']
              ];
              cache.addAll(urlsToCache);
            })
        })
    );
  }
});
// Here we intercept request and serve up the matching files
self.addEventListener('fetch', function(event) {
  if (doCache) {
    event.respondWith(
      caches.match(event.request).then(function(response) {
        return response || fetch(event.request);
      })
    );
  }
});
Now check if the browsers support the service workers and thereafter register worker.js. To do this, you need to add the following script to public/index.html (Note that “shrink-to-fit=no” from viewport meta tag has been removed).
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <title>React App</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
    <script>
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', function() {
          navigator.serviceWorker.register('worker.js').then(function(registration) {
            console.log('Worker registration successful', registration.scope);
          }, function(err) {
            console.log('Worker registration failed', err);
          }).catch(function(err) {
            console.log(err);
          });
        });
      } else {
        console.log('Service Worker is not supported by browser.');
      }
    </script>
  </body>
</html>
You must restart your app and reload the browser after which you will notice the “Worker Registration Successful” message in the developer console. Now regenerate the Lighthouse report.

Step 4 – Improving Progressive Nature of the App

Your app will render an empty root div until the JavaScript loads and React hooks the initial route. You must ensure your app works without any JS loading and displays a bit of CSS and HTML before React comes into play. Your updated index.html will look like this:
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <title>React App</title>
    <style type="text/css">
      body {
        margin: 0;
        padding: 0;
        font-family: sans-serif;
      }
      .navbar {
        background-color: #01C8E5;
        text-align: center;
      }
      .navbar a {
        display: inline-block;
        padding: 10px;
        color: #fff;
        text-decoration: none;
      }
      .page-info {
        text-align: center;
        font-weight: bold;
      }
    </style>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root">
      <div class="navbar">
        <a href="/">Feed</a>
      </div>
      <p class="page-info">
        Loading an awesome app...
      </p>
    </div>
    <script>
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', function() {
          navigator.serviceWorker.register('worker.js').then(function(registration) {
            console.log('Worker registration successful', registration.scope);
          }, function(err) {
            console.log('Worker registration failed', err);
          }).catch(function(err) {
            console.log(err);
          });
        });
      } else {
        console.log('Service Worker is not supported by browser.');
      }
    </script>
  </body>
</html>
Now use Lighthouse to re-audit your app and you will notice an improvement in the app's performance.

Step 5 – Adding Splash Icons

You’re required to add a 512x512 icon to show up on the splash screen. To do so, you will have to update the manifest.json and add the icon in the public folder.
{
  "short_name": "React App",
  "name": "Create React App Sample",
  "icons": [
    {
      "src": "icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {  
      "src": "icon-512x512.png",  
      "sizes": "512x512",  
      "type": "image/png"  
    }
  ],
  "start_url": "/",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}
Also, use the following meta tags to allow the browser to identify that your app is a PWA.
<!-- Tell the browser it's a PWA -->
<meta name="mobile-web-app-capable" content="yes">
<!-- Tell iOS it's a PWA -->
<meta name="apple-mobile-web-app-capable" content="yes">

Step 6 – Deploying the PWA

Now, just the HTTPS is missing and caching can be fixed after you deploy the app. Update the doCache flag with ‘true’ in the worker.js file. Create a new project in firebase-console and name it 'Pwa App.' Then run the following command in the project directory:
npm install -g firebase-tools
firebase login
firebase init
Your firebase.json should look like this:
{
  "hosting": {
    "public": "build",
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}
After initialization, build and deploy your app.
npm run build
firebase deploy
You will see the following outcome after you audit the app using Lighthouse on the deployed URL.
Deploying the PWA using Lighthouse
Finally, you’ve created your first progressive web app with ReactJS!