Archive

Archive for April, 2020

Click Once, Select All; Click Again, Select Normally

April 29th, 2020 No comments

A bonafide CSS trick from Will Boyd!

  1. Force all the content of an element to be selected when clicked with user-select: all;
  2. If you click a second time, let the user select just parts of the text as normal.
  3. Second click? Well, it’s a trick. You’re really using a time-delayed forwards-ending @keyframes animation when the element is in :focus to change it to user-select: text;

CodePen Embed Fallback

Will’s article has a bunch of more useful information and use-cases for user-select.

Direct Link to ArticlePermalink

The post Click Once, Select All; Click Again, Select Normally appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

[David Baron’s] Thoughts on an implementable path forward for Container Queries

April 29th, 2020 No comments

That’s the title of a public post from David Baron, a Principal Engineer at Firefox, with thoughts toward container queries. I know a lot of people have been holding their breath waiting for David’s ideas, as he’s one of few uniquely qualified to understand the ins and outs of this and speak to implementation possibility.

We’re still in the early stages of container queries. Every web designer and developer wants them, the browsers know it, but it’s a super complicated situation. It was very encouraging in February 2020 to hear positive signals about a possible switch-statement syntax that would give us access to an available-inline-size used to conditionally set individual values.

Now we’re seeing a second idea that is also in the realm of the possible.

This ideas uses an @rule instead for the syntax. From the document:

@container <selector> (<container-media-query>)? {
  // ... rules ...
}

So I’m imagining it like:

.parent {
  contain: layout inline-size;
  display: grid;
  grid-template-columns: 100%;
  gap: 1rem;
}
@container .parent (min-width: 400px) {
  grid-template-columns: 1fr 1fr;

  .child::before {
     content: "Hello from container query land!";
   }
}

Except…

  1. I’m not sure if you’d have to repeat the selector inside as well? Or if dropping property/value pairs in there automatically applies to the selector in the @rule.
  2. David says “The rules can match only that container’s descendants. Probably we’d need support for some properties applying to the container itself, but others definitely can’t.” I’d hope grid properties are a strong contender for something you can change, but I have no idea. Otherwise, I think we’d see people wrapping elements with
    to get around the “only descendants” limit.

Containment seems to be a very important part of this. Like if the element isn’t property contained, the container query just won’t work. I don’t know that much about containment, but Rachel has a great deep dive from late last year.

Again, this is super early days, I’m just having fun watching this and none of us really have any idea what will actually make it to browsers.

Direct Link to ArticlePermalink

The post [David Baron’s] Thoughts on an implementable path forward for Container Queries appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Alpine.js: The JavaScript Framework That’s Used Like jQuery, Written Like Vue, and Inspired by TailwindCSS

April 29th, 2020 No comments

We have big JavaScript frameworks that tons of people already use and like, including React, Vue, Angular, and Svelte. Do we need another JavaScript library? Let’s take a look at Alpine.js and you can decide for yourself. Alpine.js is for developers who aren’t looking to build a single page application (SPA). It’s lightweight (~7kB gzipped) and designed to write markup-driven client-side JavaScript.

The syntax is borrowed from Vue and Angular directive. That means it will feel familiar if you’ve worked with those before. But, again, Alpine.js is not designed to build SPAs, but rather enhance your templates with a little bit of JavaScript.

For example, here’s an Alpine.js demo of an interactive “alert” component.

CodePen Embed Fallback

The alert message is two-way bound to the input using x-model="msg". The “level” of the alert message is set using a reactive level property. The alert displays when when both msg and level have a value.

It’s like a replacement for jQuery and JavaScript, but with declarative rendering

Alpine.js is a Vue template-flavored replacement for jQuery and vanilla JavaScript rather than a React/Vue/Svelte/WhateverFramework competitor.

Since Alpine.js is less than a year old, it can make assumptions about DOM APIs that jQuery cannot. Let’s briefly draw a comparison between the two.

Querying vs. binding

The bulk of jQuery’s size and features comes in the shape of a cross-browser compatibility layer over imperative DOM APIs — this is usually referred to as jQuery Core and sports features that can query the DOM and manipulate it.

The Alpine.js answer to jQuery core is a declarative way to bind data to the DOM using the x-bind attribute binding directive. It can be used to bind any attribute to reactive data on the Alpine.js component. Alpine.js, like its declarative view library contemporaries (React, Vue), provides x-ref as an escape hatch to directly access DOM elements from JavaScript component code when binding is not sufficient (eg. when integrating a third-party library that needs to be passed a DOM Node).

Handling events

jQuery also provides a way to handle, create and trigger events. Alpine.js provides the x-on directive and the $event magic value which allows JavaScript functions to handle events. To trigger (custom) events, Alpine.js provides the $dispatch magic property which is a thin wrapper over the browser’s Event and Dispatch Event APIs.

Effects

One of jQuery’s key features is its effects, or rather, it’s ability to write easy animations. Where we might use slideUp, slideDown, fadeIn, fadeOut properties in jQuery to create effects, Alpine.js provides a set of x-transition directives, which add and remove classes throughout the element’s transition. That’s largely inspired by the Vue Transition API.

Also, jQuery’s Ajax client has no prescriptive solution in Alpine.js, thanks to the Fetch API or taking advantage of a third party HTTP library (e.g. axios, ky, superagent).

Plugins

It’s also worth calling out jQuery plugins. There is no comparison to that (yet) in the Alpine.js ecosystem. Sharing Alpine.js components is relatively simple, usually requiring a simple case of copy and paste. The JavaScript in Alpine.js components are “just functions” and tend not to access Alpine.js itself, making them relatively straightforward to share by including them on different pages with a script tag. Any magic properties are added when Alpine initializes or is passed into bindings, like $event in x-on bindings.

There are currently no examples of Alpine.js extensions, although there are a few issues and pull requests to add “core” events that hook into Alpine.js from other libraries. There are also discussions happening about the ability to add custom directives. The stance from Alpine.js creator Caleb Porzio, seems to be basing API decisions on the Vue APIs, so I would expect that any future extension point would be inspired on what Vue.js provides.

Size

Alpine.js is lighter weight than jQuery, coming in at 21.9kB minified — 7.1kB gzipped — compared to jQuery at 87.6kB minified — 30.4kB minified and gzipped. Only 23% the size!

Most of that is likely due to the way Alpine.js focuses on providing a declarative API for the DOM (e.g. attribute binding, event listeners and transitions).

Bundlephobia breaks down the two

For the sake of comparison, Vue comes in at 63.5kB minified (22.8kB gzipped). How can Alpine.js come in lighter despite it’s API being equivalent Vue? Alpine.js does not implement a Virtual DOM. Instead, it directly mutates the DOM while exposing the same declarative API as Vue.

Let’s look at an example

Alpine is compact because since application code is declarative in nature, and is declared via templates. For example, here’s a Pokemon search page using Alpine.js:

CodePen Embed Fallback

This example shows how a component is set up using x-data and a function that returns the initial component data, methods, and x-init to run that function on load.

Bindings and event listeners in Alpine.js with a syntax that’s strikingly similar to Vue templates.

  • Alpine: x-bind:attribute="express" and x-on:eventName="expression", shorthand is :attribute="expression" and @eventName="expression" respectively
  • Vue: v-bind:attribute="express" and v-on:eventName="expression", shorthand is :attribute="expression" and @eventName="expression" respectively

Rendering lists is achieved with x-for on a template element and conditional rendering with x-if on a template element.

Notice that Alpine.js doesn’t provide a full templating language, so there’s no interpolation syntax (e.g. {{ myValue }} in Vue.js, Handlebars and AngularJS). Instead, binding dynamic content is done with the x-text and x-html directives (which map directly to underlying calls to Node.innerText and Node.innerHTML).

An equivalent example using jQuery is an exercise you’re welcome to take on, but the classic style includes several steps:

  • Imperatively bind to the button click using $('button').click(/* callback */).
  • Within this “click callback” get the input value from the DOM, then use it to call the API.
  • Once the call has completed, the DOM is updated with new nodes generated from the API response.

If you’re interested in a side by side comparison of the same code in jQuery and Alpine.js, Alex Justesen created the same character counter in jQuery and in Alpine.js.

Back in vogue: HTML-centric tools

Alpine.js takes inspiration from TailwindCSS. The Alpine.js introduction on the repository is as “Tailwind for JavaScript.”

Why is that important?

One of Tailwind’s selling points is that it “provides low-level utility classes that let you build completely custom designs without ever leaving your HTML.” That’s exactly what Alpine does. It works inside HTML so there is no need to work inside of JavaScript templates the way we would in Vue or React Many of the Alpine examples cited in the community don’t even use script tags at all!

Let’s look at one more example to drive the difference home. Here’s is an accessible navigation menu in Alpine.js that uses no script tags whatsoever.

CodePen Embed Fallback

This example leverages aria-labelledby and aria-controls outside of Alpine.js (with id references). Alpine.js makes sure the “toggle” element (which is a button), has an aria-expanded attribute that’s true when the navigation is expanded, and false when it’s collapsed. This aria-expanded binding is also applied to the menu itself and we show/hide the list of links in it by binding to hidden.

Being markup-centric means that Alpine.js and TailwindCSS examples are easy to share. All it takes is a copy-paste into HTML that is also running Alpine.js/TailwindCSS. No crazy directories full of templates that compile and render into HTML!

Since HTML is a fundamental building block of the web, it means that Alpine.js is ideal for augmenting server-rendered (Laravel, Rails, Django) or static sites (Hugo, Hexo, Jekyll). Integrating data with this sort of tooling can be a simple as outputting some JSON into the x-data="{}" binding. The affordance of passing some JSON from your backend/static site template straight into the Alpine.js component avoids building “yet another API endpoint” that simply serves a snippet of data required by a JavaScript widget.

Client-side without the build step

Alpine.js is designed to be used as a direct script include from a public CDN. Its developer experience is tailored for that. That’s why it makes for a great jQuery comparison and replacement: it’s dropped in and eliminates a build step.

While it’s not traditionally used this way, the bundled version of Vue can be linked up directly. Sarah Drasner has an excellent write-up showing examples of jQuery substituted with Vue. However, if you use Vue without a build step, you’re actively opting out of:

  • the Vue CLI
  • single file components
  • smaller/more optimized bundles
  • a strict CSP (Content Security Policy) since Vue inline templates evaluate expressions client-side

So, yes, while Vue boasts a buildless implementation, its developer experience is really depedent on the Vue CLI. That could be said about Create React App for React, and the Angular CLI. Going build-less strips those frameworks of their best qualities.

There you have it! Alpine.js is a modern, CDN-first library that brings declarative rendering for a small payload — all without the build step and templates that other frameworks require. The result is an HTML-centric approach that not only resembles a modern-day jQuery but is a great substitute for it as well.

If you’re looking for a jQuery replacement that’s not going to force you into a SPAs architecture, then give Alpine.js a go! Interested? You can find out more on Alpine.js Weekly, a free weekly roundup of Alpine.js news and articles.

The post Alpine.js: The JavaScript Framework That’s Used Like jQuery, Written Like Vue, and Inspired by TailwindCSS appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

We Redesigned Web Design Ledger – Here’s It Is!

April 29th, 2020 No comments

The news is true, we completely redesigned the best blog in the world, Web Design Ledger!

Okay, maybe we’re a little bit biased, but there’s no denying that the new web design layout is amazing.

We are so excited to show you guys the finished product.

Let me just hit you with the most satisfying before and after ever.

Before…

After!

Amazing, right?!

With this new era and new decade that we’ve come into this year, we wanted to bring our design blog along with it and let it go through a major change.

We really wanted it to symbolise a new design era.

It was about time our blog got a facelift, and we’re obsessed with it.

Everything is minimal and has soft edges, and what I’m really thrilled about is that gradient bar at the top of the home page.

Our blog is easier to browse through now than ever and it just has an all-around crisp and fresh vibe to it.

We’ve been working on this design for a long time now, and we couldn’t be happier for you guys to see it.

The old design was great too, but it was time for the old design to retire and for the new design to have its moment and really flourish.

We hope that the rest of this year will be full of exciting things and new changes.

We’re excited to be alongside you through this year and see what it all has to offer.

I know we’re all going through a strange time right now, but together, we’ll pull through this and come out newer and better than ever.

Just like our new design ?

What do you guys think of the new design?

Let us know in the comments!

Until next time,

Stay safe and stay creative, folks!

Read More at We Redesigned Web Design Ledger – Here’s It Is!

Categories: Designing, Others Tags:

How To Succeed In Wireframe Design

April 29th, 2020 No comments
Flow chart of stages of software design & development life cycle where wireframes can be used.

How To Succeed In Wireframe Design

How To Succeed In Wireframe Design

Anton Suprunenko

2020-04-29T12:30:00+00:002020-04-30T13:10:47+00:00

For the most part, we tend to underestimate things that are familiar to us. It is also very likely that we will underestimate those things that though new, seem very simple to process. And that is correct to some degree. But, when we are faced with complex cases and all measures are taken, a good and solid understanding of the basics could help us to find the right solutions.

In this article, we will take a deeper look at one of the most simple, thus, quite often underrated activities in web development that is the design of wireframes. We will find out what are wireframes, why we need to design them, how to get the most out of the wireframes design, and how to take it to the next level.

According to The Top 20 Reasons Startups Fail report by CB Insights, 17% of startups reported lack of user-friendliness as the reason for their failure. Designing a user-friendly interface is not a trivial task, especially for large and complex products where there are many entities, dependencies, and elements to be organized. To design such complex products you should follow a top-down approach and wireframes design is the best technique that could help you with that.

First, Let’s Define Terms

Wireframe — also known as a page schematic or screen blueprint, and it is a visual guide that represents the skeletal framework of a website or an application.

Additional definition we will look at is wireframing — a process of designing a wireframe, and commonly used to lay out content and functionality on a page which takes into account user needs and user journeys. Wireframes are used early in the development process to establish the basic structure of a page before visual design and content is added.

At first glance, wireframing seems simple. And herein lies the major problem: that we tend not to pay enough attention to simple things. One way to help us get the most benefits from wireframing is to define the goals of the product or service.

The main goal of wireframing, that we could get is to show the team and stakeholders which entities, pages, and components the application is going to have and how these elements of the digital product will interact with each other.

From the goal definition we can see how big the impact of wireframing is for both the development process and the final product.

When we keep in mind the goals of the wireframing process, we still need to pay attention to what are the common pitfalls to avoid during wireframes design.

Wireframing Mistakes We Want To Avoid

  • Creating wireframes for the sake of ‘box-checking’;
  • Skipping wireframes stage at all;
  • Preparing wireframes after the visual designs;
  • Not understanding why to use wireframes.

Wireframes should precede the stage of visual design, not vice versa. It’s like deciding on the technology stack for your application after having the code written.

Wireframe design lays the foundation for the quality of the design, and the better we understand the goal of this phase the more benefits we could get. So let’s dive deeper and find out why we need to design wireframes and what values this technique brings.

Businesses that lack knowledge of the product design may welcome the practice of skipping wireframe design as it allows them to cut the project costs, but this decision may lead to potential failure in the long run. And you, as the designer, should explain why we are doing it, how it will help the final product, and how it could even save future expenses.

Next, let’s check some points that could help you better understand why we need wireframes and see how wireframes help to get feedback from your developers, clients and future users of your product.

Why You Should Design Wireframes

Help Your Team Estimate And Refine The Scope Of Work

Wireframes allow designers to quickly create a visual representation of the future product and demonstrate it to the team for the needed revisions. Wireframes also help you show your team which screens the application is going to have, which elements and controls will be on each screen, and how all the elements will interact with each other. In addition, looking through wireframes is way faster than reading specifications. Also, it helps us avoid discrepancies in scope between the initial estimates and the final ones.

Involve All Team Members In The Product Design Stage

We all have been in the position of having created a top-notch design, only to be faced with development constraints. The use of wireframes allows us to involve developers in discussing designs at the early stages, enabling them to provide feedback and suggest changes before you start working on visual design. This way, you can speed up the design process and avoid wasting time and money.

Flow chart of stages of software design & development life cycle where wireframes can be used.

Stages of software design & development life cycle where wireframes can be used in one form or another. (Large preview)

Hold A Demo For Clients

Getting rapid feedback from your clients and stakeholders is an important component of the design process. Also, we all have experienced multiple change-requests from our stakeholders and that is normal. With wireframes, we could make this process more efficient. Making changes to prototypes requires more time and effort than making changes to wireframes, it will let you be more agile and don’t waste extra time on rework.

Carry Out User Testing

According to Eric Ries, author of Lean Startup, the sooner you carry out user testing, the better — no one wants to roll out an application and find out that users don’t get how to use it right. Wireframes can help designers get valuable feedback from potential users and don’t spend time on developing complex interactive prototypes when they are not needed.

The fact that UI/UX designers use wireframes does not necessarily mean that they do it right. For that, you should remember and follow the best practices.

Wireframing Best Practices

To bring the best results and serve a solid foundation for further UI, you need to follow several simple rules:

1. Minimize The Use Of Color In Wireframes

If you’re using rich color palettes in your wireframes, remind yourself of the goal of wireframing (to show which elements the product is going to have, and how they should interact with each other) and think if extra colors help you to achieve it.

Example of how to minimize the use of color in wireframes

Minimize the use of color in wireframes, we will have dedicated phase for this. (Large preview)

In some cases, they could. But in general, adding colors to your wireframes might distract the viewer’s attention and will surely make any updates more difficult. Moreover, there’s another important issue to consider — not all clients have a good understanding of UX techniques and might take colored wireframes for final designs.

Example of correct color using in wireframes

Example of correct color using in wireframes. (Large preview)

However, this doesn’t mean you should never use color on wireframes and strictly stick with the black and white palette. Sometimes using color to highlight specific components is justified. For example, you can use red for error states or blue for notes, etc.

2. Use Simple Design Of Components

When you add components to your wireframes, go for basic designs. Wireframes aren’t intended to contain thoroughly designed and detailed components. Instead, they should be easily recognized by your team members and stakeholders. Adding detailed components will cost you a lot of time and effort without being particularly useful.

Example of how to use simple design of components and make its functional purpose clear

Use simple design of components and make its functional purpose clear. (Large preview)

3. Maintain Consistency

Similar components must look the same on all your wireframes. If the same components look different, developers are likely to question if they are actually the same and even add extra time to the estimates because of different designs. When working on wireframes, remember a simple rule: be consistent and try not to create confusion.

Example of how to maintain consistency between similar components

Maintain consistency between similar components and avoid using same look for different components. (Large preview)

4. Use Real Content

From time to time we could see that UI/UX designers don’t add real content on the wireframes and use lorem ipsum instead. That’s a common mistake that few designers even realize they make. You may object and say that the content isn’t available at the stage of design. Well, it’s enough to use the draft version of the content.

Example of using real content instead of lorem ipsum in wireframes

Use real content instead of lorem ipsum. (Large preview)

Content impacts the design you’ll create, and the draft content will help you make the right decisions and deliver the superb design. If you use lorem ipsum, however, you won’t see the full picture and will likely need to make a lot of adjustments to the UI or even worse — you will create a design that doesn’t work. Also, the real content will add value to your wireframes, explain the context better and maybe indicate that you need to start gathering the real content already.

5. Use Annotations

It may happen that some design solutions can’t be visually illustrated, so stakeholders or developers might have questions about them. For example, the logic behind some controls. In such cases, you can provide on-screen annotations to explain the logic behind that. This way, your team will understand your solutions, and you won’t need to spend time discussing them.

Example of using annotations to describe specific logic

Use annotations to describe specific logic. (Large preview)

6. Low To High-Fidelity

There’s no strict rule. Sometimes you should go for low-fidelity wireframes, while some projects might require high-fidelity ones. It depends on the project, so if you feel like adding more details to the wireframes — don’t hesitate to do it. But according to Eric Ries, don’t do extra work when this doesn’t bring value, start from the basics and then add details as long as they are needed. For instance, if you need to draw the developers’ attention to some custom solution, then add more details to illustrate it in your wireframes.

Example of both low and high-fidelity wireframes

Both low and high-fidelity wireframes have a place to be. (Large preview)

7. Extend Wireframes To Prototypes

As designers we work with different products, some of them have simple and common interactions, and some of them have quite advanced ones. Sometimes wireframes are not enough to illustrate the interaction of complex and uncommon interfaces, but instead of writing long notes and spending hours on explanations, you could extend your wireframes to interactive prototypes.

Example of how interactive prototype flow looks

Developing interactive prototype now easier than ever. (Large preview)

The good news is that today we have a wide range of simple but very powerful tools like Figma, Invision, Adobe XD, UXPin, Axure, Moqups, etc. and we definitely need to review them and choose the best tool for designing the wireframes and developing simple prototypes.

Wireframe Design Tools

Now it’s time to choose a superb wireframing tool that will help you create amazing designs and streamline your workflow. There are a lot of different options you can use for wireframing, and you might have used some of them before. I’d like to give you a basic understanding of how different they are.

Most wireframe tools are tailored to:

  • Simplicity
    They have a low barrier to entry and are perfect for people who take their first steps in UI/UX design and lack experience using more sophisticated software.
  • Collaboration
    These are packed with a rich functionality for teamwork. Collaboration is a backbone of modern software development, so the best wireframing tools not only provide lots of features but allow for efficient and easy collaboration between all team members involved in the design process.

Here are the most widely used wireframe tools tailored to collaboration:

  • Figma
    A powerful cloud-based tool that comes in a web version and desktop applications for Windows and macOS. Figma comes with a lot of powerful features for building wireframes, prototypes, UIs, and more (see table below).
  • Sketch
    This tool is extremely popular with UI/UX designers. If you need to go beyond the default Sketch toolset, you can use dozens of plugins to get extra functions. Unlike many of its competitors, Sketch is available only on macOS and you will need a 3rd-party solution for collaboration.

There are plenty of applications you can use to design wireframes. You shouldn’t make a choice based solely on the features provided in the application. Instead, I would advise you to try and explore all of them and decide which works for you best. Below you can find a list of some of the most popular tools to start with.

Tool Pros Cons
Sketch
  • Dedicated to design UI
  • Can create design from scratch
  • Link artboards to Interactive prototypes
  • Large community and wide range of plugins
  • Simple interface
  • Paid
  • Mac only
  • Requires 3rd party plugins for extended features like collaboration with team members
Figma
  • Has free option
  • Dedicated to design UI
  • Can create design from scratch
  • Link artboards to Interactive prototypes
  • Wide range of built in collaboration features, like specs for developers
  • Simple and fast interface
  • Large community
  • 3rd party plugins
  • Available for Mac, Win, Web
  • Can import from Sketch
  • Simultaneous work of several designers with one layout
  • Pay only for extra editors, all viewers of designs and specs are for free
  • Requires online connection
  • No privacy of creative process, as everyone who has access to you file could see your real time activity
Invision Studio
  • Has free option
  • Dedicated to design UI
  • Good addon to InvisionApp
  • Can create design from scratch
  • Available for Mac and Win
  • Can import from Sketch
  • No third-party plugins
  • No simultaneous editing
  • Need to use Invision app for presenting, building prototypes, and provide specs for developers
Adobe XD
  • Has free option
  • Dedicated to design UI
  • Can create design from scratch
  • Can import from Sketch and Photoshop
  • Link artboards to Interactive prototypes
  • Handy tools to work with objects groups
  • Available for Mac and Win
  • Simple and fast interface
  • Voice command triggers and playback
  • Coediting feares
  • Small community
  • No web-based app
  • Limited functionality comparing to competitors, but constantly growing
Principle
  • Advanced prototyping and animation features
  • Import designs from Sketch and Figma
  • Paid
  • Mac only
  • No web-based app
  • Can only prototype with existing screens
  • No developers hand-off
  • Sharing only to iOS or Mac
  • Quite complex UI, you will need to spend some time to learn it
Framer X
  • Paid
  • Mac Only
  • No web-based app
  • Import only from Sketch
  • No built in collaboration features
  • For some custom solutions, coding knowledges are required
UXPin
  • Has free option
  • Dedicated to design UI
  • Can create design from scratch
  • Link artboards to Interactive prototypes
  • Can import from Sketch and Photoshop
  • Support dynamic inputs and variables
  • Wide range of built in collaboration features, like specs for developers
  • Available for Mac, Win, Web
  • Great knowledgebase
  • Requires online connection
  • Can only view one screen at a time
Balsamiq
  • Web-based app
  • Simple interface
  • Created to quick and easy design simples wireframes
  • Paid
  • Requires online connection
  • No prototyping or collaboration features
  • Very limited functionality
Axure
  • Available for Mac and Win
  • Simultaneous work
  • Can create design from scratch
  • Support dynamic inputs and variables
  • Let’s you to create hi-fidelity prototypes with very close look and feel to real application
  • Paid
  • No web-based app
  • Quite complex UI, you will need to spend some time to learn it
  • Check-out system for avoiding merge conflicts is not user friendly
Moqups
  • Has free option
  • Web-based app
  • Dedicated to design UI
  • Can create designs from scratch
  • Simple prototyping
  • Good for wireframes
  • Collaboration features
  • Requires online connection
  • No import from other design tools
  • No animations features
  • Not the best tool for visual UI design
  • No hands of for developers
Adobe Photoshop
  • Available for Mac and Win
  • Advanced features to create and edit raster images
  • Large community
  • Can be used to design wireframes if you don’t have any other option
  • Paid
  • Not dedicated to design UI
  • No web-based app
  • No prototyping features
  • No collaboration features
  • Overwhelmed UI
Adobe Illustrator
  • Available for Mac and Win
  • Advanced features to create and edit vector images
  • Large community
  • Can be used to design wireframes if you don’t have any other option
  • Paid
  • Not dedicated to design UI
  • No web-based app
  • No prototyping features
  • No collaboration features
  • Overwhelmed UI

As an example of the power of modern design tools, I’d like to share my own experience and show you how we set up an effective wireframing design process with one of the tools above.

Case Study: How We Set Up A Wireframing Process Across Multiple Teams

Context

The company I worked at was building complex fintech digital products. Apart from the design team, there was a professional team of business analysts (BAs). They prepared the requirements and created low-fidelity wireframes that they passed on to our design team.

Picking The Tool

We needed to choose an all-in-one tool for the BA and design teams. Since most business analysts have fairly low design skills, we wanted to find a tool that would be simple enough for BAs and — at the same time — powerful enough for designers. Also, easy collaboration was our team’s priority. Based on these criteria, we opted for Figma.

Creating The Library Of Components

To streamline the product design process, we created a custom library of components that the BA team could use. This allowed us to speed up the wireframing, as the business analysts could quickly use ready-made blocks instead of drawing their own.

Training The Team

To show how to use Figma and the library of components, we held a workshop for our BA team. We also found it important to teach them some extra features, such as prototyping.

Diagram of relations between teams in wireframing design process

Diagram of relations between teams in wireframing design process. (Large preview)

Result

In our case Figma proved to be efficient for wireframing and collaboration, even though the team members were located in Ukraine, Australia, and the Philippines. We currently use Figma for the communication channel — it proved to be more convenient to collaborate on the wireframes by mail or in messengers.

Summing Up

Being a simple practice, wireframes design usually doesn’t get enough awareness from us, designers, when we face them for the first time.

As a result, lack of attention for this technique leads to a number of flaws, when we either add a lot of decoration to wireframes, or create low-fi wireframes for the sake of box-checking when the project rather requires a more detailed solution, or even skip this stage and go straight to visual UI design.

Usually, all of these mistakes are the result of poor understanding of both wireframes design objectives (that is to show which elements the product is going to have, and how they should interact with each other), as well as poor understanding of when wireframes could help us, like:

  • Wireframes could help the team to get more precise estimates of the project.
  • Wireframes could help to involve all team members to design processes and avoid engineering mistakes that will affect the development process.
  • Wireframes could help us to make early presentations to clients, stakeholders and conduct user testing sessions to get feedback as soon as possible, and save time on the development of poor solutions.

Today, as designers, we are lucky as never before because there are dozens of tools available for us to design wireframes and also smoothly integrate this activity in our general design process.

The only thing that we need to do is to spend some time to incorporate both the technique and tools in our own design process, and find a way how to make them work for us to take our product design process to the next level. That they certainly can.

(ah, yk, il)
Categories: Others Tags:

Email Personalization: Your Secret To Better Engagement

April 29th, 2020 No comments

One of the struggles that marketers face is how to send the right message at exactly the right time to target people in a way that will appeal to them. To solve the problem, businesses need to get themselves acquainted with new technologies and the power of personalization.

In the past few years, digital marketing as we know it has undergone numerous changes, distinguishing itself from the traditional marketing of the past.

With new technologies on the rise, marketing has become easier and smarter, enabling businesses to achieve more than they did. More specifically, the use of AI and machine learning has allowed businesses to refine their marketing campaigns, placing the customer at the center of their operations.

As a channel, email has proven itself…to have the best ROI

However, how can you capture a customer’s attention without being physically there to engage with them and show them that your business is the right place to spend their time and money? One of your best allies to show consumers that you aren’t a faceless brand is none other than email marketing.

As a channel, email has proven itself not only to be convenient for modern consumers, but also to have the best ROI; $55 for every $1 you spend on it.

Your mail campaigns are indeed efficient lead nurturing tools, but everything will be in vain if you don’t target your audience with highly personalized messages.

Why Do Businesses Need Personalization?

Modern consumers receive hundreds of promotional emails on a daily basis. However, some of them end up in their trash without being read. Why?

Well, with the rise of scams, the majority of consumers have trained themselves to identify fake messages and fraudulent content.

As a result, emails that look spammy, impersonal and irrelevant — even if that wasn’t your intention — will eventually end up in users’ trash folders.

This will harm your email deliverability and give you a bad send reputation that will prevent you from reaching your subscribers’ inbox.

To ensure that your email campaigns get the desired open and click-through rates, you have to make sure that your messages are tailored to your subscribers’ needs. That’s where personalization comes in.

Personalized content will show your recipients that your message is unique and not part of a one-size-fits-all email campaign.

Of course, you can’t send every single campaign manually. To save time, marketing automation has enabled businesses to automate the process and deliver numerous campaigns automatically without cutting down on personalization.

To do so, you need a platform to provide you with valuable, real-time insights and powerful personalization tools. If you still haven’t chosen one, you can try one of the available free email marketing services to get an idea of how email personalization works.

Personalization will help your audience see the value of your message, primarily because it will be addressed to them.

Consequently, tailored content will help you get more engagement, build a loyal audience who will anticipate your content, and turn them from subscribers into satisfied customers. As email marketing statistics show, personalization is so powerful that it can increase your open rate even by 29%.

What About Hyper-Personalization?

A simple first name in your emails might be effective, but as marketing evolves, it won’t be enough to attract your subscribers’ attention.

For that, businesses have tried to discover new ways to get their audience to click on their incentives and promote their business development. According to a survey by SmarterHQ 72% of consumers say they now only engage with marketing tailored to their interests.

72% of consumers say they now only engage with marketing tailored to their interests

This consumer tendency has created a new form of personalization called hyper-personalization.

Hyper-personalization leverages data to provide more personalized suggestions and messages that will be tailored to each customer’s needs.

Through this advanced form of personalization, you can improve customer experience and drive your prospects and leads a step further down your marketing and sales funnels.

To make hyper-personalization possible, you need to leverage the power of AI and data. But before you do that, you need to know how to collect customer data and then leverage it through AI and machine learning.

Collecting Customer Data

Your first step to personalizing your marketing is to decide what kind of data you need to collect, and why you need it. Especially after GDPR regulations came to existence and consumers’ rising concerns about data privacy.

Here’s an example from Bulgari’s website, informing visitors about their privacy policy in a fully transparent manner:

This cookie policy is right there, complete with everything one would need to know when viewing a brand’s website, even before signing up.

It will make your prospects feel safe right off the bat since the website not only acknowledges its use of cookies but also gives the prospect an opportunity to review why this happens.

There is, of course, no set of rules regarding the data you may need from a prospect. It could be anything.

Now that you’ve made your privacy policy clear it’s time to start collecting your visitors’ information. In this case, Bulgari has created an efficient form to capture its visitors’ emails and at the same time collect valuable information that will improve their newsletter open and click rate:

Segmenting Your Subscribers

Adding the right input fields into your forms will give your new subscribers an idea of what you’ll do with their information.

Bulgari’s form is a great example that includes all the right fields to collect insight into its audience’s preferences.

After your prospects click on your CTA and join your mailing list, you can start segmenting each subscriber based on their interests and preferences.

Segmentation is one of the most efficient practices to personalize your email content and deliver tailored content that will convert your audience into loyal customers.

For instance, demographic segmentation will help you come up with unique campaigns for your female and male subscribers. Then, you can use their individual data to further personalize the email content based on their interests.

Segmenting your audience, though, is only the beginning to achieve hyper-personalization.

Leveraging the power of AI will help you deliver personalized product recommendations in the form of amazing email campaigns that will convince your audience to click-through and buy more.

How To Use Customer Data The Right Way

The first thing you need to know is how AI enables hyper-personalization. Essentially, it’s how you can fully leverage data to improve your marketing activities.

Machines learn in the same way humans do. By feeding data into the machine and adding more and more scenarios, you’re teaching the platform to distinguish between scenarios and find patterns in a quicker and more accurate manner.

More importantly, the machine is taught to connect past “purchases” and come up with suggestions for a marketing team.

Essentially, the more data the machine can go through, the more scenarios it can come up with and the more prospects it can connect to. This will lead to the creation of a unique buyer persona that will be more accurate than the traditional buyer personas created by marketers.

In the end, the personas you create through AI will be able to provide tailor-made solutions and appeal to the general sentiment of each segment of your audience.

Now that you’ve created your personas and know which segment of your list is interested in which of your products, you can use your promotional content more effectively.

Here’s an example from Matalan that uses a customer’s previous purchase data to come up with a personalized cross-sell email:

With a hyper-personalized email, you’ll be able to target your audience with more accuracy.

The use of data will help you craft more messages that will be personalized and tailor-made. So, when you apply them to the AI-generated user persona you will step up your customer lifecycle marketing efforts effectively.

Takeaway

If you use AI and data correctly, you’ll be able to provide one-on-one content down the line, seeing as AI is able to track and trace the kind of content individuals are most interested in, through social media data, engagement data, and so on.

This will help marketers to create amazing content that will be both valuable and engaging for your new prospects.

What’s more, personalization will enable marketing teams to create something that will feel natural, incentivizing your audience to click on your CTAs and move a step further down your marketing funnel.

Source

Categories: Designing, Others Tags:

How to Redirect a Search Form to a Site-Scoped Google Search

April 28th, 2020 No comments

This is just a tiny little trick that might be helpful on a site where you don’t have the time or desire to build out a really good on-site search solution. Google.com itself can perform searches scoped to one particular site. The trick is getting people there using that special syntax without them even knowing it.

Make a search form:

<form action="https://google.com/search" target="_blank" type="GET">

  <label>
     Search CSS-Tricks on Google: 
     <input type="search" name="q">
   </label>

  <input type="submit" value="Go">

</form>

When that form is submitted, we’ll intercept it and change the value to include the special syntax:

var form = document.querySelector("form");

form.addEventListener("submit", function (e) {
  e.preventDefault();
  var search = form.querySelector("input[type=search]");
  search.value = "site:css-tricks.com " + search.value;
  form.submit();
});

That’s all.

CodePen Embed Fallback

The post How to Redirect a Search Form to a Site-Scoped Google Search appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Using Formik to Handle Forms in React

April 28th, 2020 No comments
Showing console output of the various hooks and objects that are logged by Formik.

There is no doubt that web forms play an integral role in our web site or applications. By default, they provide a useful set of elements and features — from legends and fieldsets to native validation and states — but they only get us so far when we start to consider the peculiarities of using them. For example, how can we manipulate the state of a form? How about different forms of validation? Even hooking a form up to post submissions is a daunting effort at times.

Component-driven front-end libraries, like React, can ease the task of wiring web forms but can also get verbose and redundant. That’s why I want to introduce you to Formik, a small library that solves the three most annoying parts of writing forms in React:

  1. State manipulation
  2. Form validation (and error messages)
  3. Form submission

We’re going to build a form together in this post. We’ll start with a React component then integrate Formik while demonstrating the way it handles state, validation, and submissions.

Creating a form as a React component

Components live and breathe through their state and prop. What HTML form elements have in common with React components is that they naturally keep some internal state. Their values are also automatically stored in their value attribute.

Allowing form elements to manage their own state in React makes them uncontrolled components. That’s just a fancy way of saying the DOM handles the state instead of React. And while that works, it is often easier to use controlled components, where React handles the state and serves as the single source of truth rather than the DOM.

The markup for a straightforward HTML form might look something like this:

<form>
  <div className="formRow">
    <label htmlFor="email">Email address</label>
    <input type="email" name="email" className="email" />
  </div>
  <div className="formRow">
    <label htmlFor="password">Password</label>
    <input type="password" name="password" className="password" />
  </div>
  <button type="submit">Submit</button>
</form>

We can convert that into a controlled React component like so:

function HTMLForm() {
  const [email, setEmail] = React.useState("");
  const [password, setPassword] = React.useState("");


  return (
    <form>
      <div className="formRow">
        <label htmlFor="email">Email address</label>
        <input
          type="email"
          name="email"
          className="email"
          value={email}
          onChange={e => setEmail(e.target.value)}
        />
      </div>
      <div className="formRow">
        <label htmlFor="password">Password</label>
        <input
          type="password"
          name="password"
          className="password"
          value={password}
          onChange={e => setPassword(e.target.value)}
        />
      </div>
      <button type="submit">Submit</button>
    </form>
  );
}

This is a bit verbose but it comes with some benefits:

  1. We get a single source of truth for form values in the state.
  2. We can validate the form when and how we want.
  3. We get performance perks by loading what we need and when we need it.

OK, so why Formik again?

As it is with anything JavaScript, there’s already a bevy of form management libraries out there, like React Hook Form and Redux Form, that we can use. But there are several things that make Formik stand out from the pack:

  1. It’s declarative: Formik eliminates redundancy through abstraction and taking responsibility for state, validation and submissions.
  2. It offers an Escape Hatch: Abstraction is good, but forms are peculiar to certain patterns. Formik abstracts for you but also let’s you control it should you need to.
  3. It co-locates form states: Formik keeps everything that has to do with your form within your form components.
  4. It’s adaptable: Formik doesn’t enforce any rules on you. You can use as less or as much Formik as you need.
  5. Easy to use: Formik just works.

Sound good? Let’s implement Formik into our form component.

Going Formik

We will be building a basic login form to get our beaks wet with the fundamentals. We’ll be touching on three different ways to work with Formik:

  1. Using the useFormik hook
  2. Using Formik with React context
  3. Using withFormik as a higher-order component

I’ve created a demo with the packages we need, Formik and Yup.

Method 1: Using the useFormik hook

As it is right now, our form does nothing tangible. To start using Formik, we need to import the useFormik hook. When we use the hook, it returns all of the Formik functions and variables that help us manage the form. If we were to log the returned values to the console, we get this:

We’ll call useFormik and pass it initialValues to start. Then, an onSubmit handler fires when a form submission happens. Here’s how that looks:

// This is a React component
function BaseFormik() {
  const formik = useFormik({
    initialValues: {
      email: "",
      password: ""
    },
    onSubmit(values) {
      // This will run when the form is submitted
    }
  });
  
 // If you're curious, you can run this Effect
 //  useEffect(() => {
 //   console.log({formik});
 // }, [])


  return (
    // Your actual form
  )
}

Then we’ll bind Formik to our form elements:

// This is a React component
function BaseFormik() {
  const formik = useFormik({
    initialValues: {
      email: "",
      password: ""
    },
    onSubmit(values) {
      // This will run when the form is submitted
    }
  });
  
 // If you're curious, you can run this Effect
 //  useEffect(() => {
 //   console.log({formik});
 // }, [])


  return (
  // We bind "onSubmit" to "formik.handleSubmit"
  <form className="baseForm" onSubmit={formik.handleSubmit} noValidate>
    <input
      type="email"
      name="email"
      id="email"
      className="email formField"
      value={formik.values.email} // We also bind our email value
      onChange={formik.handleChange} // And, we bind our "onChange" event.
    />
  </form>
  )
}

This is how the binding works:

  1. It handles form submission with onSubmit={formik.handleSubmit}.
  2. It handles the state of inputs with value={formik.values.email} and onChange={formik.handleChange}.

If you take a closer look, we didn’t have to set up our state, nor handle the onChange or onSubmit events as we’d typically do with React. The complete change to our form goes:

However as you might have noticed, our form contains some redundancy. We had to drill down formik and manually bind the form input’s value and onChange event. That means we should de-structure the returned value and immediately bind the necessary props to a dependent field, like this:

// This is a React component
function BaseFormik() {
  const {getFieldProps, handleSubmit} = useFormik({
    initialValues: {
      email: "",
      password: ""
    },
    onSubmit(values) {
      // This will run when the form is submitted
    }
  });
  
 // If you're curious, you can run this Effect
 //  useEffect(() => {
 //   console.log({formik});
 // }, [])


  return (
  <form className="baseForm" onSubmit={handleSubmit} noValidate>
    <input
      type="email"
      id="email"
      className="email formField"
      {...getFieldProps("email")} // We pass the name of the dependent field
    />
  </form>
  )
}

Let’s take things even further with the included component.

Method 2: Using Formik with React context

The component exposes various other components that adds more abstraction and sensible defaults. For example, components like <Form/>, , and are ready to go right out of the box.

Keep in mind, you don’t have to use these components when working with but they do require (or withFormik) when using them.

Using requires an overhaul because it uses the render props pattern as opposed to hooks with useFormik. The render props pattern isn’t something new in React. It is a pattern that enables code re-usability between components — something hooks solve better. Nevertheless, has a bagful of custom components that make working with forms much easier.

import { Formik } from "formik";


function FormikRenderProps() {
  const initialValues = {
    email: "",
    password: ""
  };
  function onSubmit(values) {
    // Do stuff here...
    alert(JSON.stringify(values, null, 2));
  }
  return (
      <Formik {...{ initialValues, onSubmit }}>
        {({ getFieldProps, handleSubmit }) => (
            <form className="baseForm" onSubmit={handleSubmit} noValidate>
              <input
                type="email"
                id="email"
                className="email formField"
                {...getFieldProps("email")}
              />
            </form>
        )}
      </Formik>
  );
}

Notice that initialValues and onSubmit have been completely detached from useFormik. This means we are able to pass the props that needs, specifically initialValues and useFormik.

returns a value that’s been de-structured into getFieldProps and handleSubmit. Everything else basically remains the same as the first method using useFormik.

Here’s a refresher on React render props if you’re feeling a little rusty.

We haven’t actually put any components to use just yet. I’ve done this intentionally to demonstrate Formik’s adaptability. We certainly do want to use those components for our form fields, so let’s rewrite the component so it uses the component.

import { Formik, Field, Form } from "formik";


function FormikRenderProps() {
  const initialValues = {
    email: "",
    password: ""
  };
  function onSubmit(values) {
    // Do stuff here...
    alert(JSON.stringify(values, null, 2));
  }
  return (
      <Formik {...{ initialValues, onSubmit }}>
        {() => (
            <Form className="baseForm" noValidate>
              <Field
                type="email"
                id="email"
                className="email formField"
                name="email"
              />
            </Form>
        )}
      </Formik>
  );
}

We replaced with and removed the onSubmit handler since Formik handles that for us. Remember, it takes on all the responsibilities for handling forms.

We also replaced with and removed the bindings. Again, Formik handles that.

There’s also no need to bother with the returned value from anymore. You guessed it, Formik handles that as well.

Formik handles everything for us. We can now focus more on the business logic of our forms rather than things that can essentially be abstracted.

We’re pretty much set to go and guess what? We’ve haven’t been concerned with state managements or form submissions!

“What about validation?” you may ask. We haven’t touched on that because it’s a whole new level on its own. Let’s touch on that before jumping to the last method.

Form validation with Formik

If you’ve ever worked with forms (and I bet you have), then you’re aware that validation isn’t something to neglect.

We want to take control of when and how to validate so new opportunities open up to create better user experiences. Gmail, for example, will not let you input a password unless the email address input is validated and authenticated. We could also do something where we validate on the spot and display messaging without additional interactions or page refreshes.

Here are three ways that Formik is able to handle validation:

  1. At the form level
  2. At the field level
  3. With manual triggers

Validation at the form level means validating the form as a whole. Since we have immediate access to form values, we can validate the entire form at once by either:

Both validate and validationSchema are functions that return an errors object with key/value pairings that those of initialValues. We can pass those to useFormik, or withFormik.

While validate is used for custom validations, validationSchema is used with a third-party library like Yup.

Here’s an example using validate:

// Pass the `onSubmit` function that gets called when the form is submitted.
const formik = useFormik({
  initialValues: {
    email: "",
    password: ""
  },
  // We've added a validate function
  validate() {
    const errors = {};
    // Add the touched to avoid the validator validating all fields at once
    if (formik.touched.email && !formik.values.email) {
      errors.email = "Required";
    } else if (
      !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$/i.test(formik.values.email)
    ) {
      errors.email = "Invalid email address";
    }
    if (formik.touched.password && !formik.values.password) {
      errors.password = "Required";
    } else if (formik.values.password.length <= 8) {
      errors.password = "Must be more than 8 characters";
    }
    return errors;
  },
  onSubmit(values) {
    // Do stuff here...
  }
});
// ...

And here we go with an example using validationSchema instead:

const formik = useFormik({
  initialValues: {
    email: "",
    password: ""
  },
  // We used Yup here.
  validationSchema: Yup.object().shape({
    email: Yup.string()
      .email("Invalid email address")
      .required("Required"),
    password: Yup.string()
      .min(8, "Must be more than 8 characters")
      .required("Required")
  }),
  onSubmit(values) {
    // Do stuff here...
  }
});

Validating at the field level or using manual triggers are fairly simple to understand. Albeit, you’ll likely use form level validation most of the time. It’s also worth checking out the docs to see other use cases.

Method 3: Using withFormik as a higher-order component

withFormik is a higher-order component and be used that way if that’s your thing. Write the form, then expose it through Formik.

A couple of practical examples

So far, we’ve become acquainted with Formik, covered the benefits of using it for creating forms in React, and covered a few methods to implement it as a React component while demonstrating various ways we can use it for validation. What we haven’t done is looked at examples of those key concepts.

So, let’s look at a couple of practical applications: displaying error messages and generating a username based on what’s entered in the email input.

Displaying error messages

We’ve built our form and validated it. And we’ve caught some errors that can be found in our errors object. But it’s no use if we aren’t actually displaying those errors.

Formik makes this a pretty trivial task. All we need to do is check the errors object returned by any of the methods we’ve looked at — , useFormik or withFormik — and display them:

<label className="formFieldLabel" htmlFor="email">
  Email address
  <span className="errorMessage">
    {touched["email"] && errors["email"]}
  </span>
</label>
<div className="formFieldWrapInner">
  <input
    type="email"
    id="email"
    className="email formField"
    {...getFieldProps("email")}
  />
</div>

If there’s an error during validation, {touched["email"] && errors["email"]} will display it to the user.

We could do the same with . With this, we only need to tell it the name of the dependent field to watch:

<ErrorMessage name="email">
  {errMsg => <span className="errorMessage">{errMsg}</span>}
</ErrorMessage>

Generating a username from an email address

Imagine a form that automatically generates a username for your users based on their email address. In other words, whatever the user types into the email input gets pulled out, stripped of @ and everything after it, and leaves us with a username with what’s left.

For example: jane@doe.com produces @jane.

Formik exposes helpers that can “intercept” its functionality and lets us perform some effects.In the case of auto-generating a username, one way will be through Formik’s setValues:

onSubmit(values) {
  // We added a `username` value for the user which is everything before @ in their email address.
  setValues({
    ...values,
    username: `@${values.email.split("@")[0]}`
  });
}

Type in an email address and password, then submit the form to see your new username!

Wrapping up

Wow, we covered a lot of ground in a short amount of space. While this is merely the tip of the iceberg as far as covering all the needs of a form and what Formik is capable of doing, I hope this gives you a new tool to reach for the next time you find yourself tackling forms in a React application.

If you’re ready to take Formik to the next level, I’d suggest looking through their resources as a starting point. There are so many goodies in there and it’s a good archive of what Formik can do as well as more tutorials that get into deeper use cases.

Good luck with your forms!

The post Using Formik to Handle Forms in React appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Implementing Dark Mode In React Apps Using styled-components

April 28th, 2020 No comments
StackOverflow announces dark mode on Twitter

Implementing Dark Mode In React Apps Using styled-components

Implementing Dark Mode In React Apps Using styled-components

Blessing Krofegha

2020-04-28T10:30:00+00:002020-04-28T14:46:54+00:00

One of the most commonly requested software features is dark mode (or night mode, as others call it). We see dark mode in the apps that we use every day. From mobile to web apps, dark mode has become vital for companies that want to take care of their users’ eyes.

Dark mode is a supplemental feature that displays mostly dark surfaces in the UI. Most major companies (such as YouTube, Twitter, and Netflix) have adopted dark mode in their mobile and web apps.

While we won’t go in depth into React and styled-components, a basic knowledge of React, CSS, and styled-components would come in handy. This tutorial will benefit those who are looking to enhance their web applications by catering to those who love dark mode.

StackOverflow announces dark mode on Twitter

StackOverflow announces dark mode on Twitter (Large preview)

A few days before the writing of this article, StackOverflow announced its release of dark mode, giving users the chance to toggle between the two modes.

Dark mode reduces eye strain and helps when you’re working for a long time on a computer or mobile phone.

What Is Dark Mode?

Dark mode is the color scheme of any interface that displays light text and interface elements on a dark background, which makes the screen a little easier to look at mobile phones, tablets, and computers. Dark mode reduces the light emitted by the screen, while maintaining the minimum color-contrast ratios required for readability.

Why Should You Care About Dark Mode?

Dark mode enhances visual ergonomics by reducing eye strain, adjusting the screen to current light conditions, and providing ease of use at night or in dark environments.

Before implementing dark mode in our app, let’s look at its benefits.

Battery Saving

Dark mode in web and mobile apps can prolong the battery life of a device. Google has confirmed that dark mode on OLED screens has been a huge help to battery life.

For example, at 50% brightness, dark mode in the YouTube app saves about 15% more screen energy than a flat white background. At 100% screen brightness, the dark interface saves a whopping 60% of screen energy.

Dark Mode Is Beautiful

Dark mode is beautiful, and it can significantly enhance the appeal of the screen.

While most products are going for that similar bland white look, dark mode offers something different that feels mysterious and new.

It also provides great opportunities to present graphic content such as dashboards, pictures, and photos in a fresh way.

Twitter dark versus light mode

The beauty of Twitter’s dark mode over light mode (Large preview)

Now that you know why you should implement dark mode in your next web app, let’s dive deep into styled-components, which is the defining resource of this tutorial.


Dark mode is the color scheme of any interface that displays light text and interface elements on a dark background, which makes it a little easier to look at on mobile phones, tablets, and computers.

What Are styled-components?

Throughout this article, we will be using the styled-components library very often. There have always been many ways to style a modern web app. There’s the traditional method of styling at the document level, which includes creating an index.css file and linking it to the HTML or styling inside the HTML file.

A lot has changed in the ways that web apps are styled recently, since the introduction of CSS-in-JS.

CSS-in-JS refers to a pattern in which CSS is composed using JavaScript. It utilizes tagged template literals to style components in a JavaScript file.

To learn more about CSS-in-JS, check out Anna Monus’s article on the subject.

styled-components is a CSS-in-JS library lets you use all of the features of CSS that you love, including media queries, pseudo-selectors, and nesting.

Why styled-components?

styled-components was created for the following reasons:

  • No class name hell
    Instead of you scratching your head to find a class name for an element, styled-components generates unique class names for your styles. You’ll never have to worry about misspellings or using class names that have no meaning.
  • Using props
    styled-components allow us to extend styling properties using the props parameter, commonly used in React — thus, dynamically affecting the feel of a component via the application’s state.
  • Supports Sass syntax
    Writing Sass syntax out of the box without having to set up any preprocessors or extra build tools is possible with styled-components. In your style definitions, you can use the & character to target the current component, use pseudo-selectors, and experiment with nesting.
  • Theming
    styled-components have full theming support by exporting a ThemeProvider wrapper component. This component provides a theme to all React components within itself via the Context API. In the rendering tree, all styled-components will have access to the provided theme, even when they are multiple levels deep. As we continue in this tutorial, we will look deeper into the theming features of styled-components.

To learn more advantages of styled-components, check out Kris Guzman’s article.

Implementing Dark Mode

In this article, we are going to implement dark mode on a simple YouTube-like web page.

To follow along, ensure that you clone the original repository from the starter branch.

Setting Up

Let’s install all of the dependencies in our package.json file. From the terminal, run the following command:

npm install

Upon its successful installation, run npm start. Here is what the web page looks like without dark mode implemented on it.

The web page to be used, without dark mode. (Large preview)

To install styled-components, in your terminal run npm install styled-components.

Implementation

To implement dark mode, we need to create four different components.

  • Theme
    This contains the color properties of our light and dark themes.
  • GlobalStyles
    This contains the global styles for the entire document.
  • Toggler
    This holds the button element that toggles the functionality.
  • useDarkMode
    This custom hook handles the logic behind the change of theme and the persistence of our theme in localStorage.

Theme Component

In the src folder, you’ll see components in the components folder. Create a Themes.js file, and add the following code to it.

export const lightTheme = {
    body: '#FFF',
    text: '#363537',
    toggleBorder: '#FFF',
    background: '#363537',
}
export const darkTheme = {
    body: '#363537',
    text: '#FAFAFA',
    toggleBorder: '#6B8096',
    background: '#999',
}

Here, we’ve defined and exported lightTheme and darkTheme objects with distinct color variables. Feel free to experiment and customize the variables to suit you.

globalStyles Component

Remaining in your components folder, create a globalStyles.js file, and add the following code:

import { createGlobalStyle} from "styled-components"
export const GlobalStyles = createGlobalStyle`
  body {
    background: ${({ theme }) => theme.body};
    color: ${({ theme }) => theme.text};
    font-family: Tahoma, Helvetica, Arial, Roboto, sans-serif;
    transition: all 0.50s linear;
  }
  `

We’ve imported createGlobalStyle from styled-components. The createGlobalStyle method replaces the now deprecated injectGlobal method from styled-components version 3. This method generates a React component, which, when added to your component tree, will inject global styles into the document, in our case, App.js.

We defined a GlobalStyle component and assigned background and color properties to values from the theme object. Thus, every time we switch the toggle, the values will change depending on the dark theme or light theme objects that we are passing to ThemeProvider (which will be created later, as we proceed).

The transition property of 0.50s enables this change to occur a little more smoothly, so that as we toggle back and forth, we can see the changes happen.

Creating Theme-Toggling Functionality

To implement the theme-toggling functionality, we need to add only a few lines of code. In the App.js file, add the following code (note that the highlighted code is what you should add):

import React, { useState, useEffect } from "react";
import {ThemeProvider} from "styled-components";
import { GlobalStyles } from "./components/Globalstyle";
import { lightTheme, darkTheme } from "./components/Themes"
import "./App.css";
import dummyData from "./data";
import CardList from "./components/CardList";
const App = () => {
const [videos, setVideos] = useState([]);
const [theme, setTheme] = useState('light');
const themeToggler = () => {
  theme === 'light' ? setTheme('dark') : setTheme('light')
}
useEffect(() => {
    const timer = setTimeout(() => {
      setVideos(dummyData);
    }, 1000);
    return () => clearTimeout(timer);
  }, []);
  return (
    <ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>
      <>
      <GlobalStyles/>
          <div className="App">
            <button onClick={themeToggler}>Switch Theme</button>
      {
      videos.map((list, index) => {
        return (
          <section key={index}>
            <h2 className="section-title">{list.section}</h2>
            <CardList list={list} />
            <hr />
          </section>
        );
      })}
        </div>
      </>
    </ThemeProvider>

  );
};
export default App;

The highlighted code is the one newly added to App.js. We’ve imported ThemeProvider from styled-components. ThemeProvider is a helper component in the styled-components library that provides theming support. This helper component injects a theme into all React component below itself via the Context API.

In the rendering tree, all styled-components will have access to the provided theme, even when they are multiple levels deep. Check out the section on “Theming”.

Next, we import the GlobalStyle wrapper from ./components/Globalstyle. Lastly, from the top, we import both the lightTheme and darkTheme objects from ./components/Themes.

In order for us to create a toggling method, we need a state that holds our theme’s initial color value. So, we create a theme state, and set the initial state to light, using the useState hook.

Now, for the toggling functionality.

The themeToggler method uses a ternary operator to check the state of the theme, and it toggles either dark or light based on the value of the condition.

ThemeProvider, a styled-components helper component, wraps everything in the return statement and injects any components below it. Remember that our GlobalStyles inject global styles into our components; hence, it’s called inside the ThemeProvider wrapper component.

Lastly, we created a button with an onClick event that assigns our themeToggler method to it.

Let’s see the outcome thus far.

Dark mode implemented without persistence (Large preview)

Our App.js file needs to be refactored; a lot of its code is not DRY. (DRY stands for “don’t repeat yourself”, a basic principle of software development aimed at reducing repetition.) All of the logic seems to be in App.js; it’s good practice to separate our logic for the sake of clarity. So, we’ll create a component that handles the toggling functionality.

Toggle Component

Still within the components folder, create a Toggler.js file, and add the following code to it:

import React from 'react'
import { func, string } from 'prop-types';
import styled from "styled-components"
const Button = styled.button`
  background: ${({ theme }) => theme.background};
  border: 2px solid ${({ theme }) => theme.toggleBorder};
  color: ${({ theme }) => theme.text};
  border-radius: 30px;
  cursor: pointer;
  font-size:0.8rem;
  padding: 0.6rem;
  }
`;
const Toggle = ({theme,  toggleTheme }) => {
    return (
        <Button onClick={toggleTheme} >
          Switch Theme
        </Button>
    );
};
Toggle.propTypes = {
    theme: string.isRequired,
    toggleTheme: func.isRequired,
}
export default Toggle;

To keep things neat, we’ve styled our toggle button in the Toggle component, using the styled function from styled-components.

This is purely for presentation; you can style the button as you see fit.

Inside the Toggle component, we pass two props:

  • the theme provides the current theme (light or dark);
  • the toggleTheme function will be used to switch between themes.

Next, we return the Button component and assign a toggleTheme function to the onClick event.

Lastly, we use propTypes to define our types, ensuring that our theme is a string and isRequired, while our toggleTheme is func and isRequired.

Using Custom Hooks (useDarkMode)

When building an application, scalability is paramount, meaning that our business logic must be reusable, so that we can use it in many places and even in different projects.

That is why it would be great to move our toggling functionality to a separate component. For that, we would create our own custom hook.

Let’s create a new file named useDarkMode.js in the components folder, and move our logic to this file, with some tweaks. Add the following code to the file:

import { useEffect, useState } from 'react';
export const useDarkMode = () => {
    const [theme, setTheme] = useState('light');

    const setMode = mode => {
        window.localStorage.setItem('theme', mode)
        setTheme(mode)
    };

    const themeToggler = () => {
        theme === 'light' ? setMode('dark') : setMode('light')
    };

    useEffect(() => {
        const localTheme = window.localStorage.getItem('theme');
        localTheme && setTheme(localTheme)
    }, []);
    return [theme, themeToggler]
};

We’ve added a few things here.

  • setMode
    We use localStorage to persist between sessions in the browser. So, if a user has chosen the dark or light theme, that’s what they’ll get upon their next visit to the app or if they reload the page. Hence, this function sets our state and passes theme to localStorage.
  • themeToggler
    This function uses a ternary operator to check the state of the theme and toggles either dark or light based on the truth of the condition.
  • useEffect
    We’ve implemented the useEffect hook to check on component mounting. If the user has previously selected a theme, we will pass it to our setTheme function. In the end, we will return our theme, which contains the chosen theme and the themeToggler function to switch between modes.

I think you’ll agree that our dark-mode component looks sleek.

Let’s head over to App.js for the final touches.

import React, { useState, useEffect } from "react";
import {ThemeProvider} from "styled-components";
import  {useDarkMode} from "./components/useDarkMode"
import { GlobalStyles } from "./components/Globalstyle";
import { lightTheme, darkTheme } from "./components/Themes"
import Toggle from "./components/Toggler"
import "./App.css";
import dummyData from "./data";
import CardList from "./components/CardList";
const App = () => {
const [videos, setVideos] = useState([]);
const [theme, themeToggler] = useDarkMode();
const themeMode = theme === 'light' ? lightTheme : darkTheme;

useEffect(() => {
  const timer = setTimeout(() => {
    setVideos(dummyData);
  }, 1000);
  return () => clearTimeout(timer);
}, []);

return (
  <ThemeProvider theme={themeMode}>
    <>
      <GlobalStyles/>
        <div className="App">
        <Toggle theme={theme} toggleTheme={themeToggler} />
          {
            videos.map((list, index) => {
              return (
                <section key={index}>
                  <h2 className="section-title">{list.section}</h2>
                  <CardList list={list} />
                  <hr />
                </section>
              );
            })}
        </div>
      </>
    </ThemeProvider>
  );
};
export default App;

The highlighted code is newly added to App.js.

First, we import our custom hook, destructure the theme and themeToggler props, and set it with the useDarkMode function.

Note that the useDarkMode method replaces our theme state, which was initially in App.js.

We declare a themeMode variable, which renders either a light or dark theme based on the condition of the theme mode at the time.

Now, our ThemeProvider wrapper component is assigned our just recently created themeMode variable to the theme prop.

And lastly, in place of the regular button, we pass in the Toggle component.

Remember that in our Toggle component, we defined and styled a button and passed both theme and toggleTheme to them as props. So, all we have to do is pass these props appropriately to the Toggle component, which will act as our button in App.js.

Yes! Our dark mode is set, and it persists, not changing color when the page is refreshed or visited in a new tab.

Let’s see the outcome in action:

Dark mode implemented, but with a glitch in the button color when the browser reloads.
Dark mode implemented, but with a glitch in the button color when the browser reloads. (Large preview)

Almost everything works well, but there is one small thing we can do to make our experience splendid. Switch to the dark theme and then reload the page. Do you see that the blue color in the button loads before the gray for a brief moment? That happens because our useState hook initiates the light theme initially. After that, useEffect runs, checks localStorage, and only then sets the theme to dark. Let’s jump over to our custom hook useDarkMode.js and add a little code:

import { useEffect, useState } from 'react';
export const useDarkMode = () => {
    const [theme, setTheme] = useState('light');
    const [mountedComponent, setMountedComponent] = useState(false)
    const setMode = mode => {
        window.localStorage.setItem('theme', mode)
        setTheme(mode)
    };
    const themeToggler = () => {
        theme === 'light' ? setMode('dark') : setMode('light')
    };
    useEffect(() => {
        const localTheme = window.localStorage.getItem('theme');
        localTheme ? setTheme(localTheme) : setMode('light')
        setMountedComponent(true)
    }, []);
    return [theme, themeToggler, mountedComponent]
};

The highlighted code is the only one added to useDarkMode.js. We’ve created another state named mountedComponent and set the default value to false using the useState hook. Next, inside the useEffect hook, we set the mountedComponent state to true using setMountedComponent. Lastly, in the return array, we include the mountedComponent state.

Finally, let’s add a bit of code in App.js to make it all work.

import React, { useState, useEffect } from "react";
import {ThemeProvider} from "styled-components";
import  {useDarkMode} from "./components/useDarkMode"
import { GlobalStyles } from "./components/Globalstyle";
import { lightTheme, darkTheme } from "./components/Themes"
import Toggle from "./components/Toggler"
import "./App.css";
import dummyData from "./data";
import CardList from "./components/CardList";
const App = () => {
  const [videos, setVideos] = useState([]);
  const [theme, themeToggler, mountedComponent] = useDarkMode();
  const themeMode = theme === 'light' ? lightTheme : darkTheme;
  useEffect(() => {
    const timer = setTimeout(() => {
      setVideos(dummyData);
    }, 1000);
    return () => clearTimeout(timer);
  }, []);
  if(!mountedComponent) return <div/>
  return (
    <ThemeProvider theme={themeMode}>
      <>
      <GlobalStyles/>
        <div className="App">
          <Toggle theme={theme} toggleTheme={themeToggler} />
          {
            videos.map((list, index) => {
              return (
                <section key={index}>
                  <h2 className="section-title">{list.section}</h2>
                  <CardList list={list} />
                  <hr />
                </section>
              );
            })}
        </div>
      </>
    </ThemeProvider>

  );
};
export default App;

We’ve added our mountedComponent state as a prop in our useDarkMode hook, and we’ve checked whether our component has mounted, because this is what happens in the useEffect hook. If it hasn’t happened yet, then we will render an empty div.

Let’s see the outcome of our dark-mode web page.

Final result of dark mode
Final result of dark mode (Large preview)

Now, you’ll notice that while in dark mode, when the page reloads, the button’s color doesn’t change.

Conclusion

Dark mode is increasingly becoming a user preference, and implementing it in a React web app is a lot easier when using the ThemeProvider theming wrapper in styled-components. Go ahead and experiment with styled-components as you implement dark mode; you could add icons instead of a button.

Please do share your feedback and experience with the theming feature in styled-components in the comments section below. I’d love to see what you come up with!

The supporting repository for this article is available on GitHub. Also, check it out on CodeSandbox.

References

Smashing Editorial(ks, ra, il, al)
Categories: Others Tags:

Static or Not?

April 27th, 2020 No comments

A quick opinion piece by Kev Quirk: Why I Don’t Use A Static Site Generator. Kev uses WordPress:

Want to blog on my iPad? I can. Want to do it on my phone? No problem. On a machine I don’t normally use? Not an issue, as long as it has a browser.

First, it’s worth understanding that by using WordPress it doesn’t opt you out of using a static site generator. WordPress has an API, and that opens the door to hit that API during a build process and build your site that way. That’s what Gatsby does, there is a plugin that exports a static site, and projects like Frontity really blur the lines.

But I agree with Kev here on his reasoning. For all his reasons, and 1,000 more, it’s a perfectly acceptable and often smart choice to run a WordPress site. I think about it in terms of robustness and feature-readiness. Need e-commerce? It’s there. Need forms? There are great plugins. Need to augment how the CMS works? You have control over the types of content and what is in them. Need auth? That’s a core feature. Wish you had a great editing experience? Gutenberg is glorious.

Time and time again, I build what I wanted to build with WordPress quickly and efficiently and it’s made me feel productive and powerful. But I don’t wanna make this specifically about WordPress; this can be true of any “classic” CMS. Craft CMS has a GraphQL API out of the box. We just posted about a Drupal + Jamstack webinar.

In the relatively new world of static sites, a little thing can end up a journey of research and implementation, like you’re the only third person on Earth to ever do it.

Now all that said…

What do I think of static site generators and the Jamstack world? They are awesome.

I think there is a lot to be said about building sites this way. The decoupling of data and front-end is smart. The security is great. The DX, what with the deploy previews and git-based everything is great. The speed you get out of the gate is amazing (serving HTML from a CDN is some feat).

Just like a classic server-side CMS doesn’t opt you out of building a static site, building with a static site doesn’t opt you out of doing dynamic things — even super duper fancy dynamic things. Josh Comeau has a great new post going into this. He built a fancy little app that does a ton in the browser with React, but that doesn’t mean he still can’t deliver a good amount of it statically. He calls it a “mindset shift,” referring to the idea that you might think you need a database call, but do you really? Could that database call have already happened and generated a static file? And if not, still, some of it could have been generated with the last bits coming over dynamically.

I can’t wait for a world where we start really seeing the best of both worlds. We do as much statically as possible, we get whatever we can’t do that way with APIs, and we don’t compromise on the best tools along the way.

When to go with a static site…

  • If you can, you should consider it, as the speed and security can’t be beaten.
  • If you’re working with a Greenfield project.
  • If your project builds from and uses accessible APIs, you could hit that API during the build process as well as use it after the initial HTML loads.
  • If some static site generator looks like a perfect fit for something you’re doing.
  • If a cost analysis says it would be cheaper.
  • If functionality (like build previews) would be extremely helpful for a workflow.

When to go with server-side software…

  • If you need the features of a classic CMS (e.g. WordPress), and the technical debt of going static from there is too high.
  • If you’re already in deep with a server-rendered project (Ruby on Rails, Python, etc.) and don’t have any existing trouble.
  • If that is where you have the most team expertise.
  • If a cost analytics says it would be cheaper.
  • If there aren’t good static solutions around for what want to build (e.g. forums software).
  • If you have an extreme situation, like millions of URLs, and the build time for static is too high.

Bad reasons to avoid a static site…

  • You need to do things with servers. (Why? You can still hit APIs on servers, either at build or during runtime.)
  • You need auth. (Why? Jamstack is perfectly capable of auth with JWTs and such.)
  • You haven’t even looked into doing things Jamstack-style.

Bad reasons to choose server-side software…

  • You haven’t even looked into doing things Jamstack-style.
  • Because you think using comfortable / existing / classic / well-established / well-supported tools opt you out of building anything statically.
  • Something something SEO. (If anything, statically rendered content should perform better. But it’s understandable if a move to static means moving to client-side calls for something like product data.)

The post Static or Not? appeared first on CSS-Tricks.

Categories: Designing, Others Tags: