<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jellene Khoh</title>
    <description>The latest articles on Forem by Jellene Khoh (@jellene4eva).</description>
    <link>https://forem.com/jellene4eva</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F148002%2F8260d32d-3f9a-464d-ac87-8f13ec2831fd.jpeg</url>
      <title>Forem: Jellene Khoh</title>
      <link>https://forem.com/jellene4eva</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jellene4eva"/>
    <language>en</language>
    <item>
      <title>Docker Alpine + ExpressJS + Angular</title>
      <dc:creator>Jellene Khoh</dc:creator>
      <pubDate>Tue, 09 Apr 2019 13:58:05 +0000</pubDate>
      <link>https://forem.com/jellene4eva/docker-alpine-expressjs-angular-3l16</link>
      <guid>https://forem.com/jellene4eva/docker-alpine-expressjs-angular-3l16</guid>
      <description>&lt;p&gt;This was for a project that I did recently that required a reporting dashboard app to be served from a docker image, and would live inside small low-powered linux devices.&lt;/p&gt;

&lt;p&gt;The app had to fulfill these criterias:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; It needs to be replicated quickly for many devices&lt;/li&gt;
&lt;li&gt; It needs to be small, there isn't a lot of space&lt;/li&gt;
&lt;li&gt; It needs to be able to connect to MariaDB database in the localhost network&lt;/li&gt;
&lt;li&gt; Certain fields are configurable from a JSON database that is exposed outside the container.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FjRzKPHWUSAKkdtTPETu6" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FjRzKPHWUSAKkdtTPETu6" alt="IMG_20190408_153056.jpg"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Docker container containing an ExpressJS app that serves an Angular app&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;1. It needs to be replicated quickly for many devices&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Docker has been around for a considerable time already, released on &lt;a href="https://www.infoq.com/news/2013/03/Docker" rel="noopener noreferrer"&gt;2013&lt;/a&gt;, it aims to solve the problem of "But it works on my computer".&lt;/p&gt;

&lt;p&gt;A popular use of docker is to pair it with kubernetes to spin up multiple microservices to handle large spikes of concurrent users, and then remove them after the spike to save resources. Each microservice is a tiny server on its own.&lt;/p&gt;

&lt;p&gt;Since docker images are essentially like a backup copy of a tiny server, it will always run the same way without much configuration. Which makes it easy to copy the image to any new device, and spin up a new docker container running the app.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture Solution
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; Use Docker to containerize the app&lt;/li&gt;
&lt;li&gt; ExpressJS serves as a web server for the frontend Angular app.&lt;/li&gt;
&lt;li&gt; ExpressJS uses &lt;a href="https://github.com/typicode/lowdb" rel="noopener noreferrer"&gt;lowdb&lt;/a&gt; to read/write configurations to a JSON file in a folder called data/.&lt;/li&gt;
&lt;li&gt; ExpressJS uses &lt;a href="https://knexjs.org/" rel="noopener noreferrer"&gt;knex.js&lt;/a&gt; to query SQL database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The final work folder looks something like this –&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    backend/
        |- src/...
        |- dist/
            |- server.min.js
    frontend/
        |- src/...
        |- dist/
            |- public/
                |- main.min.js
                |- vendor.min.js
                |- index.html
    docker/
        |- data/
            |- local-db.json
        |- server.min.js
        |- package.json
        |- public/
            |- main.min.js
            |- vendor.min.js
            |- index.html
        |- Dockerfile
        |- .dockerignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both frontend and backend is minimized to reduce space. The contents of the the minimized code is copied to the docker folder so that it is easier for me to pack it into a docker image.&lt;/p&gt;

&lt;p&gt;Express server is serving the public folder (Angular app) under root route. While the rest of the API starts with &lt;code&gt;/api/&lt;/code&gt; prefix. This also means that Angular can use &lt;code&gt;/api&lt;/code&gt; when calling http, so it'll always call something in the same domain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;reportUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Package.json from the backend is included as well, because I need install the node_modules required for the ExpressJS app. It's probably possible to somehow bundle the dependencies using Webpack, but I was strapped for time and didn't investigate further how to do so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;FileAsync&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lowdb/adapters/FileAsync&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lowdb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;low&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;maxEntries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MAXENTRIES&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will write a default JSON configuration to data/local-db.json.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dockerfile
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;2. It needs to be small, there isn't a lot of space&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A common practice during development is the throw all the source files into the docker container and run a full node.js server to serve your application. It's the easy, fast, painless.&lt;/p&gt;

&lt;p&gt;But a full node.js on debian server is quite big - nearly 650MB from the start. After installing our ExpressJS app and Angular it went to about 1.3GB.&lt;/p&gt;

&lt;p&gt;So we opted to go with the new barebone OS based on &lt;a href="https://alpinelinux.org/" rel="noopener noreferrer"&gt;Alpine&lt;/a&gt; linux, which is a huge 50MB. With everything installed, it came up to about 300MB. Still much smaller than the full server image.&lt;/p&gt;

&lt;p&gt;The full list of available node base images are &lt;a href="https://hub.docker.com/_/node/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A barebone OS means that we need some extra files in order to install the node modules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    FROM node:10.15.3-alpine

    ENV JWT_SECRET 512FF7B2EMCKAHG24C
    ENV BCRYPT_SALT 12
    ENV PORT 8080
    ENV TOKEN_EXPIRES_IN 24h

    WORKDIR /usr/src/app
    COPY . .
    RUN apk --no-cache add --virtual native-deps \
        bash g++ gcc libgcc libstdc++ linux-headers make python &amp;amp;&amp;amp; \
        npm install --quiet node-gyp forever -g &amp;amp;&amp;amp;\
        npm install --production --quiet
    EXPOSE 8080
    CMD forever server.min.js 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a very detailed &lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; on how to write a Dockerfile, but essentially a docker file is similar to a bash script that runs commands in sequence and finally serve the app.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FROM node:10.15.3-alpine&lt;/code&gt; is how I select the image as a base for the container.&lt;/p&gt;

&lt;p&gt;I'm setting environment variables with the &lt;code&gt;ENV&lt;/code&gt; command. Which can then be read in the ExpressJS app via &lt;code&gt;process.env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;WORKDIR&lt;/code&gt; selects the current folder I want to use IN the container. If no directory exist, Docker creates them.&lt;/p&gt;

&lt;p&gt;I include several installs (gcc, python etc) that is required for node to be built.&lt;/p&gt;

&lt;p&gt;And then finally serving &lt;code&gt;server.min.js&lt;/code&gt; with &lt;a href="https://github.com/foreverjs/forever" rel="noopener noreferrer"&gt;Forever&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Forever is a CLI tool that will run the node server as a daemon, and cannot be killed accidentally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker Run
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;3. It needs to be able to connect to MariaDB database in the localhost network&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now comes the fun part – running the app. First we must build it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    $ docker build --tag node-app:alpine .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker build reads the command from Dockerfile and builds an image.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--tag&lt;/code&gt; allows me to name the docker image, so that it's easier to find it later.&lt;/p&gt;

&lt;p&gt;After building, &lt;code&gt;docker images&lt;/code&gt; shows that I've indeed built an image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    $ docker images

    REPOSITORY     TAG          IMAGE ID         CREATED          SIZE
    node-app       alpine       f4ca2e0425a0     3 days ago       354MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to run the docker image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    $ docker run \
        --name node-app \
        --network host \
        --restart 'unless-stopped' \ 
        --detach \
        node-app:alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--name&lt;/code&gt; lets me set a custom name. If it's not provided, docker will create a name for you like precious-grauss or similar.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--restart&lt;/code&gt; will make the running container run forever unless specifically stopped.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--detach&lt;/code&gt; will make it run in the background, freeing up my terminal for other things. If you don't use this, you'll need a 2nd terminal to stop your docker container.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--network&lt;/code&gt; is the &lt;em&gt;key option&lt;/em&gt; here. One of the requirements is that the docker container should be able to connect to a database on localhost. And by using the option &lt;code&gt;host&lt;/code&gt;, we can do so. There are other methods of creating docker networks and connecting containers together. You can read more &lt;a href="https://docs.docker.com/network/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With this command, I am now able to see the app run on &lt;code&gt;localhost:8080&lt;/code&gt;. And my app is able to connect to the database successfully. 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FB920t0WCRs2gzdLGFOg6" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FB920t0WCRs2gzdLGFOg6" alt="giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker volume
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;4. Certain fields are configurable from a JSON database that is exposed outside the container.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The docker container should now be running smoothly, until, I find that the local-db json isn't really updated. And I'm not able to control the configuration from outside the container.&lt;/p&gt;

&lt;p&gt;That's because I left out the &lt;code&gt;--volume&lt;/code&gt; option during docker run that allows me to mount a folder unto docker, which can then be shared between host machine and the docker container. You can read more about data persistence in docker &lt;a href="https://docs.docker.com/storage/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    $ docker run \
        --name node-app \
        --volume $(pwd)/data:/usr/src/app/data \
        --network host \
        --restart 'unless-stopped' \ 
        --detach \
        node-app:alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$(pwd)&lt;/code&gt; will insert the current working directory into the command. If I were to call docker from a different folder, the pwd will be different.&lt;/p&gt;

&lt;p&gt;Here the volume command mounts the data folder to the data folder that exists inside the docker container &lt;code&gt;/usr/src/app/&lt;/code&gt; folder. If the target folder does not exist, &lt;code&gt;--volume&lt;/code&gt; will create it for me.&lt;/p&gt;

&lt;p&gt;Run this, and now I can control the configs from outside.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saving and Loading images
&lt;/h2&gt;

&lt;p&gt;Now that I have the image up and running. I need to export the image into a format I can import into different devices and start up the same instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    $ docker save -o ./node-app-image.tar node-app:alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;save&lt;/code&gt; command exports the current image state into a tarball. I make sure that I have not added any custom configuration, because I don't want them saved into the image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    $ docker load -i ./node-app-image.tar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then run the &lt;code&gt;load&lt;/code&gt; command after I have downloaded the tarball into the machine. Loading the image will include the image into &lt;code&gt;docker images&lt;/code&gt;. And then I do the &lt;code&gt;run&lt;/code&gt; command as before, and it should find the same &lt;code&gt;node-app:alpine&lt;/code&gt; image I saved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;p&gt;Docker is really quite powerful. It has let developers scale up apps instantly and confidently, because the environment will always be exactly the same.&lt;/p&gt;

&lt;p&gt;That said, I think the docker documentation can be a little easier to deal with. There is just such a huge amount of configuration to learn, it is no wonder docker setup is a career on its own.&lt;/p&gt;

&lt;p&gt;Regardless, learning docker is exciting. Let me know if there is a better way! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2F8L2FP8g0TSqfltStIKHN" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2F8L2FP8g0TSqfltStIKHN" alt="giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;[1] &lt;a href="https://github.com/nodejs/docker-node" rel="noopener noreferrer"&gt;https://github.com/nodejs/docker-node&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://github.com/nodejs/docker-node/issues/282" rel="noopener noreferrer"&gt;https://github.com/nodejs/docker-node/issues/282&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://stackoverflow.com/questions/43316376/what-does-net-host-option-in-docker-command-really-do" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/43316376/what-does-net-host-option-in-docker-command-really-do&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://stackoverflow.com/questions/12701259/how-to-make-a-node-js-application-run-permanently" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/12701259/how-to-make-a-node-js-application-run-permanently&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>angular</category>
      <category>express</category>
      <category>devops</category>
    </item>
    <item>
      <title>Fundamentals of UX</title>
      <dc:creator>Jellene Khoh</dc:creator>
      <pubDate>Mon, 01 Apr 2019 19:06:56 +0000</pubDate>
      <link>https://forem.com/jellene4eva/fundamentals-of-ux-5hn0</link>
      <guid>https://forem.com/jellene4eva/fundamentals-of-ux-5hn0</guid>
      <description>&lt;p&gt;&lt;small&gt;&lt;em&gt;Cover Photo by &lt;a href="https://unsplash.com/@halgatewood?utm_source=ghost&amp;amp;utm_medium=referral&amp;amp;utm_campaign=api-credit" rel="noopener noreferrer"&gt;Hal Gatewood&lt;/a&gt; / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;amp;utm_medium=referral&amp;amp;utm_campaign=api-credit" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;UX (user experience) is the answer to the question of "why" and "how". Why should we have this feature? Why is the button red? How do I look at my settings? Why is it so slow?&lt;/p&gt;

&lt;p&gt;Most of the time we associate UX to UI (user interface). But UI is only a small part of the larger picture. The user can also be a programmer, or a customer of a physical device. The main goal of UX design is to create a frictionless experience for the user&lt;a href="https://www.belatrixsf.com/blog/why-ux-design-is-so-important-in-agile-software-development/" rel="noopener noreferrer"&gt;[7]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The UX designer is usually an integral part of the agile development cycle between design and development, connecting good design, software development, and business goals into a wholesome and focused package. Software developers backend or frontend can benefit from UX knowledge.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Designers are the bridge between business and users, being this characteristic one of our strength. &lt;strong&gt;—&lt;/strong&gt; Diego Mazo &lt;a href="https://medium.com/strategic-design-lab/what-a-strategic-designer-does-b942f295379" rel="noopener noreferrer"&gt;[2]&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The folks at UX Collective asked the community what skills are needed as a UX designer. These are the 5 skills&lt;a href="https://uxdesign.cc/what-does-it-take-to-become-an-experience-design-expert-eba0e0d588eb" rel="noopener noreferrer"&gt;[1]&lt;/a&gt; they think are required to be an expert in UX design: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;Visual Design:&lt;/em&gt;&lt;/strong&gt; Do you know the fundamentals design patterns and Gestalt principles?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;Business alignment skills:&lt;/em&gt;&lt;/strong&gt; Can you communicate the business value of your design work and tie it into the overall goals of the company?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;Research:&lt;/em&gt;&lt;/strong&gt; Can you collect actionable insights from customers and users through strategic (are you solving the right problems) &amp;amp; tactical research (are your designing the right solutions)?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;Organization &amp;amp; Communication&lt;/em&gt;&lt;/strong&gt;: Are you able efficiently convey your message both in terms of information architecture and content?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;Technical:&lt;/em&gt;&lt;/strong&gt; Can you code whatever you had visually designed? Make a simple prototype?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Today we're going to look at the visual part (or UI) of UX design. These are a few laws and principles that we as software developers can follow to increase usability of our app.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Gestalt's Theory&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
‌User's tendency to visually categorize by scanning, not reading&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Jakob's Law&lt;/em&gt;‌&lt;/strong&gt;&lt;br&gt;
‌User prefer websites that work the same way&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Fitts's Law&lt;/em&gt;‌&lt;/strong&gt;&lt;br&gt;
‌Increase size of important action buttons&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Hick's Law&lt;/em&gt;‌&lt;/strong&gt;&lt;br&gt;
‌Less option is better&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Miller's Law&lt;/em&gt;‌&lt;/strong&gt;&lt;br&gt;
‌We can only effectively remember up to 7 elements at once&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Endowed Progress Effect&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
‌Progress bar make users finish the task&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Doherty's Threshold&lt;/em&gt;‌&lt;/strong&gt; &lt;br&gt;
‌Things need to happen &amp;lt;400ms to keep attention span&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Hand gesture design&lt;/em&gt;‌&lt;/strong&gt;&lt;br&gt;
‌Mobile first design &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;‌&lt;/p&gt;




&lt;p&gt;‌&lt;/p&gt;

&lt;h2&gt;
  
  
  Gestalt's Theory
&lt;/h2&gt;

&lt;p&gt;Gestalt's Theory is a pyschological concept from 1890s that explores the way how people perceives information and using them to build good navigation, digestible copy, and effective color choice that has a great impact on the usability of the product&lt;a href="https://tubikstudio.com/gestalt-theory-for-efficient-ux-principle-of-similarity/" rel="noopener noreferrer"&gt;[3]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Modern UX patterns uses principles of Gestalt's Theory one way or the other. By knowing the factors influencing visual perception, you can design the UI as to lower the level of misunderstandings users could perceive from the software. &lt;a href="https://tubikstudio.com/gestalt-theory-for-efficient-ux-principle-of-similarity/" rel="noopener noreferrer"&gt;[3]&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;

&lt;h3&gt;
  
  
  #1: Figure-ground Principle
&lt;/h3&gt;

&lt;p&gt;The figure-ground principle states that  if the visual field is homogeneous throughout, and there is a figure of a different color, &lt;strong&gt;there is a tendency to see the figure as positioned in front&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;This is most apparent in the "card" system design whereby we insert important fields in white boxes to bring it to the front. Generally we do not want to go beyond 2-3 layers of foreground-background, or else it gets too "tall". &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“White space is to be regarded as an active element, not a passive background.” _— Jan Tschichold&lt;/em&gt;_ &lt;a href="https://www.smashingmagazine.com/2014/05/design-principles-space-figure-ground-relationship/" rel="noopener noreferrer"&gt;[8]&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2F1PQ59BxRtSp2apHoKPJg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2F1PQ59BxRtSp2apHoKPJg" alt="image-4.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;White cards make it standout from the background. &lt;a href="https://gumroad.com/discover?query=app" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;I would also say that having a separate color for call-to-action (CTA) buttons also brings it out to the foreground. It projects a more &lt;em&gt;positive&lt;/em&gt; action. This effect is also called the &lt;a href="https://en.wikipedia.org/wiki/Von_Restorff_effect" rel="noopener noreferrer"&gt;&lt;strong&gt;The Von Restorff&lt;/strong&gt;&lt;/a&gt; effect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FmXvjPyTHTNSq9OR6Qq7d" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FmXvjPyTHTNSq9OR6Qq7d" alt="image-12.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;The accept button is usually colored to make it stand out. &lt;a href="https://www.tumblr.com/dashboard" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;

&lt;h3&gt;
  
  
  #2: Similarity Principle
&lt;/h3&gt;

&lt;p&gt;The principle of similarity states that &lt;strong&gt;we tend to group things together when they look similar&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FHzom6V9TDhr2rYKMgQCg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FHzom6V9TDhr2rYKMgQCg" alt="image-11.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;When items have the same color, we tend to group that together. &lt;a href="http://vanseodesign.com/web-design/gestalt-principles-of-perception/" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;We can use that in chat boxes to separate who is talking. Using colors to separate ownership is an easy way to utilize this principle. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FK7tbs98mTuq9HhaYYU7s" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FK7tbs98mTuq9HhaYYU7s" alt="image-6.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;You can clearly see the blue speech are your own. &lt;a href="https://www.sketchappsources.com/free-source/2649-facebook-like-chatbox-sketch-freebie-resource.html" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;

&lt;h3&gt;
  
  
  #3: Proximity Principle 
&lt;/h3&gt;

&lt;p&gt;The principle of proximity states that &lt;strong&gt;things that are close together appear as forming a group&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FLo4U1zRSZy7cABsKNuPo" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FLo4U1zRSZy7cABsKNuPo" alt="image-7.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;We instinctively group them by how close the group are to each other. &lt;a href="http://vanseodesign.com/web-design/gestalt-principles-of-perception/" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FHkD2pEsQJ2sL6PKZsw5W" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FHkD2pEsQJ2sL6PKZsw5W" alt="image-10.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;The distance between the elements group them into separate items. &lt;a href="https://angel.co" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Whitespace between elements are very powerful. It's like a table with invisible lines, but much cleaner than using lines to separate elements in a grid format. &lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;

&lt;h3&gt;
  
  
  #4: Common Fate Principle 
&lt;/h3&gt;

&lt;p&gt;The principle of common fate states that &lt;strong&gt;when objects act or move the same way, we perceive them as being grouped together&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/7tZp9KvLm5GKs/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/7tZp9KvLm5GKs/giphy.gif"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;&lt;a href="https://giphy.com/gifs/animations-ui-mobile-7tZp9KvLm5GKs" rel="noopener noreferrer"&gt;via GIPHY&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/wU5e48vZIVRNS/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/wU5e48vZIVRNS/giphy.gif"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;&lt;a href="https://giphy.com/gifs/top-ios-ipad-wU5e48vZIVRNS" rel="noopener noreferrer"&gt;via GIPHY&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Using animation we can indicate a new page, or pop over menu. It's a good way to introduce new UI elements if you move them into the page together. &lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;

&lt;h3&gt;
  
  
  #5: Continuity Principle 
&lt;/h3&gt;

&lt;p&gt;The principle of continuity states that &lt;strong&gt;elements that are arranged on a line are perceived to be more related than elements that are not.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FzqlCY4eBRkq0qTr9OqSV" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FzqlCY4eBRkq0qTr9OqSV" alt="image-14.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;We group items based on alignment. &lt;a href="https://marvelapp.com/pricing" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FKii8h0k6T7Kuf9cNS8Xq" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FKii8h0k6T7Kuf9cNS8Xq" alt="image-18.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Horizontal alignment also indicate that the plus button is for adding the blog somewhere. &lt;a href="https://www.tumblr.com/dashboard" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Aside from indicating groups, aligning elements in the page together helps give the sense of togetherness. As humans, we find symmetry and orderliness pleasing, even on a subconscious level. &lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;

&lt;h3&gt;
  
  
  #6: Closure Principle 
&lt;/h3&gt;

&lt;p&gt;The principle of closure states that &lt;strong&gt;we can fill in the missing information when elements in a composition are aligned in such a way that the viewer perceives that "the information could be connected."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FMsVKq7Y7ROeSBYGndmOW" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FMsVKq7Y7ROeSBYGndmOW" alt="image-20.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Notification badges implies that we have number of items associated with the link. &lt;a href="https://www.telerik.com/support/kb/winforms/buttons/details/notification-button" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FZZmFrPEWRWOKNxYv5hv0" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FZZmFrPEWRWOKNxYv5hv0" alt="image-19.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;We can guess that the action buttons below relates to Property Taxes, and not Rent. &lt;a href="https://dribbble.com/shots/2766291-Invoice-Notifications-Bank-app-mockups/attachments/563703" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Icons and badges are good examples where users generally can connect what the icon means, to a function that it might trigger. &lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;

&lt;h3&gt;
  
  
  #7: Simplicity principle
&lt;/h3&gt;

&lt;p&gt;This principle implies that as individuals perceive the world, &lt;strong&gt;they eliminate complexity and unfamiliarity so they can observe a reality in its most simplistic form.&lt;/strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Gestalt_psychology" rel="noopener noreferrer"&gt;[4]&lt;/a&gt;&lt;a href="http://vanseodesign.com/web-design/gestalt-principles-of-perception/" rel="noopener noreferrer"&gt;[5]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I take this to mean general composition of the elements in the page. When users scan the page, they see large chunks of sections so that they can navigate with ease.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FNFdjCgwyQP60UBN514bF" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FNFdjCgwyQP60UBN514bF" alt="image-22.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Ember's landing page separated to several parts. &lt;a href="https://www.emberjs.com/" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;We can see here in Ember's landing page that there are clearly separated parts in the page. Each part has its own principle to tie it together, but on a larger scale, they also connect to each other. &lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;

&lt;h3&gt;
  
  
  #8 Past experience principle
&lt;/h3&gt;

&lt;p&gt;This principle implies that elements &lt;strong&gt;tend to be grouped together if they were often together in the past.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using green to indicate &lt;em&gt;positive&lt;/em&gt;, and red to indicate &lt;em&gt;negative&lt;/em&gt;, is one way to immediately project association to the action. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FxNJBm0koQ82Nn0122lIE" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FxNJBm0koQ82Nn0122lIE" alt="image-24.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Red usually means irreversible damage. &lt;a href="https://ux.stackexchange.com/questions/49991/should-yes-delete-it-be-red-or-green" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;This can also be explained with &lt;strong&gt;Germane Cognitive Load&lt;/strong&gt;: whereby it’s easier for the users to recognize and learn something new if they can discern it into a pattern from something they already understand. &lt;a href="https://blog.marvelapp.com/psychology-principles-every-uiux-designer-needs-know/" rel="noopener noreferrer"&gt;[6]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FiGY33wsDSKqQuHhNkvO6" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FiGY33wsDSKqQuHhNkvO6" alt="image-25.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Expandable content indicated by the arrow. &lt;a href="https://www.impactbnd.com/blog/laws-of-ux-infographic" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;From the chevron arrows, we recognize that it seems to be a box that can be toggled to expand. We can reuse patterns like these so that users immediately know how to use the app. This is very similar to the next point - Jakob's Law.&lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;




&lt;p&gt;‌&lt;/p&gt;

&lt;h2&gt;
  
  
  Jakob's Law
&lt;/h2&gt;

&lt;p&gt;Jakob's Law is coined by Jakob Nielson. It states that &lt;strong&gt;users prefer your site to work the same way as all the other sites they already know.&lt;/strong&gt; &lt;a href="https://lawsofux.com/jakobs-law" rel="noopener noreferrer"&gt;[11]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FKHWAY26WQlycz0LNju0F" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FKHWAY26WQlycz0LNju0F" alt="image-30.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Input for Whatsapp, Telegram, and Facebook messenger&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;We are all familiar with chat apps. And users expect that their chat app will be a box in the bottom, with a text box, and some option for inserting emojis. It can be in a totally different language, and still users know where to find it. &lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;




&lt;p&gt;‌&lt;/p&gt;

&lt;h2&gt;
  
  
  Fitts's Law 
&lt;/h2&gt;

&lt;p&gt;Fitts's law is the amount of time required for a person to move a pointer to the desired button (e.g. CTA) &lt;strong&gt;decreases&lt;/strong&gt; with larger &lt;strong&gt;size&lt;/strong&gt; and shorter &lt;strong&gt;distance&lt;/strong&gt;&lt;a href="https://www.interaction-design.org/literature/topics/fitts-law" rel="noopener noreferrer"&gt;[9]&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In other words, the action button should be made larger, and the distance between a user’s task/attention area and the task-related button should be kept as short as possible. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FHvke0a3CRoCVihXzMd6e" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FHvke0a3CRoCVihXzMd6e" alt="image-28.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;User eye movement heatmap. &lt;a href="https://www.researchgate.net/figure/The-F-Pattern-heat-map-in-reading-webpages-Nielsen-2006b_fig1_321859889" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Research has established that the user scans the website in an "F" pattern, starting from the top left, and forms an opinion about the website within 50 ms&lt;a href="https://www.researchgate.net/figure/The-F-Pattern-heat-map-in-reading-webpages-Nielsen-2006b_fig1_321859889" rel="noopener noreferrer"&gt;[10]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FbRem90DTl6VX0mnjR5gy" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FbRem90DTl6VX0mnjR5gy" alt="image-27.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Everything is on the top left. Compose being the largest button. &lt;a href="https://mail.google.com/mail/u/0/#inbox" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Google made this work by placing the most prominent feature of Gmail on the top left in a big white button. And to the right is the email list. Immediately the user finds the most important feature gmail has to offer. Also, many of the filtering buttons are close to each other. &lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;




&lt;p&gt;‌&lt;/p&gt;

&lt;h2&gt;
  
  
  Hick's Law
&lt;/h2&gt;

&lt;p&gt;Hick's Law is the time it takes for a person to make a decision &lt;strong&gt;decreases&lt;/strong&gt; as a result of the &lt;strong&gt;lesser&lt;/strong&gt; possible choices they have. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FT8ZQlIXTQ96lcF06C1M4" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FT8ZQlIXTQ96lcF06C1M4" alt="image-29.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Amazon Web Services UI improves by reducing options per page. &lt;a href="https://aws.amazon.com/products/" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;We can see how Amazon greatly improved their UI by grouping their services by smaller groups, thus having &lt;em&gt;less&lt;/em&gt; options to choose per page. &lt;/p&gt;

&lt;p&gt;Another business related use of this concept is in pricing. When given too many pricing option, users are left confused and unable to make a decision. Having lesser options increases the time to make a decision. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FHfbFZe9dTOOLGCRgj6f9" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FHfbFZe9dTOOLGCRgj6f9" alt="image-31.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Firebase has only 3 tier pricing for their services. &lt;a href="https://firebase.google.com/pricing/" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;




&lt;p&gt;‌&lt;/p&gt;

&lt;h2&gt;
  
  
  Miller's Law
&lt;/h2&gt;

&lt;p&gt;Miller's Law states that people can remember up to &lt;strong&gt;7 different elements&lt;/strong&gt; in their working memory, anything more will increase the percentage of errors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2Fu5oGEVZoSRy77HWB620U" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2Fu5oGEVZoSRy77HWB620U" alt="image-32.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Google Calendar shows approximately 7 items on the page at one time.&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;We can reduce the amount of item on the page to roughly 7. If it's too little, try breaking it up into smaller chunks of 7 or less. Subheadings, layers, borders, are some of the way to section your information. &lt;/p&gt;

&lt;p&gt;It's also a good idea to limit authentication code to less than 7 characters. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FlsAu39VuSa2YqA1MvFgb" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FlsAu39VuSa2YqA1MvFgb" alt="image-33.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Steam Guard code&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;I imagine it would be quite annoying if you had to fill in 20 character authentication code in 3 seconds. &lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;




&lt;p&gt;‌&lt;/p&gt;

&lt;h2&gt;
  
  
  Endowed Progress Effect
&lt;/h2&gt;

&lt;p&gt;Researcher Joseph C. Nunes documents the effect whereby &lt;strong&gt;people provided with artificial advancement toward a goal exhibit greater persistence toward reaching the goal.&lt;/strong&gt; &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.545.2322&amp;amp;rep=rep1&amp;amp;type=pdf" rel="noopener noreferrer"&gt;[13]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FeeXFYTcPQKW8iDQcw33Q" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FeeXFYTcPQKW8iDQcw33Q" alt="image-34.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;The classic windows progress bar. &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/controls/progress-bar-control" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;I'm sure everybody knows about the progress bar. But did you know many apps had to insert a fake progress bar, so that users feel better? &lt;a href="https://news.ycombinator.com/item?id=16289380" rel="noopener noreferrer"&gt;[14]&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Actual progress bars are probably harder to replicate in an async function, but there is a place where progress bars can help a lot — wizards. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2Fb8yf5LWPTtqAe8Uacokj" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2Fb8yf5LWPTtqAe8Uacokj" alt="image-35.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;Salesforce forms uses progress bar to guide users. &lt;a href="https://www.pardot.com/wp-content/help/uploads/2010/10/Screen-Shot-2013-01-14-at-2.29.03-PM.png" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Wizards break up the mundane process of data entry, it also gives users a sense of progress so that it feels like they're moving forward. &lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;




&lt;p&gt;‌&lt;/p&gt;

&lt;h2&gt;
  
  
  Doherty's Threshold
&lt;/h2&gt;

&lt;p&gt;In the age of fast internet, the worst sin is to have a slow app. Walter J. Doherty published a research paper in 1982 that set the &lt;strong&gt;requirement for computer response time is &amp;lt;400ms&lt;/strong&gt;. &lt;a href="https://lawsofux.com/doherty-threshold" rel="noopener noreferrer"&gt;[15]&lt;/a&gt; Any slower than that, the system is considered slow. &lt;/p&gt;

&lt;p&gt;Aside from the obvious optimization of the system, we can also employ a few tactics to slow the user down. &lt;/p&gt;

&lt;p&gt;We explored progress bars previously, it can help immensely to provide an immediate feedback. &lt;/p&gt;

&lt;p&gt;Another way is to run processes in the background. For example deleting an email might remove the item from the screen immediately, but the actual &lt;code&gt;DELETE&lt;/code&gt; call can be run in the background so that users perceive it as fast. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/26AHumw7ezGDRpYmk/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26AHumw7ezGDRpYmk/giphy.gif"&gt;&lt;/a&gt;&lt;br&gt;
&lt;sup&gt;&lt;em&gt;&lt;a href="https://media.giphy.com/media/26AHumw7ezGDRpYmk/giphy.gif" rel="noopener noreferrer"&gt;via GIPHY&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;




&lt;p&gt;‌&lt;/p&gt;

&lt;h2&gt;
  
  
  Hand Gesture Design
&lt;/h2&gt;

&lt;p&gt;There are nearly 5 billion phone users in 2019 &lt;a href="https://www.statista.com/statistics/274774/forecast-of-mobile-phone-users-worldwide/" rel="noopener noreferrer"&gt;[16]&lt;/a&gt;, that's nearly 70% of the world use mobile phones. All the newest web apps have responsive design to fit the mobile screen. But are we designing it with mobile in mind? &lt;/p&gt;

&lt;p&gt;Here are a few ways to make it easier for phone users:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Assume users will use their thumbs, not a stylus&lt;/li&gt;
&lt;li&gt; Have important buttons at the bottom of the screen&lt;/li&gt;
&lt;li&gt; Allow swiping to do actions&lt;/li&gt;
&lt;li&gt; Large buttons for fat fingers&lt;/li&gt;
&lt;li&gt; Optimize for right hands (sorry left-handers, you're only 10% of the population)&lt;/li&gt;
&lt;li&gt; Allow toggle-show password, typos are very common on phones&lt;/li&gt;
&lt;li&gt; Make sure input field is visible when keyboard is up. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1547032175-7fc8c7bd15b3%3Fixlib%3Drb-1.2.1%26q%3D80%26fm%3Djpg%26crop%3Dentropy%26cs%3Dtinysrgb%26w%3D1080%26fit%3Dmax%26ixid%3DeyJhcHBfaWQiOjExNzczfQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1547032175-7fc8c7bd15b3%3Fixlib%3Drb-1.2.1%26q%3D80%26fm%3Djpg%26crop%3Dentropy%26cs%3Dtinysrgb%26w%3D1080%26fit%3Dmax%26ixid%3DeyJhcHBfaWQiOjExNzczfQ" alt="person using Android smartphone"&gt;&lt;/a&gt; &lt;br&gt;
&lt;sup&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@georgiadelotz?utm_source=ghost&amp;amp;utm_medium=referral&amp;amp;utm_campaign=api-credit" rel="noopener noreferrer"&gt;Georgia de Lotz&lt;/a&gt; / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;amp;utm_medium=referral&amp;amp;utm_campaign=api-credit" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;




&lt;p&gt;‌&lt;/p&gt;

&lt;h2&gt;
  
  
  Honorable Mentions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Tesler's Law&lt;/strong&gt; - for any system there is a certain amount of complexity which cannot be reduced. &lt;a href="https://lawsofux.com/teslers-law" rel="noopener noreferrer"&gt;[12]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Zeigarnik Effect&lt;/strong&gt; - people tend to remember about an objective that was once pursued and left incomplete. &lt;a href="https://medium.com/coffee-and-junk/design-psychology-zeigarnik-effect-a53688b7f6d1" rel="noopener noreferrer"&gt;[17]&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;‌&lt;/p&gt;




&lt;p&gt;‌&lt;/p&gt;

&lt;h2&gt;
  
  
  How can I apply this to software development?
&lt;/h2&gt;

&lt;p&gt;With all these information about user behavior, it only works if we implement and use it in our development. How can we do so? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Be consistent with your use of color in buttons&lt;/li&gt;
&lt;li&gt;  Reserve strong colors for important elements, everything else can be muted&lt;/li&gt;
&lt;li&gt;  Split your information into a hierarchy of smaller things&lt;/li&gt;
&lt;li&gt;  Give immediate visual feedback&lt;/li&gt;
&lt;li&gt;  Have max of 7 items for every section&lt;/li&gt;
&lt;li&gt;  Position important items on the top left for desktop, and bottom right for mobile&lt;/li&gt;
&lt;li&gt;  Follow other website's behavior liberally&lt;/li&gt;
&lt;li&gt;  Keep everything aligned&lt;/li&gt;
&lt;li&gt;  Use the software you develop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What about software for developers? Developers are users too. They react in similar ways.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Use consistent APIs&lt;/li&gt;
&lt;li&gt;  Expose high level functions, not every low level function in the file&lt;/li&gt;
&lt;li&gt;  Split your library into smaller modules&lt;/li&gt;
&lt;li&gt;  Give instant and human readable error messages&lt;/li&gt;
&lt;li&gt;  Include documentation on the top of the library file&lt;/li&gt;
&lt;li&gt;  Follow similar behavior as other popular libraries&lt;/li&gt;
&lt;li&gt;  Use the library you develop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, break all the rules that you've just learned because design is never set in stone. Happy UX Designing! &lt;/p&gt;

&lt;h2&gt;
  
  
  ‌References
&lt;/h2&gt;

&lt;p&gt;[1] &lt;a href="https://uxdesign.cc/what-does-it-take-to-become-an-experience-design-expert-eba0e0d588eb" rel="noopener noreferrer"&gt;https://uxdesign.cc/what-does-it-take-to-become-an-experience-design-expert-eba0e0d588eb&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[2] &lt;a href="https://medium.com/strategic-design-lab/what-a-strategic-designer-does-b942f295379" rel="noopener noreferrer"&gt;https://medium.com/strategic-design-lab/what-a-strategic-designer-does-b942f295379&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[3] &lt;a href="https://tubikstudio.com/gestalt-theory-for-efficient-ux-principle-of-similarity/" rel="noopener noreferrer"&gt;https://tubikstudio.com/gestalt-theory-for-efficient-ux-principle-of-similarity/&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[4] &lt;a href="https://en.wikipedia.org/wiki/Gestalt_psychology" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Gestalt_psychology&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[5] &lt;a href="http://vanseodesign.com/web-design/gestalt-principles-of-perception/" rel="noopener noreferrer"&gt;http://vanseodesign.com/web-design/gestalt-principles-of-perception/&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[6] &lt;a href="https://blog.marvelapp.com/psychology-principles-every-uiux-designer-needs-know/" rel="noopener noreferrer"&gt;https://blog.marvelapp.com/psychology-principles-every-uiux-designer-needs-know/&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[7] &lt;a href="https://www.belatrixsf.com/blog/why-ux-design-is-so-important-in-agile-software-development/" rel="noopener noreferrer"&gt;https://www.belatrixsf.com/blog/why-ux-design-is-so-important-in-agile-software-development/&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[8] &lt;a href="https://www.smashingmagazine.com/2014/05/design-principles-space-figure-ground-relationship/" rel="noopener noreferrer"&gt;https://www.smashingmagazine.com/2014/05/design-principles-space-figure-ground-relationship/&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[9] &lt;a href="https://www.interaction-design.org/literature/topics/fitts-law" rel="noopener noreferrer"&gt;https://www.interaction-design.org/literature/topics/fitts-law&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[10] &lt;a href="https://www.researchgate.net/figure/The-F-Pattern-heat-map-in-reading-webpages-Nielsen-2006b_fig1_321859889" rel="noopener noreferrer"&gt;https://www.researchgate.net/figure/The-F-Pattern-heat-map-in-reading-webpages-Nielsen-2006b_fig1_321859889&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[11] &lt;a href="https://lawsofux.com/jakobs-law" rel="noopener noreferrer"&gt;https://lawsofux.com/jakobs-law&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[12] &lt;a href="https://lawsofux.com/teslers-law" rel="noopener noreferrer"&gt;https://lawsofux.com/teslers-law&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[13] &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.545.2322&amp;amp;rep=rep1&amp;amp;type=pdf" rel="noopener noreferrer"&gt;http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.545.2322&amp;amp;rep=rep1&amp;amp;type=pdf&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[14] &lt;a href="https://news.ycombinator.com/item?id=16289380" rel="noopener noreferrer"&gt;https://news.ycombinator.com/item?id=16289380&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[15] &lt;a href="https://lawsofux.com/doherty-threshold" rel="noopener noreferrer"&gt;https://lawsofux.com/doherty-threshold&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[16] &lt;a href="https://www.statista.com/statistics/274774/forecast-of-mobile-phone-users-worldwide/" rel="noopener noreferrer"&gt;https://www.statista.com/statistics/274774/forecast-of-mobile-phone-users-worldwide/&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[17] &lt;a href="https://medium.com/coffee-and-junk/design-psychology-zeigarnik-effect-a53688b7f6d1" rel="noopener noreferrer"&gt;https://medium.com/coffee-and-junk/design-psychology-zeigarnik-effect-a53688b7f6d1&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;[1] &lt;a href="https://logogeek.uk/logo-design/gestalt-theory/" rel="noopener noreferrer"&gt;https://logogeek.uk/logo-design/gestalt-theory/&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[2] &lt;a href="https://www.usertesting.com/blog/gestalt-principles/" rel="noopener noreferrer"&gt;https://www.usertesting.com/blog/gestalt-principles/&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[3] &lt;a href="http://www.scholarpedia.org/article/Gestalt_principles" rel="noopener noreferrer"&gt;http://www.scholarpedia.org/article/Gestalt_principles&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[4] &lt;a href="https://www.smashingmagazine.com/2014/03/design-principles-visual-perception-and-the-principles-of-gestalt/" rel="noopener noreferrer"&gt;https://www.smashingmagazine.com/2014/03/design-principles-visual-perception-and-the-principles-of-gestalt/&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[5] &lt;a href="http://facweb.cs.depaul.edu/sgrais/gestalt_principles.htm" rel="noopener noreferrer"&gt;http://facweb.cs.depaul.edu/sgrais/gestalt_principles.htm&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[6] &lt;a href="https://www.impactbnd.com/blog/laws-of-ux-infographic" rel="noopener noreferrer"&gt;https://www.impactbnd.com/blog/laws-of-ux-infographic&lt;/a&gt;‌&lt;br&gt;&lt;br&gt;
‌[7] &lt;a href="https://www.upwork.com/hiring/mobile/mobile-gestures-shaping-user-experience/" rel="noopener noreferrer"&gt;https://www.upwork.com/hiring/mobile/mobile-gestures-shaping-user-experience/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ux</category>
      <category>beginners</category>
      <category>design</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using Plotly.js Charts for Dashboards</title>
      <dc:creator>Jellene Khoh</dc:creator>
      <pubDate>Sun, 24 Mar 2019 12:38:33 +0000</pubDate>
      <link>https://forem.com/jellene4eva/using-plotlyjs-charts-for-dashboards-2g5l</link>
      <guid>https://forem.com/jellene4eva/using-plotlyjs-charts-for-dashboards-2g5l</guid>
      <description>&lt;p&gt;Today we're going to look at a really powerful charting library that is really easy to use and set up. &lt;a href="https://plot.ly/javascript/" rel="noopener noreferrer"&gt;Plotly Open Source Graphing Library&lt;/a&gt; supports several programming languages, including Python, Matlab, R, and most importantly Javascript!&lt;/p&gt;

&lt;p&gt;I've had to build a few dashboards for IoT companies, and charts are definitely one of the biggest elements in the view. Need I say more about the significance of charts to business related reporting such as sales, network monitoring, stocks etc.&lt;/p&gt;

&lt;p&gt;Plotly offers many kinds of charts and maps, but the most common ones I use are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Line charts&lt;/li&gt;
&lt;li&gt;  Bar charts&lt;/li&gt;
&lt;li&gt;  Step charts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below I'll walk through the basics on how I use plotly.js in an actual project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Very similar to other charting libraries, you can get them via CDN or npm packages. More detailed guide is in their &lt;a href="https://github.com/plotly/plotly.js" rel="noopener noreferrer"&gt;github page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  CDN
&lt;/h3&gt;

&lt;p&gt;Insert the script in the head of &lt;code&gt;index.html&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.plot.ly/plotly-latest.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  NPM
&lt;/h3&gt;

&lt;p&gt;To install with npm simply do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;plotly.js-dist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that it is &lt;code&gt;plotly.js-dist&lt;/code&gt; and not plotly.js&lt;/p&gt;

&lt;h3&gt;
  
  
  Import
&lt;/h3&gt;

&lt;p&gt;Now to import it into your project do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Plotly&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plotly.js-dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="nx"&gt;Plotly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPlot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the html you'll need a div with the &lt;code&gt;id&lt;/code&gt; you want to point to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;div id="div-id"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Really easy stuff!&lt;/p&gt;




&lt;h2&gt;
  
  
  Plotting a basic chart
&lt;/h2&gt;

&lt;p&gt;Now let do a basic line chart.&lt;/p&gt;

&lt;p&gt;@&lt;a href="https://codepen.io/jellene4eva/pen/JzrKYW" rel="noopener noreferrer"&gt;Codepen Basic Line Chart&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The javascript for this small chart is simple, we want to break down some of the important flags you need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;trace1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Energy consumption&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;7-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#45B5C6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;trace2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cold water consumption&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;7-3-2019&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;trace1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;trace2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="nx"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;showlegend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;Plotly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPlot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myDiv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;responsive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;displaylogo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  trace
&lt;/h3&gt;

&lt;p&gt;Each series in the chart is referred to as a trace. The &lt;em&gt;xaxis&lt;/em&gt; is usually the time range, and the &lt;em&gt;yaxis&lt;/em&gt; is the value. Here, I purposely use &lt;code&gt;string&lt;/code&gt; for my &lt;em&gt;xaxis&lt;/em&gt; because I want to be able to parse it into different localized format, e.g. Feb 2, 2019 in US, vs 2.2.2019 in Finland. Or even into quarters e.g. Q1/2018.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     @note: Plotly has locale config, but I wanted more control.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you treat each &lt;em&gt;xaxis&lt;/em&gt; item as a &lt;em&gt;category&lt;/em&gt;, then everything will work fine. If &lt;em&gt;xaxis&lt;/em&gt; is an array of &lt;code&gt;Date\&lt;/code&gt; items, Plotly will automatically parse it into a &lt;em&gt;timeseries chart.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can specify the line color of the each trace. If you leave it out, Plotly will provide a color based on the index. To change the color, add an entry&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    line: { 
        color: '#fff' 
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;data&lt;/code&gt; requires an Array of object. This is a little bit different from other charting libraries like &lt;a href="https://developers.google.com/chart/" rel="noopener noreferrer"&gt;Google Charts&lt;/a&gt; or &lt;a href="https://www.highcharts.com/" rel="noopener noreferrer"&gt;Highcharts&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  layout
&lt;/h3&gt;

&lt;p&gt;Layout is the general settings for Plotly. Here we're hiding the legends by adding this in the object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    showlegend: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Legends allow you to show / hide each trace, which is pretty handy, but I've decided to turn it off. In my app, I have other buttons outside the chart for me to control showing and hiding of each data, so I don't need the legends.&lt;/p&gt;

&lt;p&gt;Other configurations that I usually use for layout are &lt;code&gt;font&lt;/code&gt;, &lt;code&gt;autosize&lt;/code&gt;, &lt;code&gt;margin&lt;/code&gt;, to make the chart fit your container.&lt;/p&gt;

&lt;p&gt;Full documentation here: &lt;a href="https://plot.ly/javascript/reference/#layout" rel="noopener noreferrer"&gt;https://plot.ly/javascript/reference/#layout&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  configuration
&lt;/h3&gt;

&lt;p&gt;These configurations are extra options for other functions around the chart, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Allowing Scroll and Zoom&lt;/li&gt;
&lt;li&gt;  Modebar show / hide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Useful ones for me are&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    {
        responsive: true, 
        displaylogo: false
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should be pretty self explanatory - the configuration allows the chart to change width according to the window, and also remove Plotly's logo from the modebar.&lt;/p&gt;

&lt;p&gt;Full documentation here: &lt;a href="https://plot.ly/javascript/configuration-options/" rel="noopener noreferrer"&gt;https://plot.ly/javascript/configuration-options/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Multiple axes
&lt;/h2&gt;

&lt;p&gt;We now explore how to use different chart types in the same plot.&lt;/p&gt;

&lt;p&gt;@&lt;a href="https://codepen.io/jellene4eva/pen/aMLmMM" rel="noopener noreferrer"&gt;Codepen Multiline Chart&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;trace1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Energy consumption&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 00:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 03:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 06:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 09:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 12:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 15:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 18:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 21:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;82&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;20 kw/H&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;50 kw/H&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;92 kw/H&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;82 kw/H&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;14 kw/H&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;20 kw/H&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;50 kw/H&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;62 kw/H&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;hoverinfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x+text+name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;marker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#270657&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;trace2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Air pressure&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 00:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 03:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 06:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 09:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 12:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 15:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 18:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 21:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;81.32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;72.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;121.41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;71.31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;40.98&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;30.96&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;51.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;71.92&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;81.32 Pa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;72.1 Pa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;121.41 Pa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;71.31 Pa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;40.98 Pa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;30.96 Pa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;51.2 Pa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;71.92 Pa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;hoverinfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x+text+name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;trace3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lights&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 00:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 03:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 06:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 09:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 12:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 15:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 18:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.3.2019 21:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;on&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;on&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;on&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;on&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;on&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#45b5c6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;yaxis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;y2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;trace1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;trace2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;trace3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="nx"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;showlegend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;yaxis2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;category&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;side&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;right&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;overlaying&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;y&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;Plotly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPlot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;myDiv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;responsive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;displaylogo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Chart types
&lt;/h3&gt;

&lt;p&gt;Here we have 3 basic chart types - line, step, and bar charts. You can configure them for each trace&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    type: "line"

    ...

    type: "bar"

    ...

    // step chart
    type: "line",
    line: {
        shape: "hv",
    },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;also notice that by setting the second &lt;em&gt;yaxis2&lt;/em&gt;, we're able set a second yaxis on the right side of the chart for text based categories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    {
        ...
        text: ['81.32 Pa', '72.1 Pa', '121.41 Pa', '71.31 Pa', '40.98 Pa', '30.96 Pa', '51.2 Pa', '71.92 Pa'],
        hoverinfo: 'x+text+name',
        ...
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Custom text can be used to insert unit to the values. &lt;code&gt;hoverinfo&lt;/code&gt; allows you to customize what you want to show when the mouse is hovering over the value. If we use the &lt;code&gt;text&lt;/code&gt; instead of &lt;code&gt;y&lt;/code&gt; then we can have the unit shown.&lt;/p&gt;




&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FtP9CA4PTMnidOQtrS3wa" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.filestackcontent.com%2FtP9CA4PTMnidOQtrS3wa" alt="Screenshot from 2019-03-13 22:51:28.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Demo iot dashboard&lt;/p&gt;

&lt;p&gt;Here is a real life example of an iot dashboard for showing value changes of live sensor data.&lt;/p&gt;

&lt;p&gt;Hopefully with this you can use Plotly in your future projects with ease.&lt;/p&gt;

&lt;p&gt;View more examples of plotly here in the feed: &lt;a href="https://plot.ly/feed/#/" rel="noopener noreferrer"&gt;https://plot.ly/feed/#/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Other charting libraries
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://www.highcharts.com/" rel="noopener noreferrer"&gt;Highcharts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="//D3.js"&gt;&lt;/a&gt;&lt;a href="https://d3js.org/" rel="noopener noreferrer"&gt;D3.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developers.google.com/chart/" rel="noopener noreferrer"&gt;Google Charts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.chartjs.org/" rel="noopener noreferrer"&gt;Chart.js&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Also published in my blog &lt;a href="//jellenekhoh.io"&gt;jellenekhoh.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ui</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
