Monday, June 19, 2017

Web Design Weekly #283

Headlines

Building Production-Ready CSS Grid Layouts

Morten Rand-Hendriksen gives us an understanding of what new layout opportunities and challenges CSS Grid brings, what old problems it solves and how to start using it in production today. (smashingmagazine.com)

Perfect Paragraph (betterwebtype.com)

Find Top Developers Fast

The search is over. Let Toptal connect you with the world’s most talented developers. Get started today. (toptal.com)

Articles

A React TODOs example, explained

If you are still battling with some React concepts this post and code examples are a great way to get a better understanding of how things should be structured and why. (hackernoon.com)

Embracing the Power of Styled Components

Fernando Agüero shares what he and his team learnt in the first week moving away from CSS Modules to Styled Components. (building.sentisis.com)

A crash course in memory management

The first of an awesome 3-part series by Lin Clark that aims to give you a good understanding of why ArrayBuffer and SharedArrayBuffer were added to JavaScript. (mozilla.org)

Redesign

Tinkering and rebuilding your personal site is one of the best ways to explore new tech without too much pressure. A perfect way to learn really. In this post Ben Smithett shares the inner details of his latest blog redesign. (bensmithett.com)

WebAssembly 101: A Developer’s First Steps

This tutorial guides you along the necessary steps to port a JavaScript library of the Conway’s game of life to WebAssembly. (blog.openbloc.fr)

JavaScript’s new #private class fields (thejameskyle.com)

Tools / Resources

An Introduction to the `fr` CSS unit

Robin Rendle digs into how the new `fr` CSS length unit can be used in conjunction with CSS Grid. (css-tricks.com)

Visuals are processed 60K times faster in the brain than text. Find the perfect visuals for your project at iStock.

Easily search millions of powerful images and video clips at iStock and ensure your project truly stands out. Until July 6th new customers can save 15% with code KZKPC46N. Make an impact without breaking the bank. (istockphoto.com)

A Guide to ES2015

In this article Ashley Rich shares his favourite parts of ES2015. Ashely clearly explains some of the features that make it pretty easy for you to keep your JavaScript cutting edge. (deliciousbrains.com)

Letter Effects and Interaction Ideas

A couple of ideas for typography animations and letter effects for playful interactions. (tympanus.net)

React State vs. Redux State: When and Why? (atomicobject.com)

Real-World Redux-Saga Patterns (formidable.com)

Using CSS Variables (correctly) (codepen.io)

Safari 11.0 (developer.apple.com)

Inspiration

The Road to Burnout is Paved With Context Switching (sophieshepherd.com)

Overtime with Rogie King (dribbble.com)

Jobs

Senior JavaScript Engineer

We are looking for a senior JavaScript engineer with a history of front-end JavaScript or Node.js experience to lead projects in React JS and deliver key new features for Outreach. (outreach.io)

Web/Interactive Designer at Sanborn

Sanborn is currently on the hunt for an enthusiastic, energetic soul to join our design team. We are looking for a designer who wants to be challenged in a fast-paced work environment. (sanbornagency.com)

Need to find passionate developers or designers? Why not advertise in the next newsletter

Last but not least…

Results of the Ultimate CSS Survey 2017 (sitepoint.com)

The post Web Design Weekly #283 appeared first on Web Design Weekly.


by Jake Bresnehan via Web Design Weekly

How to Build a Real-Time GitHub Issue To-Do List with CanJS

CanJS is a collection of front-end libraries that make it easier to build complex and innovative web apps that are maintainable over a long period of time. It’s broken up into dozens of individual packages, so you can pick-and-choose what you’d like in your application without being bogged down by a huge 100kb+ dependency.

CanJS promotes the MVVM (Model-View-ViewModel) architecture with the following key packages:

In this tutorial, we’re going to make a to-do list app that uses a GitHub repository’s issue list as its source. Our app will update in real-time thanks to GitHub’s Webhook API and we’ll be able to reorder issues thanks to jQuery UI’s sortable interaction.

You can find the finished source code for this app on GitHub. Here’s what the final app will look like:

Gif of adding issues and sorting them in our example app

If you're interested in taking your JavaScript skills to the next level, sign up for SitePoint Premium and check out our latest book, Modern JavaScript

MVVM in CanJS

Before we start our project for this tutorial, let’s dive into what MVVM means within a CanJS application.

Data Models

The “Model” in MVVM is for your data model: a representation of the data within your application. Our app deals with individual issues and a list of issues, so these are the data types that we have in our model.

In CanJS, we use can-define/list/list and can-define/map/map to represent arrays and objects, respectively. These are observable types of data that will automatically update the View or ViewModel (in MVVM) when they change.

For example, our app will have an Issue type like this:

import DefineMap from 'can-define/map/map';
const Issue = DefineMap.extend('Issue', {
  id: 'number',
  title: 'string',
  sort_position: 'number',
  body: 'string'
});

Each instance of Issue will have four properties: id, title, sort_position, and body. When a value is set, can-define/map/map will convert that value to the type specified above, unless the value is null or undefined. For example, setting the id to the string "1" will give the id property the number value 1, while setting it to null will actually make it null.

We’ll define a type for arrays of issues like this:

import DefineList from 'can-define/list/list';
Issue.List = DefineList.extend('IssueList', {
  '#': Issue
});

The # property on a can-define/list/list will convert any item in the list to the specified type, so any item in an Issue.List will be an Issue instance.

View Templates

The “view” in a web application is the HTML user interface with which users interact. CanJS can render HTML with a few different template syntaxes, including can-stache, which is similar to Mustache and Handlebars.

Here’s a simple example of a can-stache template:

<ol>
  
    <li>
      
    </li>
  
</ol>

In the above example, we use to iterate through a list of issues, then show the title of each issue with . Any changes to the issues list or the issue titles will cause the DOM to be updated (e.g. an li will be added to the DOM if a new issue is added to the list).

View Models

The ViewModel in MVVM is the glue code between the Model and View. Any logic that can’t be contained within the model but is necessary for the view is provided by the ViewModel.

In CanJS, a can-stache template is rendered with a ViewModel. Here’s a really simple example:

import stache from 'can-stache';
const renderer = stache(' world');
const viewModel = {greeting: 'Hello'};
const fragment = renderer(viewModel);
console.log(fragment.textContent);// Logs “Hello world”

Components

The concept that ties all of these things together is a component (or custom element). Components are useful for grouping functionality together and making things reusable across your entire app.

In CanJS, a can-component is made up of a view (can-stache file), a view-model (can-define/map/map), and (optionally) an object that can listen for JavaScript events.

import Component from 'can-component';
import DefineMap from 'can-define/map/map';
import stache from 'can-stache';

const HelloWorldViewModel = DefineMap.extend('HelloWorldVM', {
  greeting: {value: 'Hello'},
  showExclamation: {value: true}
});

Component.extend({
  tag: 'hello-world',
  view: stache(' world!'),
  ViewModel: HelloWorldViewModel,
  events: {
    '{element} click': () => {
      this.viewModel.showExclamation = !this.viewModel.showExclamation;
    }
  }
});

const template = stache('hello-world');
document.body.appendChild(template);

In the example above, our template will either show “Hello world!” or just “Hello world” (no exclamation mark), depending on whether the user has clicked our custom element.

These four concepts are all you need to know to build a CanJS app! Our example app will use these four ideas to build a full-fledged MVVM app.

Prerequisites for this tutorial

Before getting started, install a recent version of Node.js. We’ll use npm to install a backend server that will handle the communication with GitHub’s API.

Additionally, if you don’t already have a GitHub account, sign up for one.

Set up our local project

Let’s start by creating a new directory for our project and switching to that new directory:

mkdir canjs-github
cd canjs-github

Now let’s create the files we’ll need for our project:

touch app.css app.js index.html

We’ll use app.css for our styles, app.js for our JavaScript, and index.html for the user interface (UI).

CanJS Hello World

Let’s get coding! First, we’re going to add this to our index.html file:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>CanJS GitHub Issues To-Do List</title>
  <link rel="stylesheet" href="http://ift.tt/2apRjw3">
  <link rel="stylesheet" href="app.css">
</head>
<body>

<script type="text/stache" id="app-template">
  <div class="container">
    <div class="row">
      <div class="col-md-8 col-md-offset-2">
        <h1 class="page-header text-center">
          
        </h1>
      </div>
    </div>
  </div>
</script>

<script type="text/stache" id="github-issues-template">
</script>

<script src="http://ift.tt/2rOgv46"></script>
<script src="http://ift.tt/2dsPzTA"></script>
<script src="http://ift.tt/2rO6rby"></script>
<script src="/http://ift.tt/1aeIZU4"></script>
<script src="app.js"></script>
</body>
</html>

This has a bunch of different parts, so let’s break it down:

  • The two link elements in the head are the stylesheets for our project. We’re using Bootstrap for some base styles and we’ll have some customizations in app.css
  • The first script element (with id="app-template") contains the root template for our app
  • The second script element (with id="github-issues-template") will contain the template for the github-issues component we will create later in this tutorial
  • The script elements at the end of the page load our dependencies: jQuery, jQuery UI, CanJS, Socket.io, and our app code

In our app, we’ll use jQuery UI (which depends on jQuery) to sort the issues with drag and drop. We’ve included can.all.js so we have access to every CanJS module; normally, you would want to use a module loader like StealJS or webpack, but that’s outside the scope of this article. We’ll use Socket.io to receive events from GitHub to update our app in real-time.

Next, let’s add some styles to our app.css file:

form {
  margin: 1em 0 2em 0;
}

.list-group .drag-background {
  background-color: #dff0d8;
}

.text-overflow {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

Lastly, let’s add some code to our app.js file:

var AppViewModel = can.DefineMap.extend('AppVM', {
  pageTitle: {
    type: "string",
    value: "GitHub Issues",
  }
});

var appVM = new AppViewModel();
var template = can.stache.from('app-template');
var appFragment = template(appVM);
document.body.appendChild(appFragment);

Let’s break the JavaScript down:

  • can.DefineMap is used for declaring custom observable object types
  • AppViewModel is the observable object type that will serve as the root view-model for our app
  • pageTitle is a property of all AppViewModel instances that defaults to the value GitHub Issues
  • appVM is a new instance of our app’s view-model
  • can.stache.from converts the contents of a script tag into a function that renders the template
  • appFragment is a document fragment of the rendered template with the appVM data
  • document.body.appendChild takes a DOM node and appends it to the HTML body

Continue reading %How to Build a Real-Time GitHub Issue To-Do List with CanJS%


by Chasen Le Hara via SitePoint

Daniel Givens

Daniel Givens

Unique, brutalist One Page portfolio for designer Daniel Givens featuring an interactive "spray can effect" controlled by your cursor movements.

by Rob Hope via One Page Love

Hello, Laravel? Communicating with PHP through Phone Calls!

Vector icon of smartphone with weather icon overlay

Twilio is a SaaS application which enables developers to build telephone applications using web technologies. In this two-part series, we will leverage Twilio to build a weather forecast app that is accessed using the telephone system. The backend will be written with the Laravel framework (an exploratory video course is available for purchase here, or in the form of written tutorials here).

In this part, we will create a simple program that will allow a user to call a phone number that we buy from Twilio, enter a zipcode, and receive the current weather forecast. The user can also get the weather for any day of the week via the voice menu prompts. In the second part of this series, we will leverage what was built in this article to allow the user to interact with the app via SMS (text message).

Prerequisites

Development Environment

This article assumes Homestead Improved is installed. It is not necessary to use it, but the commands might differ slightly if you use a different environment. If you are not familiar with Homestead and want to produce similar results as this article aims to produce, please visit this SitePoint article that shows how to set up Homestead, and if you need a crash course in Vagrant, please see this post. Additionally, if this whets your appetite and you feel like exploring PHP development environments in depth, we have a book about that available for purchase.

Dependencies

We will create a new Laravel project and then add the Twilio PHP SDK and Guzzle HTTP client library to the project:

cd ~/Code
composer create-project --prefer-dist laravel/laravel Laravel 5.4.*
cd Laravel
composer require "twilio/sdk:^5.7"
composer require "guzzlehttp/guzzle:~6.0"

Development

Let's go through all the steps, one by one.

Routes

Open up the routes/web.php file and add the following ones:

Route::group(['prefix' => 'voice', 'middleware' => 'twilio'], function () {
    Route::post('enterZipcode', 'VoiceController@showEnterZipcode')->name('enter-zip');

    Route::post('zipcodeWeather', 'VoiceController@showZipcodeWeather')->name('zip-weather');

    Route::post('dayWeather', 'VoiceController@showDayWeather')->name('day-weather');

    Route::post('credits', 'VoiceController@showCredits')->name('credits');
});

In this app, all requests will be under the /voice path. When Twilio first connects to the app, it will go to /voice/enterZipcode via HTTP POST. Depending on what happens in the telephone call, Twilio will make requests to other endpoints. This includes /voice/zipcodeWeather for providing today's forecast, /voice/dayWeather, for providing a particular day's forecast, and /voice/credits for providing information on where the data came from.

Service Layer

We are going to add a service class. This class will hold a lot of the business logic that will be shared between the voice telephone app and the SMS app.

Create a new sub-folder called Services inside the app folder. Then, create a file called WeatherService.php and put the following content into it:

<?php

namespace App\Services;

use Illuminate\Support\Facades\Cache;
use Twilio\Twiml;

class WeatherService
{
}

This is a large file in the project, so we will build it piece by piece. Put the following pieces of code in this section inside our new service class:

    public $daysOfWeek = [
        'Today',
        'Sunday',
        'Monday',
        'Tuesday',
        'Wednesday',
        'Thursday',
        'Friday',
        'Saturday'
    ];

We will use this array to map a day of the week to a number; Sunday = 1, Monday = 2, etc.

    public function getWeather($zip, $dayName)
    {

        $point = $this->getPoint($zip);
        $tz = $this->getTimeZone($point);
        $forecast = $this->retrieveNwsData($zip);
        $ts = $this->getTimestamp($dayName, $zip);

        $tzObj = new \DateTimeZone($tz->timezoneId);

        $tsObj = new \DateTime(null, $tzObj);
        $tsObj->setTimestamp($ts);

        foreach ($forecast->properties->periods as $k => $period) {
            $startTs = strtotime($period->startTime);
            $endTs = strtotime($period->endTime);

            if ($ts > $startTs and $ts < $endTs) {
                $day = $period;
                break;
            }
        }

        $response = new Twiml();

        $weather = $day->name;
        $weather .= ' the ' . $tsObj->format('jS') . ': ';
        $weather .= $day->detailedForecast;

        $gather = $response->gather(
            [
                'numDigits' => 1,
                'action' => route('day-weather', [], false)
            ]
        );

        $menuText = ' ';
        $menuText .= "Press 1 for Sunday, 2 for Monday, 3 for Tuesday, ";
        $menuText .= "4 for Wednesday, 5 for Thursday, 6 for Friday, ";
        $menuText .= "7 for Saturday. Press 8 for the credits. ";
        $menuText .= "Press 9 to enter in a new zipcode. ";
        $menuText .= "Press 0 to hang up.";

        $gather->say($weather . $menuText);

        return $response;
    }

The getWeather method takes a zipcode with the day of the week and crafts the text of a weather forecast. First, it figures out the reference time for the day requested, and then looks up the weather forecast by doing a foreach over the array of forecast data. After that, it returns a Voice TwiML response. Below is a sample of what is returned:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Gather numDigits="1" action="/voice/dayWeather">
    <Say>
      This Afternoon the 31st: Sunny, with a high near 72. South southwest wind around 8 mph. Press 1 for Sunday, 2 for Monday, 3 for Tuesday, 4 for Wednesday, 5 for Thursday, 6 for Friday, 7 for Saturday. Press 8 for the credits. Press 9 to enter in a new zipcode. Press 0 to hang up.
    </Say>
  </Gather>
</Response>

The <Gather> tag tells Twilio to expect input from the user's keypad. The numDigits attribute says how many digits to expect. The action attribute says what endpoint to contact next.

    protected function retrieveNwsData($zip)
    {
        return Cache::remember('weather:' . $zip, 60, function () use ($zip) {
            $point = $this->getPoint($zip);

            $point = $point->lat . ',' . $point->lng;
            $url = 'http://ift.tt/2siEbBl' . $point . '/forecast';

            $client = new \GuzzleHttp\Client();

            $response = $client->request('GET', $url, [
                'headers' => [
                    'Accept' => 'application/geo+json',
                ]
            ]);

            return json_decode((string)$response->getBody());
        });
    }

The retrieveNwsData method gets the weather forecast data. First, the method checks to see if a copy of the zipcode's weather forecast is in cache. If not, then the Guzzle HTTP client is used to make an HTTP GET request to the National Weather Service's (NWS) API endpoint http://ift.tt/2siJ4Kk. To get the geographic point of the zipcode, a call is made to the getPoint method before doing the request to the weather API. The response from the API endpoint is the weather forecast in GeoJSON format. The forecast is for every day and night for a week (with some exceptions we will discuss later); 14 entries in all. We cache the API response for an hour because making the request is slow, plus we do not want to hit the government servers too frequently and get banned.

    protected function getPoint($zip)
    {
        return Cache::remember('latLng:' . $zip, 1440, function () use ($zip) {
            $client = new \GuzzleHttp\Client();
            $url = 'http://ift.tt/1p5neFv';

            $response = $client->request('GET', $url, [
                'query' => [
                    'postalcode' => $zip,
                    'countryBias' => 'US',
                    'username' => env('GEONAMES_USERNAME')
                ]
            ]);

            $json = json_decode((string)$response->getBody());

            return $json->postalCodes[0];
        });
    }

The getPoint method maps a zipcode to a geographic point. This is done by using the GeoNames API. The results are cached for a day because using the API is slow.

    protected function getTimeZone($point)
    {
        $key = 'timezone:' . $point->lat . ',' . $point->lng;

        return Cache::remember($key, 1440, function () use ($point) {
            $client = new \GuzzleHttp\Client();
            $url = 'http://ift.tt/1C9XM7m';

            $response = $client->request('GET', $url, [
                'query' => [
                    'lat' => $point->lat,
                    'lng' => $point->lng,
                    'username' => env('GEONAMES_USERNAME')
                ]
            ]);

            return json_decode((string) $response->getBody());
        });
    }

The getTimeZone method is used to get the timezone that a geographic point resides inside. The GeoNames API is also used and the results are cached for a day for the same reasons.

Continue reading %Hello, Laravel? Communicating with PHP through Phone Calls!%


by Christopher Thomas via SitePoint

The UX of the Zombie Scroller (and How to Cure It)

If you work on the web, you probably already understand that most readers don't diligently read every word of your content. Instead, they begin by scanning across it almost unconsciously – similar to the way you might scan passing food labels in a supermarket aisle.

Why do we scan?

Simple. We scan because it demands much less mental effort and we prefer to save our focus for the important stuff. We ‘skim across’ content until we find something that really captures out attention – when we activate our “slow thinking”.

The supermarket is a classic example of a place where we scan. Our eyes might take in 50 different varieties of pasta sauce without properly reading any of the labels.

However, when we turn on our “slow, focused thinking” – perhaps reading the ingredients on a sauce jar – our brain starts consuming a lot more mental energy – which is a limited resource.

Introducing 'Focus Points'

So, let’s gamify this idea and call this brain energy 'Focus Points (FP)'. The more focus points we spend, the more tired we feel and the more our thinking power weakens.

When a user scans a long page of content, they are spending these 'focus points' each time they pay attention to pieces of content they find interesting. The longer they scroll, the more fatigued they get.

Of course, this means the content offerings they discover further down the page get less attention. Like trying to entice a shopper with an overstuffed trolley, they simply have less 'FPs' left to spend. Therefore even high-quality content options become less visible and engaging. We call this phenomenon a scrolling fatigue.

Let's draw some lines to visualize all this focus economy. If you are scanning a content without committing any effort, you just gradually burning your focus until you get tired and eventually quit.

[caption id="attachment_155906" align="aligncenter" width="800"]Chart: Focus vs scroll distance Chart: Focus vs scrolling distance. A smooth decrease.[/caption]

However, if you engage with the content without any 'reward', you just spend a bunch of focus points on a spot. For example, if you actively engage in each story in your social media feed, your brain will shut down just after a few meaningful interactions.

[caption id="attachment_155907" align="aligncenter" width="800"]Chart: Focus vs Scrolling distance. Interactions demand mental energy. Chart: Focus vs Scrolling distance. Interactions demand mental energy.[/caption]

Readability and Focus

Another factor you should keep in mind is readability. If your content is hardly readable, it requires more effort to digest, burning focus points faster. So unless you intentionally want to hurt your users, don't make your list difficult and expose only essential information. Do you really need the publish date? Do you need the topic on every listing?

[caption id="attachment_155908" align="aligncenter" width="800"]Chart: Focus vs Scroll distance Chart: Focus vs Scroll distance. Increased readability translates to longer average engaged scrolls.[/caption]

Rage-quits and Zombies

[caption id="at" align="alignright" width="400"]Zombie Day 6 - Bifff 2012 Eddie Berthier @didyPhotography http://ift.tt/2rNmK8i Very long scrolling pages are bad for you.[/caption]

Generally, as users move into the zone of scrolling fatigue, their brain becomes less susceptible to standard hooks and reward mechanisms (the curve of focus points drops exponentially). This automatically lowers any motivation to put any effort into digesting information end eventually they quit.

It's almost as if scrolling fatigued users become zombified. To avoid this situation we have to minimize the consumption of focus points.

How Does Fatigue Impact on Different Types of Content Collections

If you are designing a large content collection with large scroll range - you also face fatigue problem. You must expose as much content as possible at the same time keep your users conscious enough to engage it.

To understand how to deal with this, you should know how users scan different list layouts. Let’s get a little bit practical here. Today, there are three main types of content lists:

[caption id="attachment_155909" align="aligncenter" width="891"]Three grid types Three grid types[/caption]

Linear lists

The most natural and common way to display chunks of content is just put them into rows. Google search results and eBay listings fit this classic pattern. Linear lists are the easiest to scan, it's hard to miss any content item and users can compare items side-by-side because they are all aligned together.

The downside of linear lists tends to be mostly aesthetic. Typically they take more space and can be visually boring (and I’m not talking about Excel here).

Classic Grids

The second most common option is to place your items in a 2D grid. This is a brilliant way to squeeze more content into the viewport – especially if your content is more graphical than text. Photo galleries and shopping sites love this pattern.

And this is perfectly fine – until you need your users to pay attention to every item. Since scanning a grid pattern is much more demanding than a linear list, you will burn through your user's focus points more quickly. Also, after a short time, users will typically start skipping chunks of content and your grid usability will fail.

The Masonry Grid

Masonry grids are a variation on the classic grid – but with much more unit-size variation. Many would argue that the Masonry grid is the most aesthetically pleasing way to display graphical content. It lets you tile the entire viewport and makes each content item a different size. Pinterest is probably the most famous Masonry grid layout, but you'll find masonry widely-used in mood boards and showcases.

However, on the downside, it is pure visual chaos. It has no obvious visual order and no clear eye lead pattern. So if you are trying to use masonry to represent some kind of IA structure, you will likely just end up confusing your users.

Continue reading %The UX of the Zombie Scroller (and How to Cure It)%


by Petras Baukys via SitePoint

RedDraft

RedDraft

Long scrolling One Page portfolio for web designer, Ricardo Garcia. Quite like his contour-scroller background effect against the icon animations in the experience section.

by Rob Hope via One Page Love

Faygo Call It Pop

http://ift.tt/2tk6jCg

Fun marketing idea by Faygo using a One Page website to promote and gather people's pledges to call carbonated beverages "Pop".

by Rob Hope via One Page Love