Categories
Uncategorized

SmashingConfs, Inspiring Talks And Birthday Cake

Do you know when the very first article got published on Smashing Magazine? Well, it doesn’t take long to research and find out: it was back in September ’06. Since then, the web has obviously changed a lot, but there’s one thing that has always remained true for us: we care about quality content. We…

Want to Read more ? Do you know when the very first article got published on Smashing Magazine? Well, it doesn’t take long to research and find out: it was back in September ’06. Since then, the web has obviously changed a lot, but there’s one thing that has always remained true for us: we care about quality content. We never wanted to be a big publishing house: Our team is small, but it’s a truly wonderful team of people who really care about what they do. Passionate and dedicated. Honest and respectful. Professional but informal. Quirky and personal.
This year wasn’t quite the year that we planned, but we’re super proud of handling it so well nevertheless. As soon as lockdowns were announced, we launched our online events, and it’s awesome to see how well they’re being received. The team has so much fun meeting people in different timezones while being scattered all over the globe.
So after 14 years of online publishing, we are ever so committed to nourishing productivity, improving design and development skills, and finessing the work-life balance. We hope that our articles, guides, podcast, digital books, job openings, conferences, newsletter and membership will help you explore and learn something new each and every day. Getting better — together — by learning from each other; that’s really the spirit that has been our mantra throughout all these years.

Last year, our editor-in-chief Rachel Andrew already shared quite a number of personal stories from the Smashing team, but in case you’ve only just recently started reading Smashing Magazine and haven’t been around for that long, perhaps you’d like to read our guidelines to find out more about how things run around here. We’re always glad to make new contacts and explore new possibilities, and would be very happy to welcome you on board of our Smashing team!
Interface Design Checklists PDF (100 Cards, Updated Regularly)
A few weeks ago, we released a digital edition of Vitaly’s Smart Interface Design Checklists of which we’re quite fond of adding to our Smashing collection. The cards were created to help designers and developers iron out misunderstandings early on in their work, thus avoiding ambiguity and costly mistakes down the line. Jump to the table of contents →

Please note that the cards are currently only available in PDF format — we’re doing our best to print them as soon as it’s possible to ship worldwide!

Upcoming Online Workshops
So, when’s the next chance to join a workshop and meet all the amazing folks from the industry? Search no more: I’ve brought all the dates and names for you below:

Sept. 22 – Oct. 6
Smart Interface Design Patterns, 2020 Edition
Vitaly Friedman
Design & UX

Oct. 8 – Oct. 22
The SVG Animation Masterclass
Cassie Evans
Front-end

Oct. 12 – Oct. 26
Web Performance Masterclass
Harry Roberts
Front-end

Oct. 28 – Oct. 29
Designing for Emotion Masterclass
Aarron Walter
Design & UX

Nov. 12 – Nov. 27
Build, Ship and Extend GraphQL APIs from Scratch
Christian Nwamba
Front-end

Nov. 18 – Nov. 26
Designing Websites That Convert
Paul Boag
Design & UX

Dec. 3 – Dec. 17
Building A Design System With CSS
Andy Bell
Front-end

Attending a Smashing online event means that you’ll be taking part in live sessions, Q&As, discussion zones, challenges, and so much more! Join in the fun — we provide live captioning in English, too!

Upcoming Online Conferences
As we’ve decided to take all of our 2020 events online, there are still two more you can join in for some SmashingConf fun. We hope to see you there!
SmashingConf Austin/NY Online (Oct 13–14)
We have combined the programming for New York and Austin as these two events were so close together and similar to each other. We’ll be running this event in Central time, just as if we were all in Austin. Check out the schedule, and buy tickets here. We’d love to see you in October!

SmashingConf SF Online (Nov 10–11)
In PST, join us for a SmashingConf San Francisco on November 10th–11th. The schedule and tickets are online for you to take a look at. We’ll be sure to have a great celebration for our final event of 2020!

Trending Topics On Smashing Magazine
At Smashing Magazine, we publish at least one new article every single day that is related to an important topic in the web industry. Of course, we have an RSS feed to which you can subscribe to anytime if you’d like to be among the first readers to be informed once there’s new content to dive in to!

“Designing With Reduced Motion For Motion Sensitivities,”written by Val Head
“How To Build Your Own Comment System Using Firebase,”written by Aman Thakur
“Everything Developers Need To Know About Figma,”written by Jurn van Wissen
“Forms And Validation In Ionic React,”written by Jerry Navi
“Demystifying Django’s Magic,”written by Precious Ndubueze

Newsletter Best Picks
As we’ve now started sending out weekly editions of the Smashing Newsletter, we’ve been aiming for shorter and topic-specific issues. So far, we’ve sent out editions that focus on CSS, front-End accessibility, and JavaScript. Of course, we like to add in a mix of other topics as well, just so that there’s something there for everyone! 😉
We love sharing all the cool things that we see folks doing across communities within the web industry, and we hope you’ll help spread the word! Here are just some of the projects that our subscribers found most interesting and vauable:
Free Vector Illustrations And Animations
A cow kidnapped by aliens, a dropped ice cream cone with a sad face, the Lochness monster emerging from the water. These are some of the fun error state animations that the folks at Pixel True Studios offer for free download in their set of vector illustrations and animations.

Apart from error state animations, the set includes illustrations, icons, and animations to depict everything a web project could call for: security, search, contact, e-commerce, SEO, and a lot more. The illustrations are available as SVGs, the animations are made with Lottie. Released under an MIT License, you can use them for free both in personal and commercial projects. A great way to add a fun and friendly touch to a design. (cm)

A Journey Through Japanese And Cyrillic Web Design
The web spans the entire globe, however, when we talk about web design, the examples and showcases usually revolve around the 26 characters of the Latin alphabet. Other writing systems are often not part of the discussion — with the effect that a lot of brilliant websites stay unnoticed for a lot of us. Time to change that.

If you’re up for a journey through Japanese web design, Responsive Web Design JP is for you. The examples in the collection shine with a unique lightness and concentration on the essential, and, even if you don’t master Japanese, you can browse the showcase by technique.
Another inspiring site that lets us take a look beyond the Latin writing system is Cyrillic Design, dedicated to sites that use Cyrillic typefaces. Lots of beautiful designs can be discovered in there and it’s particularly interesting to see how type is used to make bold statements. Two fantastic reminders to look for inspiration outside of our own comfort zones. (cm)

Cloud Diagrams Made Easy
Making complex relationships and contexts visible, a well-made diagram can often replace lengthy explanations. A fantastic little tool to help you next time you need to visualize a cloud architecture, comes from Mark Mankarious: Isoflow.

Isoflow works right in the browser and provides an easy-to-use interface that makes creating beautiful, isometric diagrams a matter of only a few minutes. Just drag and drop the elements you need onto the canvas, connect them, and add labels. Once you’re happy with the result, you can export the diagram for print or web — thanks to vector icons, it will look sharp at any size. A true timesaver. (cm)

Website Features That Annoy Screen Reader Users
A missing alt caption, an auto-playing video, unlabelled buttons, poor use of headings, inaccessible web forms — what might seem like a small issue for sighted users can make the difference between being able to use a website independently or not for blind and visually impaired people. Holly Tuke knows this from her own experience.

To raise awareness for common accessibility issues, Holly summarized five annoying website features she faces as a screen reader user every single day, and, of course, how to fix them. Little details that make a huge difference. (cm)

Accessibility For Teams
Accessibility goes far beyond the code, so when it comes to delivering accessible websites, each person in a team has their specific responsibilities. If you feel that your team hasn’t found the right strategy to tackle accessibility yet, Peter van Grieken’s guide “Accessibility for teams” has got your back.

The guide consists of six parts, with each one of them aimed at the different specialists in your team: product managers, content designers, UX designers, visual designers, and front-end developers, plus a guide on accessibility testing. The guide is still a work in progress, the parts for product managers and UX designers have already been released. A great resource that helps incorporate accessibility into your team’s workflow from the ground up. (cm)

Design Systems From All Over The Globe
An effective design system helps you reuse UI components to create coherent user experiences across all aspects of a product. If you need some inspiration for what your design system could look like, Josh Cusick started the project Design Systems For Figma, a collection of design systems from all over the globe.

Atlassian, Audi, Uber, the City of Chicago, Apple, Goldman Sachs, Slack — these are only some of the 45 companies featured in the collection. All of the design systems were created in Figma, so if you are a Figma user yourself, you can duplicate or download a file to inspect how the design system was made. A precious look into how other design teams work. (cm)

The Past, Present, And Future Of Interfaces
Why do we interface? Back in 2018, product designer Ehsan Noursalehi presented a talk on the topic at a meetup. This summer, after several months of strict quarantine gave him a new perspective on our relationship with technology, he decided to convert his observations and questions into an online micro book.

Why Do We Interface takes a historical look at interfaces to build an understanding of how they allow us to utilize information in such powerful ways that they can fundamentally change what it means to be human. A thought-provoking journey from the failed Apple Newton of 1993 to the voice-first interfaces of today and the challenges the future might bring, as well as a precious reminder about the true purpose of a designer’s job. (cm)

Generate Blobs With Ease
A blob is a blob is a blob? Not at all! Lokesh Rajendran built a cool, minimalist tool that lets you generate beautiful blob shapes for web and Flutter apps with ease.

Blobs, as the blob generator is called, creates random or fixed blobs for you, all you need to do is adjust the level of randomness and complexity. You can also customize the blobs’ color, of course, and, if you like, define a gradient for the filling or outline. To use the blob right away in a project or customize it further by animating or clipping it, the generator provides you with the SVG and Flutter code. Perfect for a nice little UI animation, as a background for an icon, a frame, or whatever else you can think of. Happy blobbing! (cm)

Accelerating JavaScript In The Browser
Once made fun of for its slowness, JavaScript became one of the most optimized and performant dynamic languages out there. But how can you get as much performance out of it as possible in an actual project? Jonathan Dinu shares a roadmap for determining how to speed up your JavaScript application.

At the core of the roadmap is a flowchart to help you assess what type of performance bottleneck you’re dealing with and how to solve it. Jonathan explores various options of leveraging browser native APIs and technologies to accelerate JavaScript execution and gives tips when a solution is beneficial and when it might even hurt performance. A deep dive into streaming data, web workers, GPU, and Web Assembly. (cm)

Design Your Own 2D Game
Arcades, shooters, adventures, puzzles — do you have a sweet spot for games? Then Ct.js is for you. The free and open-source game framework and editor lets you create 2D games of any genre while putting your JavaScript skills to the test.

Based on WebGL, the modular library is coupled with a visual editor that helps you bring your game to life. Ct.js is designed to be beginner-friendly, so there are tutorials, editable examples, and demos to tinker with; more advanced users can even add their own JavaScript library to it to expand the possibilities. The documentation features a concise introduction to the world of variables, properties, conditional statements, loops, and operations, making Ct.js a great resource for students who are just taking their first steps in coding. (cm)

A React-Powered Node Editor To Extract Business Logic
Does your app serve users with very different business logics? Do you frequently create “feature flags” to turn parts of your code on and off for different users? Is your business logic complicated and hard to maintain? If you answered one of these questions with “yes”, you might want to take a look at Flume.

The React-powered node editor and runtime engine helps you build apps that are resilient to changing requirements by modeling your business logic as a JSON graph. Flume’s sleek UI makes it easy to create and edit the graphs and its fast engine runs your logic anywhere — in a browser, on your server, in any JavaScript environment, and, if you’re not using a node server, in any environment that supports JSON. Flume is released under an MIT Open-Source license. (cm)

More Smashing Stuff

In the past few years, we were very lucky to have worked together with some talented, caring people from the web community to publish their wealth of experience as printed books that stand the test of time. Paul and Alla are some of these people. Have you checked out their books already?

Click!A practical guide on how to encourage clicks without shady tricks.Add to cart $39

Design SystemsA practical guide to creating design languages for digital products.
Add to cart $39

Front-End & UX WorkshopsInteractive, live online sessions, broken into 2.5h segments and a friendly Q&A.Jump to topics →

Visit source: Post courtesy of : SmashingConfs, Inspiring Talks And Birthday Cake

Categories
Uncategorized

Comparing Styling Methods In Next.js

As you might be aware, there are many differing perspectives on CSS-in-JS, and we all have an opinion of the topic in one way or the other that might be quite different from the opinions of framework authors. Next.js is one of the recommended tool-chains when creating a new React app. Tools like Next have…

Want to Read more ? As you might be aware, there are many differing perspectives on CSS-in-JS, and we all have an opinion of the topic in one way or the other that might be quite different from the opinions of framework authors.
Next.js is one of the recommended tool-chains when creating a new React app. Tools like Next have a simple goal of abstracting away commonly redundant tasks when writing a React app. This helps developers focus more on writing code than reinventing the wheel. While this is usually a good thing, it can also be a little tedious to get started with. For one, there’s a hurdle to cross by learning about the abstractions, and while there are a bevy of that in Next (Routing, Data Fetching…), one often overlooked is Styling.
To serve a wider audience, Next.js supports a myriad of ways to style your components. Whether you belong to the Utility first or CSS-in-JS party isn’t much of Next’s concern, its concern is how you inject your choice into its API.
The goal of this article is to help you understand how to set up styling in your Next app. We’ll be using different methods to handle the comparison. We’ll implement the different types of styling in a book application I have set up. The styling methods we’ll be looking at include:

Global CSS,
SASS/SCSS,
Component-Level SASS/SCSS,
Component-Level CSS (CSS Modules),
Styled-Components,
Styled JSX,
Emotion.

Prerequisite
Before we begin our styling tour, there are some Next nuances you need to acquaint yourself with.

_app.jsThis is a custom component that resides in the pages folder. Next.js uses this component to initialize pages.
_document.jsLike _app.js, _document.js is a custom component that Next.js uses to augment your applications <html> and <body> tags. This is necessary because Next.js pages skip the definition of the surrounding document’s markup.
_.babelrcWhen present, Next.js uses this file as the single source of truth for some internal configuration and gives you permission to extend it.

Keep in mind that if you have your server running before adding the _app.js file, then you need to restart it.
Creating A Next App With create-next-app
Creating a Next app with create-next-app is as simple as following the steps below:

Install create-next-app globally.

yarn global add create-next-app // Installs create-next-app globally

Create a new Next app named styling-in-next.

create-next-app styling-in-next // Creates a new Next app named styling-in-next

Change directory into the new site.

cd styling-in-next // Switch directory into the new Next app

Run the site.

yarn dev -p 3000 // Instruct Next to run on port 3000

Refer to the documentation for more information on creating and running a Next app.

The app should now be running on http://localhost:3000.

Demo Repository
As we go along we’ll be building a contrived Bookshelf by applying different styling methods to each books. The end result will look like:

The image above shows 6 books; each book will have its own components, then we’ll apply a specific style type to each specific book, i.e. Book 1 will make use of a global style while Book 2 will make use of another. This way we’ll see how each of these styles work and how they can be used. This will help you in making a better decision on what option to choose.
To make things simple, I’ve scaffolded a GitHub repository for you to follow along. You can grab it here.
Some changes have also been made to the default starter generated by create-next-app. Folders like emotion, global, modules, styled-components etc. have been added to the styles folder — with their corresponding style files — as well as a components directory with multiple components.

The index.js file has been modified to import and render the needed components, and each of the components has a similar structure as shown in the image below.

If you cloned and ran the demo repository, here’s what your page should look like:

With all that out of the way, let’s get styling.
Global Style
One of the common things you’d normally do when you start a new web project is to reset or normalize your CSS so there’s a uniform starting position among browsers. This is a perfect example of using Global CSS without worrying about scoping.

Update styles/global/globals.css with this extended Minimal CSS Reset.

/ styles/global/globals.css /
html {
box-sizing: border-box;
font-size: 16px;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
,
:before,
*:after {
box-sizing: inherit;
}
body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
ol,
ul {
margin: 0;
padding: 0;
font-weight: normal;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: bold;
}

ol,
ul {
list-style: none;
}

img {
max-width: 100%;
height: auto;
}

a {
color: inherit;
text-decoration: none;
}

Import the CSS reset styles/global/globals.css in pages/_app.js.

// pages/_app.js
import “../styles/global/globals.css”;

function MyApp({Component, pageProps}) {
return <Component {…pageProps} />;
}

export default MyApp;

Global styles can only be imported in the pages/_app.js. This is directly logical because these styles will apply to all pages and components in your application — regardless of where you import them — so it is better to have a single source of [import] truth to keep things straightforward, and/or if something goes wrong.
At this point, we do not have a lot of visual changes to our Bookshelf since we have only made normalization changes. One thing you might notice is the font and spacing changes.

SASS/SCSS
Next.js also allows styling with SASS with the .sass or .scss extension. Installing Sass is a requirement. Just like global styles, they can only be imported in pages/_app.js.

Install the Sass package.

yarn add sass

Update styles/scss/bookshelf.scss.

// styles/scss/bookshelf.scss
.the-bookshelf {
width: 100vw;
height: 100vh;
background-color: #e3e3e3;
display: flex;
justify-content: center;
align-items: center;

.bookshelf-wrap {
> .bookshelf {
box-shadow: inset 0 -20px #7b5019;
padding-bottom: 20px;
display: flex;
align-items: flex-end;
}

[class*=”book”] {
font-size: 32px;
letter-spacing: -0.045em;
display: flex;
transition: 0.2s;

&:hover {
transform: none;
}
}

.book-info {
text-transform: uppercase;
writing-mode: sideways-rl;
display: flex;
justify-content: space-around;
flex: 1;
align-items: center;
font-weight: bold;
padding: 16px 0;

.title {
font-weight: inherit;
font-size: 20px;
}

.author {
font-weight: inherit;
font-size: 15px;
}
}
}
}

Also update styles/sass/bookone.sass and styles/sass/booktwo.sass like so:

// styles/sass/bookone.sass
.book-one
color: #f00
width: 78px
height: 350px
transform: rotate(-4deg)
margin-left: 16px
margin-right: 23px
background-color: black

// styles/sass/booktwo.sass
.book-two
color: #781e0b
width: 38px
height: 448px
margin-right: 23px
background-color: #ffab44

SASS (.sass) is based on indentation. To make formatting easier, you can install this VSCode Extension for SASS files support (formatting, syntax highlighting…)

Import the three style files — styles/scss/bookshelf.scss , styles/sass/bookone.sass, and styles/sass/booktwo.sass — in pages/_app.js.

// pages/_app.js
import “../styles/globals.css”;
import “../styles/scss/bookshelf.scss”;
import “../styles/sass/bookone.sass”;
import “../styles/sass/booktwo.sass”;

function MyApp({Component, pageProps}) {
return ;
}

export default MyApp;

Our Bookshelf is beginning to take shape. With the styles applied, the first and second book should be styled and displayed as intended.

CSS Modules
CSS Modules is a component-level CSS, that comes built-in with Next and can be activated by naming the style files with the .module.css extension. It is also possible to use CSS Modules with SASS/SCSS with the .module.sass or .module.scss extension.
Let’s style the components/BookThree.js component with it.

Update styles/modules/BookThree.module.css.

/* styles/modules/BookThree.module.css */
.book-three {
color: #df66c3;
width: 106px;
height: 448px;
margin-right: 23px;
background-color: #153086;
transform: rotate(-4deg);
}

Import styles/modules/BookThree.module.css in components/BookThree.js, and apply the .book-three class.

// components/BookThree.js
import BookThreeStyles from “../styles/modules/BookThree.module.css”;

export default function BookThree() {
return (
<div className={BookThreeStyles[“book-three”]}>
<div className=”book-info”>
<p className=”title”>the revolt of the public</p>
<p className=”author”>Martin Gurri</p>
</div>
</div>
);
}

Accessing class names in CSS Modules is similar to Property Accessors in JavaScript — with the dot or bracket notation. Here we import BookThreeStyles and then use the bracket notation to apply the style we have in styles/modules/BookThree.module.css file.
If the selector (in this case, class name) was properly accessed, the third book should be styled now.

Emotion
Emotion is a CSS-in-JS library and like any other CSS-in-JS, allows you to write CSS styles with JavaScript.
Let’s style the components/BookFour.js component with it.

Install the packages: @emotion/core, @emotion/styled, emotion, emotion-server.

yarn add @emotion/core @emotion/styled emotion emotion-server

Update styles/emotion/StyledBookFour.js.

// styles/emotion/StyledBookFour.js
import styled from “@emotion/styled”;

export const StyledBookFour = styled.div`
color: white;
width: 38px;
height: 400px;
margin-left: 20px;
margin-right: 10px;
background-color: #2faad2;
transform: rotate(4deg);
`;

After importing styled from @emotion/styled, we export the StyledBookFour styled component — not to be confused with the other CSS-in-JS Styled Component — enhanced with the styled emotion method as in styled.div. Then we can use <StyledBookFour/> as in the next step below.

Learn more about emotion’s styled function.

Using <StyledBookFour/> is similar to how you’d use any other React component. Import styles/emotion/StyledBookFour.js in components/BookFour.js, and apply the StyledBookFour component.

// components/BookFour.js
import {StyledBookFour} from “../styles/emotion/StyledBookFour”;

export default function BookFour() {
return (
<StyledBookFour className=”book-four”>
<div className=”book-info”>
<p className=”title”>the man died</p>
<p className=”author”>wole soyinka</p>
</div>
</StyledBookFour>
);
}

With a sufficient dose of emotion, the fourth book should be thus styled.

Styled JSX
Like Global CSS and CSS-Modules, Styled-JSX works with Next.js without any extra setup required. If it helps, Styled-JSX is also Vercel’s offering of a component-based CSS, the same creators of Next.js.
Let’s style the components/BookFive.js component with it.
To keep things simple, we use the internal mode of styled-jsx here. By passing the jsx prop to the <style/> component, we are able to write as much CSS as we want like we did with .book-five, with the additional benefit of the style being localized to the <BookFive/> component.
// components/BookFive.js
export default function BookFive() {
return (
<div className=”book-five”>
<div className=”book-info”>
<p className=”title”>there was a country</p>
<p className=”author”>Chinua Achebe</p>
</div>
<style jsx>{`
.book-five {
color: #fff;
width: 106px;
height: 448px;
margin-right: 23px;
background-color: #000;
transform: rotate(4deg);
}
`}</style>
</div>
);
}

And just like that, the fifth book takes its styling.

Styled Components
Styled-Component, just like Emotion, is also a CSS-in-JS library that allows you to write CSS styles with JavaScript. Getting it setup is a little bit involved.

First, install babel-plugin-styled-components and styled-components.

yarn add babel-plugin-styled-components styled-components

Create a .babelrc file at the root of your app, and a pages/_document.js file, as shown in the before (left) and after(right) image below.

Update the .babelrc file to include the next/babel preset and include the styled-components plugin, with server-side-rendering (ssr) enabled.

// .babelrc
{
“presets”: [“next/babel”],
“plugins”: [
[
“styled-components”,
{
“ssr”: true
}
]
]
}

Update pages/_document.js by injecting the server-side rendered styles into the <head>.

Keep in mind, the snippet below (pages/_document.js) is a required logic for styled-components to work with Next.js. You almost have to do nothing but copy the logic as pointed out in the styled-components documentation.
// pages/_document.js
import Document from “next/document”;
import {ServerStyleSheet} from “styled-components”;

export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;

try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {…props} />),
});

const initialProps = await Document.getInitialProps(ctx);
return {
…initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
}

After the updates to .babelrc, and pages/_document.js, we can now begin to use styled-components.

Update styles/styled-components/StyledBookSix.js.

styled is an internal utility method that transforms the styling from JavaScript into actual CSS. <StyledBookSix/> is, and, can be used as any other React component.
// styles/StyledBookSix.js
import styled from “styled-components”;

const StyledBookSix = styled.div`
color: #fff;
width: 106px;
height: 448px;
margin-right: 23px;
background-color: rebeccapurple;
`;

export default StyledBookSix;

Learn more about How To Use Styled-Components in React.

Import styles/styled-components/StyledBookSix.js in components/BookSix.js, using the imported styled-components <StyledBookSix/>.

// components/BookSix.js
import StyledBookSix from “../styles/styled-components/StyledBookSix”;

export default function BookSix() {
return (
<StyledBookSix className=”book-six”>
<div className=”book-info”>
<p className=”title”>purple hibiscus</p>
<p className=”author”>chimamanda ngozi adichie</p>
</div>
</StyledBookSix>
);
}

With the first to sixth step completed, the sixth should be styled, and the Bookshelf done:

That’s it.
If all went well, then you should have the complete Bookshelf with the books waiting to be read.

You can grab the complete code on GitHub →

Conclusion
In my own usage with Next.js, Global styles and styled-components have often been sufficient. But there’s no doubt that all these methods have their pros and cons. And as you settle on what method to use, just keep in mind: in the end, it’s all CSS. At this point, I believe you can be able to figure out which pattern best serves you in your next project.
Resources
I find that for learning about setting up styling methods with Next.js, there’s no better place than its official documentation.
But there are also specific repositories for various styling methods. You can go through the various repository to learn more, or check for update, as things may change incognito.

Tailwind CSS
CSS Modules
Less
Stylus
Tailwind CSS with Emotion
Styletron
Glamor
CXS
Aphrodite
Fela
Styled-JSX

Visit source: Post courtesy of : Comparing Styling Methods In Next.js

Categories
Uncategorized

Advanced GraphQL Usage In Gatsby Websites

Before the release of GraphQL in 2015, Representational State Transfer (REST) was the main way to interface with an API. The introduction of GraphQL was therefore a major change in software development. As a modern static site generator, Gatsby leverages GraphQL to provide a concise methodology for bringing in and manipulating data into the framework.…

Want to Read more ? Before the release of GraphQL in 2015, Representational State Transfer (REST) was the main way to interface with an API. The introduction of GraphQL was therefore a major change in software development.
As a modern static site generator, Gatsby leverages GraphQL to provide a concise methodology for bringing in and manipulating data into the framework. In this article, we will take a closer look at GraphQL and how we can integrate it into a Gatsby website by building and implementing advanced data sourcing and transformation in Gatsby. The result is a publisher’s blog that could be used by any publishing firm to share content of their authors.
What Is GraphQL?
Going by the _QL_ in its name, GraphQL is a query language combined with a set of tools created to provide flexibility and efficiency in the way we pull data from a source. With GraphQL, a client/consumer can request exactly the data it requires. The server/provider responds with a JSON response signature matching the requirements specified in the query. It allows us to express our data needs declaratively.
Why Use GraphQL?
As a static site generator, Gatsby stores static files, which makes querying data close to impossible. There are often page components that have to be dynamic like the single blog post page, so the need to pull data from a source and transform it to the needed format would arise, just like having blog posts stored in markdown files. Some plugins provide data from various sources, which leaves you with querying and transforming the required data from a source.
According to a list on gatsby.org, GraphQL is useful in Gatsby to:

Eliminate boilerplate
Push frontend complexities into queries
Provide a perfect solution for the always complex data of a modern-day application
Finally, to remove code bloat, thereby improving performance.

GraphQL Concepts
Gatsby maintains the same ideas of GraphQL as widely used; some of these concepts are:
Schema Definition Language
GraphQL SDL is a type system incorporated into GraphQL, and you can use it to create new types for your data.
We can declare a type for a country, and its attributes could include a name, continent, population, gdp and number of states.
As an example below, we have created a new type with the name of Aleem. It has hobbies which is an array of strings and are not required, but country, marital status, and posts are needed due to the ! they include, also posts references another type, Post.
type Authors {
name: String!,
hobbies: [String]
country: String!
married: Boolean!
posts: [Post!]
}

type Post {
title: String!
body: String!
}

type Query {
author: Author
}

schema {
query: Query
}

Queries
We can use Queries to pull data from a GraphQL source.
Considering a data set like the below
{
data: {
author: [
{
hobbies: [“travelling”, “reading”],
married: false,
country: “Nigeria”,
name: “Aleem Isiaka”,
posts: [
{
title: “Learn more about how to improve your Gatsby website”,
},
{
title: “The ultimate guide to GatsbyJS”,
},
{
title: “How to start a blog with only GatsbyJS”,
},
],
},
],
},
};

We can have a query that to fetch the country and posts from the data:
query {
authors {
country,
posts {
title
}
}
}

The response that we will get should contain JSON data of blog posts with just the title and nothing more:
[
{ country: “Nigeria”, posts: [{…}, {…}, {…}] },
{ country: “Tunisia”, posts: [] },
{ title: “Ghana”, posts: []},
]

We can also use arguments as conditions for a query:
query {
authors (country: “Nigeria”) {
country,
posts {
title
}
}
}

Which should return
[
{ country: “Nigeria”, posts: [{…}, {…}, {…}] }
]

Nested fields can also be queried, like the posts with the Post type, you can ask for just the titles:
query {
authors(country: ‘Nigeria’) {
country,
posts {
title
}
}
}

And it should return any Author type matching Nigeria returning the country and posts array containing objects with just the title field.
Gatsby with GraphQL
To avoid the overhead of having a server/service that serves data that GraphQL can transform, Gatsby executes GraphQL queries at build time. Data is provided to the components during the build process, making them readily available inside the browser without a server.
Still, Gatsby can run as a server that can be queried by other GraphQL clients, like GraphiQL, in a browser.
Gatsby Ways Of Interacting With GraphQL
There are two places where Gatsby can interact with GraphQL, through a gatsby-node.js API file, and through page components.
gatsby-node.js
The createPage API can be configured as a function which will receive a graphql helper as part of the items in the first argument passed to the function.

// gatsby-node.js source: https://www.gatsbyjs.org/docs/node-apis/#createPages
exports.createPages = async ({ graphql, actions }) => {
const result = await graphql(query loadPagesQuery ($limit: Int!) {
allMarkdownRemark(limit: $limit) {
edges {
node {
frontmatter {
slug
}
}
}
}
})
}

In the above code, we have used the GraphQL helper to fetch markdown files from Gatsby’s data layer. And we can inject this to create a page and modify existing data inside the Gatsby data layer.
Page Components
Page components inside of /pages directory or templates rendered by the createPage API action can import graphql from the gatsby module and export a pageQuery. In turn, Gatsby would inject a new prop data into the props of the page component containing the resolved data.
import React from “react”;
import { graphql } from “gatsby”;

const Page = props => {
return {JSON.stringify(props.data)};
};

export const pageQuery = graphql`
query { … }
`;

export default Page;

In Other Components
Other components can import graphql and StaticQuery components from the gatsby module, render the &lt;StaticQuery/> passing query props that implement the Graphql helper and render to get the returned data.
import React from “react”;
import { StaticQuery, graphql } from “gatsby”;

const Brand = props => {
return (
<div>
<h1>{data.site.siteMetadata.title}</h1>
</div>
);
};

const Navbar = props => {
return (
<StaticQuery
query={graphql`
query {
site {
siteMetadata {
title
}
}
}
`}
render={data => <Brand data={data} {…props} />}
/>
);
};

export default Navbar;

Building A Modern And Advanced Gatsby Publishing Blog
In this section we will walk through a process of creating a blog that supports tagging, categorization, pagination and grouping articles by authors. We will use plugins of Gatsby’s ecosystem to bring in some features and use logics in GraphQL queries to make a publisher’s blog that is ready for multiple author publications.
The final version of the blog we will build can be found here, also the code is hosted on Github.
Initializing The Project
Like any Gatsby website, we initialize from a starter, here we will be using the advanced starter but modified to cater for our use case.
First clone this Github repo, change the working branch to the dev-init, and then run npm run develop from the project’s folder to start the development server making the site available at http://localhost:8000.
git clone git@github.com:limistah/modern-gatsby-starter.git
cd modern-gatsby-starter
git checkout dev-init
npm install
npm run develop

Visiting http://localhost:8000 will show the default homepage for this branch.
Creating Blog Posts Content
Some post content included in the project repository could be accessed at the dev-blog-content branch. The organization of the content directory looks like this /content/YYYY_MM/DD.md, which group posts by the created month of a year.
The blog post content has title, date, author, category, tags as its frontmatter, which we will use to distinguish a post and do some further processing on, while the rest of the content is the body of the post.

title: “Bold Mage”
date: “2020-07-12”
author: “Tunde Isiaka”
category: “tech”
tags:
– programming
– stuff
– Ice cream
– other

# Donut I love macaroon chocolate bar

Oat cake marshmallow lollipop fruitcake I love jelly-o. Gummi bears cake wafer chocolate bar pie. Marshmallow pastry powder chocolate cake candy chupa chups. Jelly beans powder soufflé biscuit pie macaroon chocolate cake. Marzipan lemon drops chupa chups sweet cookie sesame snaps jelly halvah.

Displaying Post Content
Before we can render our Markdown posts in HTML, we have to do some processing. First, loading the files into the Gatsby storage, parsing the MD to HTML, linking image dependencies, and likes. To ease this, we will use a host of plugins by the Gatsby ecosystem.
We can use these plugins by updating the gatsby-config.js at the root of the project to look like this:
module.exports = {
siteMetadata: {},
plugins: [
{
resolve: “gatsby-source-filesystem”,
options: {
name: “assets”,
path: `${__dirname}/static/`,
},
},
{
resolve: “gatsby-source-filesystem”,
options: {
name: “posts”,
path: `${__dirname}/content/`,
},
},
{
resolve: “gatsby-transformer-remark”,
options: {
plugins: [
{
resolve: `gatsby-remark-relative-images`,
},
{
resolve: “gatsby-remark-images”,
options: {
maxWidth: 690,
},
},
{
resolve: “gatsby-remark-responsive-iframe”,
},
“gatsby-remark-copy-linked-files”,
“gatsby-remark-autolink-headers”,
“gatsby-remark-prismjs”,
],
},
},
],
};

We have instructed gatsby to include the plugins to assist us in carrying out some actions, notably pulling files from the /static folder for static files and /content for our blog posts. Also, we have included a remark transformer plugin to transform all files ending with .md or .markdown into a node with all the fields of remark for rendering markdown as HTML.
Lastly, we included plugins in operating on the nodes generated by gatsby-transformer-remark.
Implementing The gatsby-config.js API File
Moving forward, inside of gatsby-node.js in the project root, we can export a function named createPage and have the content of the function to use the graphQL helper to pull nodes from the content layer of GatsbyJS.
The first update to this page would include ensuring that we have a slug set on the MarkDown remark nodes. We will listen to the onCreateNode API and get the node created to determine if it is a type of MarkdownRemark before we update the node to include a slug and date accordingly.

const path = require(“path”);
const _ = require(“lodash”);
const moment = require(“moment”);

const config = require(“./config”);

// Called each time a new node is created
exports.onCreateNode = ({ node, actions, getNode }) => {
// A Gatsby API action to add a new field to a node
const { createNodeField } = actions;
// The field that would be included
let slug;
// The currently created node is a MarkdownRemark type
if (node.internal.type === “MarkdownRemark”) {
// Recall, we are using gatsby-source-filesystem?
// This pulls the parent(File) node,
// instead of the current MarkdownRemark node
const fileNode = getNode(node.parent);
const parsedFilePath = path.parse(fileNode.relativePath);
if (
Object.prototype.hasOwnProperty.call(node, “frontmatter”) &&
Object.prototype.hasOwnProperty.call(node.frontmatter, “title”)
) {
// The node is a valid remark type and has a title,
// Use the title as the slug for the node.
slug = /${_.kebabCase(node.frontmatter.title)};
} else if (parsedFilePath.name !== “index” && parsedFilePath.dir !== “”) {
// File is in a directory and the name is not index
// e.g content/2020_02/learner/post.md
slug = /${parsedFilePath.dir}/${parsedFilePath.name}/;
} else if (parsedFilePath.dir === “”) {
// File is not in a subdirectory
slug = /${parsedFilePath.name}/;
} else {
// File is in a subdirectory, and name of the file is index
// e.g content/2020_02/learner/index.md
slug = /${parsedFilePath.dir}/;
}

if (Object.prototype.hasOwnProperty.call(node, “frontmatter”)) {
if (Object.prototype.hasOwnProperty.call(node.frontmatter, “slug”))
slug = /${_.kebabCase(node.frontmatter.slug)};
if (Object.prototype.hasOwnProperty.call(node.frontmatter, “date”)) {
const date = moment(new Date(node.frontmatter.date), “DD/MM/YYYY”);
if (!date.isValid)
console.warn(WARNING: Invalid date., node.frontmatter);
// MarkdownRemark does not include date by default

createNodeField({ node, name: “date”, value: date.toISOString() });
}
}
createNodeField({ node, name: “slug”, value: slug });
}
};

The Post Listing
At this point, we can implement the createPages API to query for all markdowns and create a page with the path as the slug we have created above. See it on Github.

//gatsby-node.js
// previous code

// Create Pages Programatically!
exports.createPages = async ({ graphql, actions }) => {
// Pulls the createPage action from the Actions API
const { createPage } = actions;

// Template to use to render the post converted HTML
const postPage = path.resolve(“./src/templates/singlePost/index.js”);

// Get all the markdown parsed through the help of gatsby-source-filesystem and gatsby-transformer-remark
const allMarkdownResult = await graphql({
allMarkdownRemark {
edges {
node {
fields {
slug
}
frontmatter {
title
tags
category
date
author
}
}
}
}
});

// Throws if any error occur while fetching the markdown files
if (allMarkdownResult.errors) {
console.error(allMarkdownResult.errors);
throw allMarkdownResult.errors;
}

// Items/Details are stored inside of edges
const postsEdges = allMarkdownResult.data.allMarkdownRemark.edges;

// Sort posts
postsEdges.sort((postA, postB) => {
const dateA = moment(
postA.node.frontmatter.date,
siteConfig.dateFromFormat
);

const dateB = moment(
postB.node.frontmatter.date,
siteConfig.dateFromFormat
);

if (dateA.isBefore(dateB)) return 1;
if (dateB.isBefore(dateA)) return -1;

return 0;
});

// Pagination Support for posts
const paginatedListingTemplate = path.resolve(
“./src/templates/paginatedListing/index.js”
);

const { postsPerPage } = config;
if (postsPerPage) {
// Get the number of pages that can be accommodated
const pageCount = Math.ceil(postsEdges.length / postsPerPage);

// Creates an empty array
Array.from({ length: pageCount }).forEach((value, index) => {
const pageNumber = index + 1;
createPage({
path: index === 0 ? /posts : /posts/${pageNumber}/,
component: paginatedListingTemplate,
context: {
limit: postsPerPage,
skip: index * postsPerPage,
pageCount,
currentPageNumber: pageNumber,
},
});
});
} else {
// Load the landing page instead
createPage({
path: /,
component: landingPage,
});
}
};

In the createPages function, we use the graphql helper provided by Gatsby to query data from the content layer. We used a standard Graphql query to do this and passed a query to get content from allMarkdownRemark type. Then moved forward to sort the posts by the created date.
We then pulled a postPerPage property from an imported config object, which is used to chunk down the total posts to the specified number of posts for a single page.
To create a listing page that supports pagination, we need to pass in the limit, pageNumber, and the number of pages to skip to the component that would be rendering the list. We are achieving this using the context property of the createPage config object. We will be accessing these properties from the page to make another graphql query to fetch posts within the limit.
We can also notice that we use the same template component for the listing, and only the path is changing utilizing the index of the chunk array we had defined ahead. Gatsby will pass the necessary data for a given URL matching /{chunkIndex}, so we can have / for the first ten posts, and /2 for the next ten posts.

Rendering Post Listing
The component rendering these pages could be found at src/templates/singlePost/index.js of the project folder. It also exports a graphql helper which pulls the limit and page query parameter it received from the createPages process to query gatsby for posts within the range of the current page.

import React from “react”;
import { graphql, Link } from “gatsby”;
import Layout from “../../layout”;
import PostListing from “../../components/PostListing”;
import “./index.css”;

const Pagination = ({ currentPageNum, pageCount }) => {
const prevPage = currentPageNum – 1 === 1 ? “/” : /${currentPageNum – 1}/;
const nextPage = /${currentPageNum + 1}/;
const isFirstPage = currentPageNum === 1;
const isLastPage = currentPageNum === pageCount;

return (
<div className=”paging-container”>
{!isFirstPage && <Link to={prevPage}>Previous</Link>}
{[…Array(pageCount)].map((_val, index) => {
const pageNum = index + 1;
return (
<Link
key={listing-page-${pageNum}}
to={pageNum === 1 ? “/” : /${pageNum}/}
>
{pageNum}
</Link>
);
})}
{!isLastPage && <Link to={nextPage}>Next</Link>}
</div>
);
};

export default (props) => {
const { data, pageContext } = props;
const postEdges = data.allMarkdownRemark.edges;
const { currentPageNum, pageCount } = pageContext;

return (
<Layout>
<div className=”listing-container”>
<div className=”posts-container”>
<PostListing postEdges={postEdges} />
</div>

<Pagination pageCount={pageCount} currentPageNum={currentPageNum} />
</div>
</Layout>
);
};

/* eslint no-undef: “off” */
export const pageQuery = graphqlquery ListingQuery($skip: Int!, $limit: Int!) {
allMarkdownRemark(
sort: { fields: [fields___date], order: DESC }
limit: $limit
skip: $skip
) {
edges {
node {
fields {
slug
date
}
excerpt
timeToRead
frontmatter {
title
tags
author
category
date
}
}
}
}
};

The Post Page
To view the content of a page, we need to programmatically create the page inside the gatsby-node.js API File. First, we have to define a new component to render the content with, for this, we have src/templates/singlePost/index.jsx.

import React from “react”;
import { graphql, Link } from “gatsby”;
import _ from “lodash”;
import Layout from “../../layout”;
import “./b16-tomorrow-dark.css”;
import “./index.css”;
import PostTags from “../../components/PostTags”;

export default class PostTemplate extends React.Component {
render() {
const { data, pageContext } = this.props;
const { slug } = pageContext;
const postNode = data.markdownRemark;
const post = postNode.frontmatter;
if (!post.id) {
post.id = slug;
}

return (
<Layout>
<div>
<div>
<h1>{post.title}</h1>
<div className=”category”>
Posted to{” “}
<em>
<Link
key={post.category}
style={{ textDecoration: “none” }}
to={/category/${_.kebabCase(post.category)}}
>
<a>{post.category}</a>
</Link>
</em>
</div>
<PostTags tags={post.tags} />
<div dangerouslySetInnerHTML={{ __html: postNode.html }} />
</div>
</div>
</Layout>
);
}
}

/* eslint no-undef: “off” */
export const pageQuery = graphqlquery BlogPostBySlug($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
timeToRead
excerpt
frontmatter {
title
date
category
tags
}
fields {
slug
date
}
}
};

Again, we are using a graphQL helper to pull out a page by a slug query that would be sent to the page through the createPages API.
Next, we should have the below code added to gatsby-node.js at the end of the createPages API function.

// Template to use to render the post converted HTML
const postPage = path.resolve(“./src/templates/singlePost/index.jsx”);

// Loops through all the post nodes
postsEdges.forEach((edge, index) => {
// Create post pages
createPage({
path: edge.node.fields.slug,
component: postPage,
context: {
slug: edge.node.fields.slug,
},
});
});

And we could visit ‘/{pageSlug}’ and have it render the content of the markdown file for that page as HTML. As an example, http://localhost:8000/the-butterfly-of-the-edge should load the converted HTML for the markdown at: content/2020_05/01.md, similar to all valid slugs. Great!

Rendering Categories And Tags
The single post template component has a link to a page in the format /categories/{categoryName} to list posts with similar categories.
We can first catch all the categories and tags as we build the single post page in the gatsby-node.js file, then create pages for each caught category/tag passing the category/tag name.
A modification to the section for creating single post page in the gatsby-node.js looks like this:
const categorySet = new Set();
const tagSet = new Set();

const categoriesListing = path.resolve(
“./src/templates/categoriesListing/index.jsx”
);
// Template to use to render posts based on categories
const tagsListingPage = path.resolve(“./src/templates/tagsListing/index.jsx”);

// Loops through all the post nodes
postsEdges.forEach((edge, index) => {
// Generate a list of categories
if (edge.node.frontmatter.category) {
categorySet.add(edge.node.frontmatter.category);
}

// Generate a list of tags
if (edge.node.frontmatter.tags) {
edge.node.frontmatter.tags.forEach((tag) => {
tagSet.add(tag);
});
}

// Create post pages
createPage({
path: edge.node.fields.slug,
component: postPage,
context: {
slug: edge.node.fields.slug,
},
});
});

And inside the component for listing posts by tags, we can have the pageQuery export query graphql for posts, including that tag in its tags list. We will use the filter function of graphql and the $in operator to achieve this:
// src/templates/tagsListing/

import React from “react”;
import { graphql } from “gatsby”;
import Layout from “../../layout”;
import PostListing from “../../components/PostListing”;

export default ({ pageContext, data }) => {
const { tag } = pageContext;
const postEdges = data.allMarkdownRemark.edges;
return (
<Layout>
<div className=”tag-container”>
<div>Posts posted with {tag}</div>
<PostListing postEdges={postEdges} />
</div>
</Layout>
);
};

/* eslint no-undef: “off” */
export const pageQuery = graphql`
query TagPage($tag: String) {
allMarkdownRemark(
limit: 1000
sort: { fields: [fields___date], order: DESC }
filter: { frontmatter: { tags: { in: [$tag] } } }
) {
totalCount
edges {
node {
fields {
slug
date
}
excerpt
timeToRead
frontmatter {
title
tags
author
date
}
}
}
}
}
`;

And we have the same process in the categories listing component, and the difference is that we only need to find where the categories match precisely with what we pass to it.
// src/templates/categoriesListing/index.jsx
import React from “react”;
import { graphql } from “gatsby”;
import Layout from “../../layout”;
import PostListing from “../../components/PostListing”;

export default ({ pageContext, data }) => {
const { category } = pageContext;
const postEdges = data.allMarkdownRemark.edges;
return (
<Layout>
<div className=”category-container”>
<div>Posts posted to {category}</div>
<PostListing postEdges={postEdges} />
</div>
</Layout>
);
};

/* eslint no-undef: “off” */
export const pageQuery = graphql`
query CategoryPage($category: String) {
allMarkdownRemark(
limit: 1000
sort: { fields: [fields___date], order: DESC }
filter: { frontmatter: { category: { eq: $category } } }
) {
totalCount
edges {
node {
fields {
slug
date
}
excerpt
timeToRead
frontmatter {
title
tags
author
date
}
}
}
}
}
`;

Noticeable, inside both of the tags and categories components, we render links to the single post page for further reading of a post’s content.

Adding Support For Authors
To support multiple authors, we have to make some modifications to our post content and introduce new concepts.
Load JSON Files
First, we should be able to store the content of authors in a JSON file like this:
{
“mdField”: “aleem”,
“name”: “Aleem Isiaka”,
“email”: “aleem.isiaka@gmail.com”,
“location”: “Lagos, Nigeria”,
“avatar”: “https://api.adorable.io/avatars/55/abott@adorable.png”,
“description”: “Yeah, I like animals better than people sometimes… Especially dogs. Dogs are the best. Every time you come home, they act like they haven’t seen you in a year. And the good thing about dogs… is they got different dogs for different people.”,
“userLinks”: [
{
“label”: “GitHub”,
“url”: “https://github.com/limistah/modern-gatsby-starter”,
“iconClassName”: “fa fa-github”
},
{
“label”: “Twitter”,
“url”: “https://twitter.com/limistah”,
“iconClassName”: “fa fa-twitter”
},
{
“label”: “Email”,
“url”: “mailto:aleem.isiaka@gmail.com”,
“iconClassName”: “fa fa-envelope”
}
]
}

We would be storing them in an author’s directory in the root of our project as /authors. Notice that the author JSON has mdField that would be the unique identifier to the author field we will be introducing to the markdown blog content; this ensures that authors can have multiple profiles.
Next, we have to update gatsby-config.js plugins instructing gatsby-source-filesystem to load the content from the authors/ directory into the Files Node.
// gatsby-config.js
{
resolve: `gatsby-source-filesystem`,
options: {
name: “authors”,
path: `${__dirname}/authors/`,
},
}

Lastly, we will install gatsby-transform-json to transform JSON files created for easy handling and proper processing.
npm install gatsby-transformer-json –save

And include it inside the plugins of gatsby-config.js,
module.exports = {
plugins: [
// …other plugins
`gatsby-transformer-json`
],
};

Querying And Creating Authors Page
To begin with, we need to query all of the authors in our authors/ directory inside of gatsby-config.js that have been loaded into the data layer, we should append the code below to createPages API function
const authorsListingPage = path.resolve(
“./src/templates/authorsListing/index.jsx”
);

const allAuthorsJson = await graphql(`
{
allAuthorsJson {
edges {
node {
id
avatar
mdField
location
name
email
description
userLinks {
iconClassName
label
url
}
}
}
}
}
`);

const authorsEdges = allAuthorsJson.data.allAuthorsJson.edges;
authorsEdges.forEach((author) => {
createPage({
path: `/authors/${_.kebabCase(author.node.mdField)}/`,
component: authorsListingPage,
context: {
authorMdField: author.node.mdField,
authorDetails: author.node,
},
});
});

In this snippet, we are pulling all the authors from the allAuthorsJson type, then, calling forEach on the nodes to create a page where we pass the mdField to distinguish the author and the authorDetails for full information about the author.
Rendering Author’s Posts
In the component rendering the page which could be found at src/templates/authorsListing/index.jsx, we have the below content for the file
import React from “react”;
import { graphql } from “gatsby”;
import Layout from “../../layout”;
import PostListing from “../../components/PostListing”;
import AuthorInfo from “../../components/AuthorInfo”;

export default ({ pageContext, data }) => {
const { authorDetails } = pageContext;
const postEdges = data.allMarkdownRemark.edges;
return (
<Layout>
<div>
<h1 style={{ textAlign: “center” }}>Author Roll</h1>
<div className=”category-container”>
<AuthorInfo author={authorDetails} />
<PostListing postEdges={postEdges} />
</div>
</div>
</Layout>
);
};

/* eslint no-undef: “off” */
export const pageQuery = graphql`
query AuthorPage($authorMdField: String) {
allMarkdownRemark(
limit: 1000
sort: { fields: [fields___date], order: DESC }
filter: { frontmatter: { author: { eq: $authorMdField } } }
) {
totalCount
edges {
node {
fields {
slug
date
}
excerpt
timeToRead
frontmatter {
title
tags
author
date
}
}
}
}
}
`;

In the above code, we exported the pageQuery like we do, to create a GraphQL query to fetch posts matched by an author, we are using the $eq operator to achieve this are generating links to a single post page for further reading.

Conclusion
In Gatsby, we can query any data that exists inside of its data access layer with the use of GraphQL query and pass variables around using some constructs defined by the architecture of Gatsby. we have seen how we could use the graphql helper in various places and understand widely used patterns for querying data in Gatsby’s websites with the help of GraphQL.
GraphQL is very powerful and could do other things like data mutation on a server. Gatsby does not need to update its data at runtime, so it does not support the mutation feature of GraphQL.
GraphQL is a great technology, and Gatsby makes it very interesting to use in their framework.
References

Gatsby support for GraphQL
Why Gatsby uses GraphQL
GraphQL concepts in Gatsby
How To GraphQL: Basic Concepts
Schema Definition Language In GraphQL
An Introduction To GraphQL
Gatsby Advanced Starter

Visit source: Post courtesy of : Advanced GraphQL Usage In Gatsby Websites

Categories
Uncategorized

Designing For Attention

We face many competing interests for users’ time and attention. If we factor in perceptions of dwindling human attention spans, we might speculate capturing and holding users’ attention is based on luck as much as sound design. However, we can incorporate meaningful tactics into our design to ensure we grab users’ attention. This is critical,…

Want to Read more ? We face many competing interests for users’ time and attention. If we factor in perceptions of dwindling human attention spans, we might speculate capturing and holding users’ attention is based on luck as much as sound design. However, we can incorporate meaningful tactics into our design to ensure we grab users’ attention. This is critical, we won’t have users if we don’t have their attention.
I’ll cover some of these tactical design elements. I’ll also discuss the importance of understanding why and how long we want our users’ attention, in order to make sure we create products that are meaningful and in line with users’ best interests.
What Is Attention?
Cognitive psychology researchers who have written books on attention have struggled to pinpoint a single definition (Styles, 2005). I will use the word attention to mean gaining your users’ mental awareness long enough for them to interpret, understand, and make a decision based on the information your product is presenting — visually, physically, or audibly (unless your website or smartphone app uses smell or taste as well).
Researchers have done a fair job of defining two sub-types of attention we should care about as design practitioners:

Transient AttentionThis type of attention is brief, perhaps even thought of as a quick distraction, that attracts someone’s attention. Think of a flash of light that draws your attention and then quickly disappears.
Sustained AttentionThis is what we think of when we talk about focus and the ability to concentrate; deep attention that allows you to intake and process information or perform a task requiring a longer duration to complete.

Neither type of attention is superior. You might only need a split second to alert a user to a change in status, or you might need users to comprehend complex material and watch a video that lasts 15 minutes or longer.
For example, a sound that indicates a file has completed downloading provides enough of a stimulus to gain the transient attention of a user so that they can then process what step (i.e. open the file or continue with something else) they’d like to take next without giving further attention to the fact that a file has been successfully downloaded. You might incorporate additional elements within the downloaded file to maintain users’ sustained attention once they open the file such as effective use of space and displaying progress towards the conclusion to allow users to concentrate on the content.
Why Is Attention Important?
We’ve long been told about the importance of making a good impression on users. These initial moments of attention will make or break your experience in users’ minds.
In 2006, researchers published results of studies suggesting that people form first impressions of a website in under half a second (Lindgaard, et al., 2006). Beyond first impressions, if you are designing a site or product that requires users to focus and enter data while completing a workflow, you will need their attention for a sustained period of time. You need to hold their attention. You need them to process the information you present and respond with the appropriate information or action you are requesting.
Dispelling A Myth
Many of us have heard (repeatedly) that humans have a shorter attention span than a goldfish. This isn’t true. The misconception was put forth in a 2015 Time article stating Microsoft researchers found human attention spans had decreased from 12 seconds to 8 seconds over the time period examined. There are many problems with these assumptions and the way attention span was defined and measured.
Critical to the clickbait statement, we cannot compare human attention to goldfish. In part, because no one knows how to measure the attention of a goldfish (Bradbury, 2016). Additionally, the study that Time cited as measuring goldfish attention was in fact measuring goldfish memory — two distinct concepts that cannot be conflated.
My final point on this is that it doesn’t matter whether our users have a shorter or longer attention span than goldfish — unless we are designing an experience meant for goldfish as users. Humans have shorter attention spans than goldfish is a catchy statement that is false and irrelevant.
Why Do You Deserve Users’ Attention?
I suggest we worry more about how we can effectively and respectfully gain our users’ attention versus the supposed shortening of the human attention span. Jakobs’ Law of the Internet User Experience (2000) states:
“Users spend most of their time on other sites. This means that users prefer your site to work the same way as all the other sites they already know.”

We can restate this in terms of the need to respect our users’ time and attention as well:
“Users spend most of their time on other sites and life activities. This means you need to understand why and how long you need users’ attention. Don’t make them spend extra time on your site.”

Once you have a user’s attention, what do you want to do with it? You need to respect your users. Understanding why you want them to give their attention and time to your site will help ensure you respect them. Additionally, you need to understand why you want to design for attention in order to craft the right design: are you seeking a brief interaction with users, or do you need sustained attention to effectively convey what users need to know?
Key Questions For Stakeholders And Users
UX and product discovery research is required to achieve your goals. Your product team should answer the questions listed in Column A in the table below. Your user research should answer the questions in Column B Below.

A
B

Questions for your product team and stakeholders
Questions for your user research to answer

Why should people use your product?
How do users currently accomplish the task or meet the need your product solves?

How long do you need their attention?How does your product differ from the competition?
Why do they use similar/competing products?

Why do you want their attention? Are users accomplishing a task (transactional) vs. looking for information (educational)?
What else is competing for users’ attention during use (context)?

Why do you deserve their attention?
How quickly can users accomplish the task using your product?

Are there potential ethical issues with increasing attention/engagement with your product?
What additional information or help do users need to make the experience self-explanatory?

Answering the questions in Column A will provide the clarity you need to ensure your product is intentional and ethical. If you are unable to effectively answer these questions, your product needs more discovery and better justification.
Answering the questions in Column B will ensure you provide the correct solutions to gain and maintain user attention, as well as respect them as users.
You should answer all of these questions even if you aren’t focusing on capturing users’ attention. These questions aren’t unique to the concept of attention, they are mandatory to answer for responsible UX design. Why should people use your product over the many existing options if you can’t explain why?
You cannot substitute books and articles on UX design for conducting research with users. I won’t cover the details of individual user research methods in this article, but conducting research using common methods will help you understand how to best answer the questions above and design for the attention needs of your users. These methods should include:

InterviewsAsking folks questions one on one is a staple UX research method. You can explore attitudes and behavior as well as adjust questions based on the feedback you are receiving.
Contextual InquirySitting side by side or in the context of use with a user. You will learn about the distractions and other tasks users engage in while attempting to use your product. Different contexts will present different challenges to inspire your design.
Usability TestingThis method allows you to answer tactical questions related to your design: Does your design work? Do users understand what to do? Do the elements meant to attract and hold attention do so effectively?

Let’s Get Tactical
OK, now you’ve determined to responsibly include elements designed to gain and hold users’ intention. I’ll cover some key tactics you can use to better design for your users’ attention:

motion,
sound,
progress and interruptions,
clearing the clutter and removing distractions,
shortcuts to the outcome,
gamification,
giving users something to do.

These are examples of some options for tactics to consider, they are not comprehensive, but most have research supporting the link between human attention and the tactic.
Motion
Motion is a scientifically sound way to grab users’ transient attention. When something appears suddenly in our peripheral vision, we cannot help but notice it (Liu, Pestilli, and Carrasco 2005). You can use motion to attract attention to a specific area of the screen, reduce frustration by surfacing a critical insight like “click here” when you sense users are struggling, or highlight a status change.
Motion is not a panacea for all situations needing user attention. First, not all users are sighted. If you looked carefully at the Liu, Pestilli, and Carrasco 2005 study, all of their research participants had 20/20 or corrected to 20/20 vision. We know we need to account for low vision and blind users in many situations we design for. Second, motion simply isn’t the correct way to address many design scenarios. Motion can be negatively distracting as easily as it can be an enhancement to gaining attention. Nielsen Norman Group provides a good article giving insight on the use of animation which includes the following:

What is the goal of the animation?
What is the frequency of occurrence?
Employ animations sparingly and only when they add meaning to the interaction.
Think about whether the animation will cause an attention shift or not and whether the same user is likely to stumble over it again and again.
Will the animation reinforce relationships between UI elements?

Nielsen Norman Group provides a great reminder not to use motion to impede users’ progress. No one wants to wait while a video of an animated chicken plays to reflect an updated status of a ticket in your project tracking software. Find other ways to keep users’ attention.
Sound
Sound is another tactic with scientific backing (Fritz, et al, 2007). Sound is useful in going beyond visual stimulus. We can use sound to draw users to a change in status, briefly drawing their transient attention (think “You’ve got mail”) and we can use sound to hold our users’ attention via narration or music. We can combine sound with visuals to create a strong impact.
Sound also has the potential to be a safer option in some settings. For example, voice assistant apps allow us to be hands-free on our phones during situations such as driving. Or having a map application that gives audible alerts and directions versus requiring users to view a screen. Thinking beyond devices with larger screens, sound can and should be incorporated into wearable devices as well. How might a heart rate monitor communicate information to users audibly? Or how might a heart rate monitor audibly communicate critical information to first responders, if necessary? Karen Kaushanksy’s 2012 Smashing Article is a good resource with links to other resources for consideration when designing audio in your experience (even if we might disagree on the value of “You’ve got mail”).
Progress (Or Not)
You can use graphical displays of progress to hold users’ attention. When users are weighing how much time they have or are willing to give paying attention to your site, you can provide a progress graphic to keep them interested. The end is near! Additionally, showing progress in increments allows users to feel a sense of accomplishment or progress while completing a task that might otherwise be considered mundane (e.g. completing a form or making progress in a mandatory online training at work).
You might consider testing if users would appreciate your progress graphic doubling as navigation in certain contexts. For example, if the progress bar in Figure 1 reflects pages on a form, would users need the ability to click back on step one if they needed to update information and then click to navigate back to step three without going through Step 2 again? This might keep users engaged if they go back to the workflow and then do not have to aimlessly skip through redundant information to get back to where they left.

Stopping progress is another way of gaining users’ attention, particularly when done during a normally routine task. If you have an important announcement or need users to pause to consume information, displaying the information and requiring an acknowledgment can be an effective technique.
Many sites and applications (including the Hinge dating app shown below) shared important messages around the issues of race and equality during recent efforts to increase awareness of inequality in the US and around the world. Hinge presented users with this screen after opening the app, a point where a user would typically land on a profile of a potential match.

You might frustrate users if you stop progress too frequently. Additionally, users are likely desensitized to some level of having progress impeded. Many e-commerce and news sites use this technique to present new users with a screen to subscribe to email updates (often with the incentive of a discount). However, this might lend validity to the technique if many of these sites are successful at doing this.
Clear Clutter/Remove Distractions
When you want users to understand something and make an action, perhaps on an unfamiliar interface with a specific purpose, you need to present them with immediate wayfinding to keep their attention.
The next example is of the opening page of a complex statistical analysis and modeling program. The design shows users immediately what they can do to begin a project, rather than overwhelming them with all the potential options. They get users’ data into the platform, let them see the value, then can progressively unfold guidance on how to run various analyses and visualization. Overwhelming users is a good way to have them stop paying attention.

When I do usability testing and hear participants — this looks so much more modern than what we have now and I like it, it is often in reference to good use of space, clearing the clutter, and showing them through the interface exactly what they need to do to complete a critical task.
The image below is a non-example of how clutter is detrimental to attention. Adding clutter has been a technique some media outlets use for distracting users in order to promote their purchase of a subscription or paid upgrade that will remove the clutter. Think ad vs ad fee experiences on apps and games.

Shortcuts To The Outcome
If you believe your potential users have short attention spans you need to get them to the desired outcome as quickly as possible. We have many techniques to do this depending on what your product is. This includes:

‘Buy Now’ buttons,
Saving a cart,
Wish lists,
Create accounts/save critical information,
Prepopulating data fields,
Removing non-required fields,
Providing concise summaries,
Showing an estimate of time to complete a task, video, or article.

E-commerce sites can add a ‘Buy Now’ option to their items to bypass as many intermediary steps possible. Similarly, allowing shoppers to save carts or make wish lists will allow them to save things for a later time when they might have more attention to give. Both of these tactics suggest you’d want to have users create accounts and save critical information for prepopulating fields or expediting use at a later time.
Allowing users to skip non-critical information or view concise summaries of information is another technique if your site presents large amounts of information. Displaying the length of time a video or audio file will take to play is a good way to let users know upfront how much time they will need to invest.
You should allow users to save progress if your product requires forms or lengthy workflows. You stand to frustrate users who invest time but cannot fully complete a task if you require them to start from scratch when they return. Prefilling data based on information you already have, and reducing or removing non-essential fields are additional ways to respect users’ time and attention.
Gamification
Products across industries have found ways to gamify their experience to hold people’s attention. Researchers in the field of education have found elements of gamification might increase the attention students give to lectures and other content where attention is required for successful processing (e.g. Barata, et al, 2013). Stephen Dale (2014) provides a thorough examination of gamification and critical factors related to successful gamification.
Depending on your product, there are many opportunities for gamification. We see this across the board in health and fitness apps: rewards and recognition for certain accomplishments, challenges and leaderboards, and the ability to share and compare with friends via social media.
The Netflix example below shows the importance of doing gamification with the right intention and appropriate audience. If increasing use of your product might be ethically questionable, or a waste of users’ time, you should explore other techniques to only hold attention for the necessary amount of time. Dale (2014) suggests we need to answer the following questions to effectively and ethically gamify our experiences:
Dale suggests we need to answer the following questions prior to gamifying our experiences:

Understand the target audience we intend to engage;
Recognize the behaviors we want to change;
Understand what motivates your audience and maintains their engagement;
Define how success will be measured.

Give Users Something To Do
You increase the likelihood of keeping users’ attention when you have them actively engage with content. Dating apps and social have perfected the interweaving of relevancy and action on phone-sized screens. Swiping on profiles, scrolling down and up, pull down to refresh, swipe right to make a new connection, all this reinforces a connection between a physical action, a response on the phone screen, and an immediate hit of dopamine. Some experts suggest this is how we have created problematic usage of smartphones.
We aren’t inherently evil when we ask users to engage in a tactile way with our applications. There are many valid and well-meaning products designers are creating to help people with medical conditions such as Parkinson’s disease and stroke among many other future potentials (Some examples of many: de Baros, et al. 2013, Oh, et al. 2018), I’m putting this technique out in that it is the definition of an effective technique for holding users’ attention, however, it is also can be problematic for users prone to addictive behaviors.
Physical interaction is also not a catch-all solution. You won’t meaningfully increase user attention to your mobile banking application no matter how many ways you let them refresh their balance by pulling down on the screen, however, you might find some users refreshing non-stop during certain time periods where they are expecting a deposit or withdrawal of funds. You need to have the other pieces to good design and technology in place to make the experience effective at that point.
For example, have you made it clear to users the bank’s policies around posting deposits? Perhaps you detect a user has refreshed on their balance 15 times in 3 minutes and you surface a message that states account balances are only refreshed at 5 pm in whatever time zone your bank is located each weekday and never on weekends. You have introduced a positive intervention to allow this user to move on with their life and they can return at the appropriate time to use your product for the appropriate reason.
The Consequences Of Irresponsible Design
I’ve covered the basics of some tactics to consider when designing for attention. You will need to explore more when making the decision as to what is best for your users and your product. We stand to suffer negative consequences if we don’t have good answers to why we want our users’ attention. It might sound dramatic, but we are responsible for how our design impacts our users’ lives. Netflix learned this a few years ago when they were exploring a badging/rewards system to gamify children watching Netflix.
Responsible adults quickly called this out as an attempt to encourage children to spend even more time in front of the television or watching shows on a device. Netflix retracted the feature, but not before receiving negative press and spending plenty of money to design and develop it out.

Ethical Implications
Beyond bad publicity, the overuse of digital products can be detrimental to users’ mental health and unethical. The idea of Internet addiction is almost as old as the Internet itself, with Young’s (1996) seminal work measuring Internet addiction starting an entire field of research aimed at the issue.
Regardless of your personal feelings, research and funding have been aimed at reducing problematic (pathologic) use of online sites and video games, The World Health Organization’s 2018 recognition of “gaming disorder” as a classifiable disease validates the negative impact digital experiences can have on users. We owe our users the respect to do what we can to prevent the overuse of unnecessary digital products. We probably shouldn’t call them users.
We also have the opportunity to do good when we acknowledge design can become addictive and attempt to address it within our products. For example, Nintendo’s president moved the company to the front of the gaming addiction conversation in announcing the company has added parental controls as one way to combat the issue.
Apple’s Screen Time is another feature meant to create user awareness and prevent the overuse of digital products. You should think about how you can get users to detach from your product as quickly as you can, once they have accomplished the task at hand.
Bringing It To Life
We need to proactively design for our users’ attention. We want to have people use our products, that is why we design. However, we need to understand and respect our users through the techniques we use to gain and keep their attention.
There is no one size fits all solution to the issue of user attention. I think that is part of the beauty; we must experiment, and we must truly know our users if we want to effectively engage them. You can use the techniques presented here, along with the continuous gathering of user feedback, to make the best decisions for your users.
I also have great news for you: if you are still reading this you have a longer attention span than a goldfish.

Visit source: Post courtesy of : Designing For Attention

Categories
Uncategorized

Animating React Components With GreenSock

During the early days of the World Wide Web, things were rather static and boring. Webpages were mostly based on graphic design and layouts from the print world until animations were introduced. Animation can engage and hold people’s attention longer than a static web page and communicates an idea or concept more clearly and effectively.…

Want to Read more ? During the early days of the World Wide Web, things were rather static and boring. Webpages were mostly based on graphic design and layouts from the print world until animations were introduced. Animation can engage and hold people’s attention longer than a static web page and communicates an idea or concept more clearly and effectively.
However, when not done right, animations can hamper user interactions with your product and negatively impact traction. The GreenSock Animation Platform AKA (GSAP) is a powerful JavaScript library that enables front-end developers, animators and designers to create performant timeline based animations. It allows animation lovers take precise control of their animation sequences rather than the sometimes constraining keyframe and animation properties that CSS offers.
In this article, I’ll introduce you to some features of GSAP such as scrollTriggers, Timelines, Easing etc, at the end we’ll build an intuitive user interface by animating a React app with this features👌. Check out the finished project on codesandbox.
This article will be useful to you if:

You have been building animations on web applications with HTML, CSS, and JavaScript.
You are already building animated webpages in a React apps with packages like animate.css, React-motion, Framer-motion, and React-Spring, plus you want to check out alternatives.
You are a React enthusiast, and you’d like to build complex animations on React-based web applications.

We will look at how to build a variety of animations from an existing web project. Let’s get to it!
Note: This article assumes you are comfortable with HTML, CSS, JavaScript, and React.js.
What Is GSAP?
GreenSock Animation Platform also known as GSAP is an Ultra high-performance, professional-grade animation for the modern web that allows developers to animate their apps in a modular, declarative, and re-usable fashion. It is framework-agnostic and can be used across any JavaScript based project, it has a very minimal bundle size and will not bloat your app.
GSAP can perform canvas animations, used to create WebGL experiences, and create dynamic SVG animations and as great browser support.
Why Use GSAP?
Maybe you’re not quite ready to betray other frameworks yet, or you haven’t been convinced to embrace the goodies that come with GSAP. Allow me to give you a few reason why you may want to consider GSAP.
You Can Build Complex Animations
GSAP JavaScript library makes it possible for developers to build simple to very complex physics-based animations like in the case of these sites, it allows developers and designers sequence motion and controls the animation dynamically. It has lots of plugins such as DrawSVGPlugin, MorphSVGPlugin, and more, which makes creating SVG based animations and 2D/3D animations a reality. Asides integrating GSAP on DOM elements, you can use them within WebGL/Canvas/ Three.js context-based animations.
Furthermore, the easing capacity of GSAP is quite sophisticated, hence making it possible to create advance effects with multiple beziers as compared to the regular CSS animation.
Performance
GSAP has an impressive high performance across different browsers.
According to GSAP’s team, in their website, “GSAP is 20x faster than jQuery, plus GSAP is the fastest full-featured scripted animation tool on the planet. It’s even faster than CSS3 animations and transitions in many cases.” Confirm speed comparison for yourself.
Furthermore, the GSAP animations perform effortlessly on both desktop computers, tablets, and smartphones. It is not needed to add a long list of prefixes, this is all being taken care of under the hood by GSAP.
You can check out more benefits on GSAP or see what Sarah Drasner as to say about it here.
Cons Of GSAP
Are you saying I should always use GSAP for every project? Of course not! I feel like, there’s only one reason you might not want to use GSAP. Let’s find out!

GSAP is solely a JavaScript-based animation library, hence it requires some knowledge of JavaScript and DOM manipulation to effectively utilize its methods and APIs. This learning curve downside leaves even more room for complications for a beginner starting out with JavaScript.
GSAP doesn’t cater to CSS based animations, hence if you are looking for a library for such, you might as well use keyframes in CSS animation.

If you’ve got any other reason, feel free to share it in the comment section.
Alright, now that your doubts are cleared, let’s jump over to some nitty-gritty in GSAP.
GSAP Basics
Before we create our animation using React, let’s get familiar with some methods and building blocks of GSAP.
If you already know the fundamentals of GSAP, you can skip this section and jump straight to the project section, where we’ll make a landing page skew while scrolling.
Tween
A tween is a single movement in an animation. In GSAP, a tween has the following syntax:
TweenMax.method(element, duration, vars)

Let’s take a look at what this syntax represents;

method refers to the GSAP method you’ll like to tween with.
element is the element you want to animate. If you want to create tweens for multiple elements at the same time, you can pass in an array of elements to element.
duration is the duration of your tween. It is an integer in seconds (without the s suffix!).
vars is an object of the properties you want to animate. More on this later.

GSAP methods
GSAP provides numerous methods to create animations. In this article, we’d mention only a few such as gsap.to, gsap.from, gsap.fromTo. You can check out other cool methods in their documentation. The methods discussed in this section will be used in building our project later in this tutorial.

gsap.to() the values to which an object should be animated i.e the end property values of an animated object — as shown below: gsap.to(‘.ball’, {x:250, duration: 5})

To demonstrate the to method the codepen demo below shows that an element with a class of ball 250px will move across the x-axis in five seconds when the components mounts. If a duration isn’t given, a default of 500 milliseconds would be used.
See the Pen GSAP REACT DEMO1 by Blessing Krofegha.
Note: x and y-axis represent the horizontal and vertical axis respectively, also in CSS transform properties such as translateX and translateY they are represented as x and y for pixel-measured transforms and xPercent and yPercent for percentage-based transforms.
To view the complete snippet of the code check the codepen playground.

gsap.from() — Defines the values an object should be animated from — i.e., the start values of an animation: gsap.from(‘.square’, {duration:3, scale: 4})

The codepen demo show how an element with a class of square is resized from a scale of 4 in 3seconds when the components mounts. Check for the complete code snippet on this codepen.
See the Pen GSAP REACT DEMO2 by Blessing Krofegha.

gsap.fromTo() — lets you define the starting and ending values for an animation. It is a combination of both the from() and to() method.

Here’s how it looks;

gsap.fromTo(‘.ball’,{opacity:0 }, {opacity: 1 , x: 200 , duration: 3 });
gsap.fromTo(‘.square’, {opacity:0, x:200}, { opacity:1, x: 1 , duration: 3 });

This code would animates the element with a class of ball from an opacity of 0 to an opacity of 1 across the x-axis in 3 seconds and the square class is animated the from an opacity of 0 to 1 in 3 seconds across the x-axis only when the component mounts. To see how the fromTo method works and the complete code snippet, check the demo on CodePen below.
See the Pen React GSAP FromTo demo by Blessing Krofegha.
Note: Whenever we’re animating positional properties, such as left and top, we must ensure that the elements concerned must have a CSS position property of either relative, absolute, or fixed.
Easing
GSAP official documentation defined easing as the primary way to change the timing of your Tweens. It determines how an object changes position at different points. Ease controls the rate of change of animation in GSAP and is used to set the style of an object’s animation.
GSAP provides different types of eases and options to give you more control over how your animation should behave. It also provides an Ease Visualizer to help you choose your preferred ease settings.
There are three types of eases, and they vary in their operations.

in() — Motion starts slowly, then picks up the pace toward the end of the animation.
out() — The animation starts fast then slows down at the end of the animation.
inOut() — The animation begins slow, picks up the pace halfway through, and ends slowly.

See the Pen React GSAP Easing demo by Blessing Krofegha.
In these easing example, we chained the tweens that displayed the three types of eases bounce.in, bounce.out and bounce.inOut, and set a delay of the number of seconds it takes the animation to complete before starting the next one only when the component is mounts. This pattern is repetitive, in the next next section we would see how we could use a timeline to do this better.
Timelines
A Timeline acts as a container for multiple tweens. It animates tweens in sequential order, and it is not dependent on the duration of the previous tween. Timeline makes it simple to control tweens as a whole and precisely manage their timing.
Timelines can be written by creating an instance of a timeline like so:
gsap.timeline();

You can also chain multiple tweens to a timeline in two different ways, in the code below:

##Method 1
const tl = gsap.timeline(); // create an instance and assign it a variable
tl.add(); // add tween to timeline
tl.to(‘element’, {});
tl.from(‘element’, {});

##Method 2
gsap.timeline()
.add() // add tween to timeline
.to(‘element’, {})
.from(‘element’, {})

Let’s recreate the previous example with a timeline:

const { useRef, useEffect } = React;

const Balls = () => {
useEffect(() => { const tl = gsap.timeline();
tl.to(‘#ball1’, {x:1000, ease:”bounce.in”, duration: 3})
tl.to(‘#ball2’, {x:1000, ease:”bounce.out”, duration: 3, delay:3 })
tl.to(‘#ball3’, {x:1000, ease:”bounce.inOut”, duration: 3, delay:6 })
}, []);
}

ReactDOM.render(, document.getElementById(‘app’));

Inside a useEffect hook, we created a variable(tl) that holds an instance of a timeline, next we used the tl variable to animate our tween in sequential without depending on the previous tween to animate, passing the same properties as it were in the previous example. For the complete code snippet of this demo check the codepen playground below.
See the Pen React GSAP (Easing with Timeline) demo by Blessing Krofegha.
Now that we have gotten a feel of some the basic building blocks of GSAP, let’s see how we could build a complete animation in a typical React app in the next section.
Let’s begin the flight! 🚀
Building An Animated Landing Page With React And GSAP
Let’s get to animate a React App. Ensure you clone the repo before you begin and run npm install in order to install the dependencies.
What Are We Building?
Currently, our landing page contains a few texts a white background, a menu that doesn’t drop down, with really no animation. The following are what we’ll be adding to the landing page;

Animate the text and the logo on the homepage, so it eases out when the component is mounted.
Animate the menu, so it drops down when the menu is clicked.
Make the images in the gallery page skew 20deg when the page scrolls.

Animated page.

Check out the demo on codesandbox.
We’ll break the process of our landing page into components, so it will be easy to grasp. Here’s the process;

Define the animation methods,
Animate text and logo,
Toggle menu,
Make images skew 20deg on page scroll.

components

Animate.js — Defined all animation methods,
Image.js — import galley images,
Menu.js — Contains the menu toggle functionality,
Header.js — Contains navigation links.

Define animation methods
Create a component folder inside the src directory, and create an animate.js file. Copy and paste the following code into it.
import gsap from “gsap”
import { ScrollTrigger } from “gsap/ScrollTrigger”;
//Animate text
export const textIntro = elem => {
gsap.from(elem, {
xPercent: -20,
opacity: 0,
stagger: 0.2,
duration: 2,
scale: -1,
ease: “back”,
});
};

Here, we imported gsap . We wrote an exported arrow function that animates the text on the landing page. Remember that gsap.from() method defines the values an object should be animated from. The function has an elem parameter that represents the class which needs to be animated. It takes a few properties and assigns values such as xPercent: -20 (transforms the object by -20%), gives the object no opacity, makes the object scale by -1, makes the object ease back in 2sec.
To see if this works, head over to App.js and include the following code.


//import textIntro
import {textIntro} from “./components/Animate”


//using useRef hook to access the textIntro DOM
let intro = useRef(null)
useEffect(() => {
textIntro(intro)
}, [])

function Home() {
return (
<div className=’container’>
<div className=’wrapper’>
<h5 className=”intro” ref={(el) => (intro = el)}></h5>
The <b>SHOPPER</b>, is a worldclass, innovative, global online ecommerce platform,
that meets your everyday daily needs.
</h5>
</div>
</div>
);
}

Here, we import the textIntro method from the Aminate component. To access the DOM we used to useRef Hook. We created a variable intro whose value is set to null. Next, inside the useEffect hook, we called the textIntro method and the intro variable. Inside our home component, in the h5 tag, we defined the ref prop and passed in the intro variable.
Animated text.

Next, we have got a menu, but it isn’t dropping down when it’s clicked. Let’s make it work! Inside the Header.js Component, add the code below.

import React, { useState, useEffect, useRef } from “react”;
import { withRouter, Link, useHistory } from “react-router-dom”;
import Menu from “./Menu”;
const Header = () => {
const history = useHistory()
let logo = useRef(null);
//State of our Menu
const [state, setState] = useState({
initial: false,
clicked: null,
menuName: “Menu”,
});
// State of our button
const [disabled, setDisabled] = useState(false);
//When the component mounts
useEffect(() => {
textIntro(logo);
//Listening for page changes.
history.listen(() => {
setState({ clicked: false, menuName: “Menu” });
});
}, [history]);
//toggle menu
const toggleMenu = () => {
disableMenu();
if (state.initial === false) {
setState({
initial: null,
clicked: true,
menuName: “Close”,
});
} else if (state.clicked === true) {
setState({
clicked: !state.clicked,
menuName: “Menu”,
});
} else if (state.clicked === false) {
setState({
clicked: !state.clicked,
menuName: “Close”,
});
}
};
// check if out button is disabled
const disableMenu = () => {
setDisabled(!disabled);
setTimeout(() => {
setDisabled(false);
}, 1200);
};
return (
<header>
<div className=”container”>
<div className=”wrapper”>
<div className=”inner-header”>
<div className=”logo” ref={(el) => (logo = el)}>
<Link to=”/”>SHOPPER.</Link>
</div>
<div className=”menu”>
<button disabled={disabled} onClick={toggleMenu}>
{state.menuName}
</button>
</div>
</div>
</div>
</div>
<Menu state={state} />
</header>
);
};
export default withRouter(Header);

In this component, we defined our menu and button state, inside the useEffect hook, we listened for page changes using useHistory hook, if the page changes we set the clicked and menuName state values to false and Menu respectively.
To handle our menu, we checked if the value of our initial state is false, if true, we change the value of initial , clicked and menuName to null, true and Close. Else we check if the button is clicked, if true we’d change the menuName to Menu. Next, we have a disabledMenu function that disables our button for 1sec when it’s clicked.
Lastly, in our button, we assigned disabled to disabled which is a boolean value that will disable the button when its value is true. And the onClick handler of the button is tied to the toggleMenu function. All we did here was toggle our menu text and passed the state to a Menu component, which we would create soonest. Let’s write the methods that will make our menu dropdown before creating the actual Menu component. Head over to Animate.js and paste this code into it.
….
//Open menu
export const menuShow = (elem1, elem2) => {
gsap.from([elem1, elem2], {
duration: 0.7,
height: 0,
transformOrigin: “right top”,
skewY: 2,
ease: “power4.inOut”,
stagger: {
amount: 0.2,
},
});
};
//Close menu
export const menuHide = (elem1, elem2) => {
gsap.to([elem1, elem2], {
duration: 0.8,
height: 0,
ease: “power4.inOut”,
stagger: {
amount: 0.07,
},
});
};

Here, we have a function called menuShow, which skews the menu horizontally by 2degrees, eases the menu, offset’s the animation using the stagger property, and transforms the menu from right to top in 0.7sec, the same properties go for the menuHide function. To use these functions, create Menu.js file inside the components and paste this code into it.

import React, {useEffect, useRef} from ‘react’
import { gsap } from “gsap”
import { Link } from “react-router-dom”
import {
menuShow,
menuHide,
textIntro,
} from ‘./Animate’
const Menu = ({ state }) => {
//create refs for our DOM elements

let menuWrapper = useRef(null)
let show1 = useRef(null)
let show2 = useRef(null)
let info = useRef(null)
useEffect(() => {
// If the menu is open and we click the menu button to close it.
if (state.clicked === false) {
// If menu is closed and we want to open it.
menuHide(show2, show1);
// Set menu to display none
gsap.to(menuWrapper, { duration: 1, css: { display: “none” } });
} else if (
state.clicked === true ||
(state.clicked === true && state.initial === null)
) {
// Set menu to display block
gsap.to(menuWrapper, { duration: 0, css: { display: “block” } });
//Allow menu to have height of 100%
gsap.to([show1, show2], {
duration: 0,
opacity: 1,
height: “100%”
});
menuShow(show1, show2);
textIntro(info);

}
}, [state])

return (
<div ref={(el) => (menuWrapper = el)} className=”hamburger-menu”>
<div
ref={(el) => (show1 = el)}
className=”menu-secondary-background-color”
></div>
<div ref={(el) => (show2 = el)} className=”menu-layer”>
<div className=”container”>
<div className=”wrapper”>
<div className=”menu-links”>
<nav>
<ul>
<li>
<Link
ref={(el) => (line1 = el)}
to=”/about-us”
>
About
</Link>
</li>
<li>
<Link
ref={(el) => (line2 = el)}
to=”/gallery”
>
Gallery
</Link>
</li>
<li>
<Link
ref={(el) => (line3 = el)}
to=”/contact-us”
>
Contact us
</Link>
</li>

</ul>
</nav>
<div ref={(el) => (info = el)} className=”info”>
<h3>Our Vision</h3>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit….
</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default Menu

What we did in the Menu component was to import the animated functions, which are menuShow, menuHide, and textIntro. Next, we assigned variables for each created refs for our DOM elements using the useRef hook and passed null as their values. Inside the useEffect hook, we check for the state of the menu, if clicked is false, we call the menuHide function, otherwise, if the clicked state is true we call the menuShow function. Lastly, we ensured that the DOM elements concerned are passed their specific refs which are menuWrapper, show1, show2. With that, we’ve got our menu animated.
Let’s see how it looks.
Animated Menu.

The last animation we would implement is make our images in our gallery skew when it scrolls. Let’s see the state of our gallery now.
Gallery without animation.

To implement the skew animation on our gallery, let’s head over to Animate.js and add a few codes to it.

….
//Skew gallery Images
export const skewGallery = elem1 => {
//register ScrollTrigger
gsap.registerPlugin(ScrollTrigger);
// make the right edge “stick” to the scroll bar. force3D: true improves performance
gsap.set(elem1, { transformOrigin: “right center”, force3D: true });
let clamp = gsap.utils.clamp(-20, 20) // don’t let the skew go beyond 20 degrees.
ScrollTrigger.create({
trigger: elem1,
onUpdate: (self) => {
const velocity = clamp(Math.round(self.getVelocity() / 300));
gsap.to(elem1, {
skew: 0,
skewY: velocity,
ease: “power3”,
duration: 0.8,
});
},
});
}

We created a function called skewGallery, passed elem1 as a param, and registered ScrollTrigger.
ScrollTrigger is a plugin in GSAP that enables us to trigger scroll-based animations, like in this case of skewing the images while the page scrolls.
To make the right edge stick to the scroll bar we passed right center value to the transformOrigin property, we also set the force3D property to true in other to improve the performance.
We declared a clamp variable that calculates our skew and ensures it doesn’t exceed 20degs. Inside the ScrollTrigger object, we assigned the trigger property to the elem1 param, which would be the element that needs to be triggered when we call this function. We have an onUpdate callback function, inside it is a velocity variable that calculates the current velocity and divides it by 300.
Lastly, we animate the element from their current values by setting other values. We set skew to initially be at 0 and skewY to be the velocity variable at 0.8.
Next, we’ve got to call this function in our App.js file.
….
import { skewGallery } from “./components/Animate”
function Gallery() {
let skewImage = useRef(null);
useEffect(() => {
skewGallery(skewImage)
}, []);
return (
<div ref={(el) => (skewImage = el)}>
<Image/>
</div>
)
}

….

Here, we imported skewGalley from ./components/Animate, created a skewImage ref that targets the image element. Inside the useEffect hook, we called the skewGallery function and passed the skewImage ref as a param. Lastly, we passed the skewImage to the ref to attribute.
You’d agree with me it was such a pretty cool journey thus far. Here’s the preview on CodeSanbox 👇

The supporting repo for this article is available on Github.
Conclusion
We’ve explored the potency of GSAP in a React project, we only scratched the surface in this article, there’s no limit to what you can do with GSAP as it concerns animation.
GSAP’s official website offers additional tips to help you gain a thorough understanding of methods and plugins. There’s a lot of demos that would blow your mind away with what people have done with GSAP. I’d love to hear your experience with GSAP in the comment section.
Resources

GSAP Documentation, GreenSock
“The Beginner’s Guide To The GreenSock Animation Platform,” Nicholas Kramer, freeCodeCamp
“An Introduction To Animations With Greensock Animation API (GSAP),” Zell Liew

Visit source: Post courtesy of : Animating React Components With GreenSock

Categories
Uncategorized

Smashing Magazine Is Fourteen!

This week at Smashing, we celebrated 14 years of bringing you the best web design and development content — and what an interesting year it has been! Last year, I published the 13th birthday post from our team meeting in Freiburg. Back then, we were about to run SmashingConf Freiburg and our meeting was full…

Want to Read more ? This week at Smashing, we celebrated 14 years of bringing you the best web design and development content — and what an interesting year it has been! Last year, I published the 13th birthday post from our team meeting in Freiburg. Back then, we were about to run SmashingConf Freiburg and our meeting was full of our plans for 2020. We were looking forward to another exciting year of conferences, and everything else that team Smashing creates. Little did we know that a year later we would all be working from our home locations, our conferences moved online, and the whole world struggling with a virus that no-one had heard of at the time.
The last year has been difficult for many people — our little team didn’t escape that. Between us, we’ve dealt with a bunch of stressful life events in addition to the pandemic. We also lost a good friend in Scott Whitehead, who died last month aged just 39. He will be dearly missed by all of us who worked with him.
Through it all, however, there is always a cheerful greeting when I log into the Smashing Slack. Some positivity on days when it seems as if nothing is going right; and a million ideas and plans despite it sometimes seeming like it makes no sense to plan anything. We’re weathering the storm, along with our wider Smashing community, and we hope that our articles, conferences, meetups, and membership have helped to make lockdown just a little less lonely.
Birthdays should be a celebration, even when times are difficult. I asked some of our Smashing Team and friends what their favorite Smashing memories were. Earlier this week, we ran SmashingConf Freiburg online, so it seems fitting that this first memory is from Vitaly about the very first SmashingConf:
“I vividly remember the first time we were waving Smashing Flags at the balcony of the very first SmashingConf in Freiburg. It was a very sunny day, with a few clouds rising above the sky, and I was walking towards Historisches Kaufhaus to get ready for the setup. It was such a powerful feeling: as I was approaching the building, I could see the flags waving from the balcony far, far away. It’s such an empowering feeling to see that something that has always been digital actually became real right in front of you.

Another feeling that had a tremendous impact on me was in a coffee shop in Kyiv, Ukraine. I was sitting and working there at a large wooden table at some point in 2014, and there was a group of young people sitting next to me. Of course, it turned out that they were designers and developers. So at some point, they stumbled upon some issue, and they opened a Smashing article and were all reading it together. It was quite a feeling because it was actually one of my earlier articles from 2010 or so, and it was so nice to see it actually being used and valued. I didn’t say anything but ordered another cappuccino, then put my headphones on and kept on working with a smile on my face. 🙂

I remember that first conference well, as I was one of the speakers along with many of my friends in the industry. Kristof Van den Eede was an attendee, and told me:
“I attended the first-ever Smashing Conference in Freiburg as a starting front-end developer. The impression it left on me is huge. I couldn’t believe I was offered the opportunity to go by the company I worked for at the time. The overall experience was amazing. I remember having my mind blown by Aarron Walter, Rachel Andrew, and so many other speakers. Since then, I’ve never missed a Smashing update or newsletter!”

Freiburg, as the home of Smashing, always has a special feel and was mentioned in many people’s memories. Sarah Drasner remembers being in Freiburg “for the 10th anniversary for the famous chocolate fondue carpet massacre!” One of our subject editors, Alma Hoffmann, also remembers meeting up with the team at a Freiburg event:
“I love Smashing! Been working with these fabulous people since 2010 when I published my first article. My most cherished memory is meeting Iris, Vitaly, Phil, Markus, Amanda, and everyone else in person at the conference in Freiburg. Vitaly, Iris and I had been working online for so long and had only seen each other on video call. Meeting in person was like out of this world! I also met incredible and amazing people whom I keep in touch with. I love the commitment to quality content we all share and want. It has been a dream to work here. Love you all!”

Marc Thiele was part of the team for the very first Smashing event and was able to host Vitaly (and provide a good camera and internet connection) for Smashing Live. He said:
“This is, by any means, the craziest and strangest year in my life. Luckily the looser restrictions now allowed, that Vitaly came over to my place to run his part of the first SmashingConf Live from my house. It was a lovely and uplifting experience in these dark days. Let’s hope that we are able to meet in person soon again.”

We often refer to our Smashing community as our friends and we love it when you feel part of what we are doing. Greg Vissing remembers his first SmashingConf,
“My favorite Smashing memory was being able to attend my first Smashing Conference in 2018 in San Francisco, CA. I had always wanted to go because Smashing Magazine was one of the reasons I got into web development. When I was told by my current employer that I could pick any conference, it was a no-brainer which one I would pick. Once I met the staff of Smashing in person, it was though I had been friends with them for years because of how friendly and inviting the conference is. I’m so appreciative of how much Smashing has furthered my career and the friendships I have made with the staff!”

I often hear from people how being involved with something at Smashing has led to unexpected things happening. Here is one such story from Eric Portis.
“In 2014 I didn’t work in tech and hadn’t spoken publicly since high school and, after a series of increasingly fantastical events, was invited to speak halfway ’round the world, to tell a few hundred people how they should put images on websites at SmashingConf Freiburg.It was all very surreal. I met a bunch of heroes who accepted me unquestioningly as a peer. Vitaly kept asking random questions and making insane demands, always with a puckish smile. There were surprise fireworks at the speaker’s dinner. And, in line for lunch, Guy Podjarny told me I should really talk to some friends of his at an image-centric startup called Cloudinary. Yadda-yadda-yadda I switched careers and work for Cloudinary, now.I’ll be trying to pay all of this forward for the rest of my career.Thanks, Smashing!”

The conference team has had to quickly put everything they know about in-person events and figure out how to translate that into virtual ones. We’ve now run two conferences, Smashing Live! and Smashing Freiburg, and have two more to go — Austin and San Francisco. Charis and Jarijn are based out in Hong Kong, and were involved with the in-person conferences last year. Jarijn told me that a favorite Smashing memory was in getting to Toronto for the first time, and being able to reunite with a childhood friend who lives nearby. Charis talked about how we had to very quickly change from thinking about in-person events to figuring out how to do online ones.
“I was super looking forward to what 2020 had to bring us. 2019 was a fantastic conference year, and running our conferences in SF, Toronto, Freiburg, and New York was one of my best memories of 2019.

Looking back at what we’ve done the past few months, I can only be super proud. We had our online workshops going very quickly after lockdowns were announced, and it was great to see how well they were received. It was so much fun meeting people on the other side of the world and getting a peek into their lives.

It’s been a lot of fun figuring out how to run events online. Working together with Amanda and Vitaly has been an absolute joy.”

While I get involved with the events, the majority of my work at Smashing is already virtual. The pandemic has sometimes meant delays with writing or editing as people struggled to cope with this new normal, but we have ticked along much as we always do. We’ve managed to publish our usual article-per-weekday throughout the past few months and introduced many new writers to the magazine, as well as publishing pieces from some of your favorite authors.
We’re always happy to see your article ideas, whether you are an experienced writer or have not been published before. Don’t just take my word for it, here is what Eric Bailey had to say,
“I’ve been reading Smashing Magazine for years, and it’s had such a positive impact on my growth and career development. Having the opportunity to give back and write for the website was a dream come true.

The Smashing team is friendly, whipsmart, and an absolute joy to work with. If you have been debating writing an article about working on the web, I enthusiastically encourage you to pitch them.

Happy birthday, Smashing! Here’s to many more!”

For the conference team, however, it’s all about in-person events, and a lot of planning had already happened for 2020. Venues and caterers were booked, flights and hotels arranged, and speakers planned. A memory I will take from this period is the day we realized it would be impossible to run the April San Francisco event. Things were changing so quickly, a week previously it looked as if we could go ahead. Rather than complaining, or sitting about bemoaning our misfortune, everyone swung into action to ensure that speakers and attendees were informed and logistics for postponing dealt with. Within a few days, we had online workshops in place and were building out contingency plans just in case — as ultimately happened — we needed to move the events fully online.
Amanda is our head of events, and she remembers this time saying,
“For many people, 2020 has been a challenging year, and at Smashing this has been no exception. However, when the team made the decision to first postpone SmashingConf SF, there was a lot of unknown, yet a beautiful display of teamwork, respect, and truly love coming through. For those who don’t know, the Conf team is fully remote, spanning 4 countries, and 2 continents, and this is the longest we’ve all gone from being together in person. Yet, this is probably the closest we’ve ever felt as a team and as a Smashing Family.”

I’ve mentioned family quite a lot, and some of us actually are family! My daughter Bethany has helped with video editing for Smashing in the past. With everything moved online and her theatre job furloughed, she’s been on board to help with conferences and workshops. She shared her thoughts on being part of the team,
“Though 2020 has been a bit of a disaster in many many ways I feel really lucky that the lockdown and the fact that I’ve been left without my main job has meant I’ve been able to work more and spend more (virtual) time with the Smashing team. It’s been so nice that even though we can’t all get together we’ve still been able to do so many workshops and conferences and get together over a screen. It’s just been lovely to get more involved with a company who is just full of awesome people and I wouldn’t have had this opportunity without this free time that was suddenly thrust upon us.”

And our CEO Inge Emmler linked family and work too, saying that working at Smashing is all about, “being in touch with nice, dear people only — online and offline — what could be more smashing? Well, perhaps celebrating my Mom´s 90th birthday in March. ”
I don’t think any of us want to predict what will be in store for our next year at Smashing. We are continuing to plan — perhaps with a few more plan B and C options that we had last year! One thing I do feel sure of though, is that we’ll continue supporting each other and our Smashing Community, through whatever the next 12 months bring.

Visit source: Post courtesy of : Smashing Magazine Is Fourteen!

Categories
Uncategorized

An Introduction To Running Lighthouse Programmatically

Lighthouse is Google’s suite of website quality analysis tools. It allows you to assess your site’s performance, accessibility, SEO, and more. It is also highly configurable, making it flexible enough to be useful for all sites, from the simplest to the highly complex. This flexibility includes several different ways of running the tests, allowing you…

Want to Read more ? Lighthouse is Google’s suite of website quality analysis tools. It allows you to assess your site’s performance, accessibility, SEO, and more. It is also highly configurable, making it flexible enough to be useful for all sites, from the simplest to the highly complex. This flexibility includes several different ways of running the tests, allowing you to choose the method that works best for your site or application.
One of the simplest ways to run Lighthouse is through Chrome’s DevTools Lighthouse panel. If you open your site in Chrome and then open Chrome’s DevTools, you should see a “Lighthouse” tab. From there, if you click “Generate Report”, you should get a full report of your site’s quality metrics.
What I am focusing on in this article, however, is at the other end of the spectrum. Running Lighthouse programmatically with JavaScript allows us to configure custom runs, picking and choosing the features we want to test, collecting and analyzing results, and specifying configuration options unique to our sites and applications.
For example, perhaps you work on a site that is accessible through multiple URLs — each with its own data and styling and perhaps even markup that you want to be able to analyze. Or maybe you want to gather the data from each test run and compile or analyze it in different ways. Having the ability to choose how you want to run a Lighthouse analysis based on what works best for your site or application makes it easier to monitor site quality and pinpoint where there are issues with your site before they pile up or cause too many problems for your site’s users.
Running Lighthouse programmatically is not the best choice for every site and I encourage you to explore all the different methods the Lighthouse team has built for using the tool. If you decide to use Lighthouse programmatically, however, the information and tutorial below should hopefully get you started.
Customizing Lighthouse Options
The advantage of running Lighthouse programmatically isn’t only the ability to configure Lighthouse itself, but rather all the things you might want or need to do around the Lighthouse tests. Lighthouse has some great documentation to get you started. To get the most out of running it programmatically, however, there are two main places where you will need to dig in and learn more about how Lighthouse works: configuring your test runs and reporting your test results.
Lighthouse Test Run Configuration
Configuring a Lighthouse test run is one of those tasks that can be as simple or as complex as you like.
When running Lighthouse programmatically, there are three places where you can provide custom options: the URL you will be testing, Chrome options, and the Lighthouse configuration object. You can see all three of these are parameters in the function for running Lighthouse from the Lighthouse documentation:

function launchChromeAndRunLighthouse(url, opts, config = null) {
return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => {
opts.port = chrome.port;
return lighthouse(url, opts, config).then(results => {
return chrome.kill().then(() => results.lhr)
});
});
}

You can use whatever code you need in order to create these parameters. For example, say you have a site with multiple pages or URLs you would like to test. Maybe you want to run that test in a CI environment as part of your CI tasks, checking all necessary pages each time the task runs. Using this setup, you can use JavaScript to create your URLs and create a loop that will run Lighthouse for each one.
Any Chrome options you might need can be specified in an object that gets passed to chrome-launcher. In the example from the documentation, the opts object contains an array we’re calling chromeFlags that you can pass to chrome-launcher and a port where you can save the port being used by chrome-launcher and then pass it to Lighthouse.
Finally, the Lighthouse configuration object allows you to add any Lighthouse-specific options. The Lighthouse package provides a default configuration object that can be used as-is or extended and modified. You can use this object to do a multitude of things, including specifying which Lighthouse test categories you want to test.
You can use the emulatedFormFactor to specify whether you want the test to run in a mobile or desktop emulator. You can use extraHeaders to add any cookies you might need to use in the browser. For example, a test running only the accessibility category on a desktop emulator that outputs the results as HTML might have a configuration object that looks like this:
const lighthouseOptions = {
extends: ‘lighthouse:default’,
settings: {
onlyCategories: [‘accessibility’],
emulatedFormFactor:’desktop’,
output: [‘html’],
},
}

This example represents a minimal configuration. There is a lot more you can do. The Lighthouse configuration docs have much more information. They also have a set of sample configuration objects for some more complex implementations.
Custom Results Reporting
When running Lighthouse programmatically, you can have the results returned in one or more of three formatted options and — and this is the most exciting piece in my opinion — you can have access to the raw Lighthouse Result (LHR) object.
HTML, JSON, CSV
Lighthouse will automatically format the results in three different ways: HTML, JSON, or CSV. These are all pre-configured results based on the basic Lighthouse reporting template, which is what you see if you run a Lighthouse test inside of Chrome DevTools, for example. In the lighthouseOptions configuration object from the previous section, you can see a key for output that contains an array with a single string: html. This specifies that I only want the results returned formatted as HTML. If I wanted the results both as HTML and JSON, that array would look like [‘html’, ‘json’].
Once Lighthouse has run, it will return a results object that will contain two keys: report and lhr. We’ll talk about the contents of the lhr key in the next section, but the report key contains an array with the results formatted as you have requested. So, for example, if we have requested [‘html’, ‘json’], then results.report[0] will contain our results formatted as HTML and results.report[1] will contain our results formatted as JSON.
The LHR Object
Running Lighthouse programmatically also gives you access to a much more flexible results object: the LHR object. This object contains the raw results and some metadata from your Lighthouse run. More complete documentation can be found on the Lighthouse Github repository.
You can use these results in any number of ways, including creating custom reports and collecting data from multiple runs for analysis.
Example: Running An Accessibility Test For Mobile And Desktop
Let’s say that I have a site that loads different components depending on whether the user is using a smaller screen or a larger one, meaning that the HTML for each version of the site will be slightly different. I want to make sure that both versions of the site get a score of 95 on the Lighthouse accessibility tests and that no code gets committed to our main branch that doesn’t meet that standard.
Note: If you want to see a working example of the code below analyzing the Sparkbox homepage, you can find the repository here.
I can configure Lighthouse to run the accessibility category twice, providing different configuration objects for each one — one setting the emulatedFormFactor to desktop and one setting it to mobile. An easy way to do this is to create an array with both objects, shown below.
const lighthouseOptionsArray = [
{
extends: ‘lighthouse:default’,
settings: {
onlyCategories: [‘accessibility’],
emulatedFormFactor:’desktop’,
output: [‘html’, ‘json’],
},
},
{
extends: ‘lighthouse:default’,
settings: {
onlyCategories: [‘accessibility’],
emulatedFormFactor:’mobile’,
output: [‘html’, ‘json’],
},
},
]

Then, I can create a function that will loop through this array and run a Lighthouse test for each object found inside the array.
One thing to note is that it is necessary to introduce a delay between each run, otherwise Chromium can get confused and the runs will error out. In order to do this, I’ve added a wait function that returns a promise when the setTimeout interval has completed.

function wait(val) {
return new Promise(resolve => setTimeout(resolve, val));
}

function launchLighthouse(optionSet, opts, results) {
return chromeLauncher
.launch({ chromeFlags: opts.chromeFlags })
.then(async chrome => {
opts.port = chrome.port;
try {
results = await lighthouse(url, opts, optionSet);
} catch (e) {
console.error(“lighthouse”, e);
}
if (results) reportResults(results, runEnvironment, optionSet, chrome);
await wait(500);
chrome.kill();
});
}

async function runLighthouseAnalysis() {
let results;
const opts = {
chromeFlags: [“–no-sandbox”, “–headless”]
};
for (const optionSet of lighthouseOptionsArray) {
console.log(“** Starting Lighthouse analysis **”);
await launchLighthouse(optionSet, opts, results);
}
}

In this case, I am sending the results to a reportResults function. From there, I save the results to local files, print results to the console, and send the results to a function that will determine if the tests pass or fail our accessibility threshold.

async function reportResults(results, runEnvironment, optionSet, chrome) {
if (results.lhr.runtimeError) {
return console.error(results.lhr.runtimeError.message);
}
await writeLocalFile(results, runEnvironment, optionSet);
printResultsToTerminal(results.lhr, optionSet);
return passOrFailA11y(results.lhr, optionSet, chrome);
}

For this project, I want to be able to save the JSON results in a specified directory for our CI test runs and the HTML file in a specified directory for our local test runs. The way Lighthouse returns these different types of results is in an array in the order in which they were requested.
So, in this example, in our lighthouseOptions object, our array asks for HTML first, then JSON. So the report array will contain the HTML-formatted results first and the JSON-formatted results second. The writeToLocalFile function then saves the correct version of the results in a file with a customized name.

function createFileName(optionSet, fileType) {
const { emulatedFormFactor } = optionSet.settings;
const currentTime = new Date().toISOString().slice(0, 16);
const fileExtension = fileType === ‘json’ ? ‘json’ : ‘html’;
return ${currentTime}-${emulatedFormFactor}.${fileExtension};
}

function writeLocalFile(results, runEnvironment, optionSet) {
if (results.report) {
const fileType = runEnvironment === ‘ci’ ? ‘json’ : ‘html’;
const fileName = createFileName(optionSet, fileType);
fs.mkdirSync(‘reports/accessibility/’, { recursive: true }, error => {
if (error) console.error(‘error creating directory’, error);
});
const printResults = fileType === ‘json’ ? results.report[1] : results.report[0];
return write(printResults, fileType, reports/accessibility/${fileName}).catch(error => console.error(error));
}
return null;
}

I also want to print the results to the terminal as the test runs finish. This provides a quick and easy way to view the results without having to open a file.

function printResultsToTerminal(results, optionSet) {
const title = results.categories.accessibility.title;
const score = results.categories.accessibility.score * 100;
console.log(‘n**n’);
console.log(Options: ${optionSet.settings.emulatedFormFactor}n);
console.log(${title}: ${score});
console.log(‘n**’);
}

And finally, I want to be able to fail my test runs if the accessibility scores do not meet my threshold score of 95.

function passOrFailA11y(results, optionSet, chrome) {
const targetA11yScore = 95;
const { windowSize } = optionSet;
const accessibilityScore = results.categories.accessibility.score * 100;
if (accessibilityScore) {
if (windowSize === ‘desktop’) {
if (accessibilityScore < targetA11yScore) {
console.error(Target accessibility score: ${targetA11yScore}, current accessibility score ${accessibilityScore});
chrome.kill();
process.exitCode = 1;
}
}
if (windowSize === ‘mobile’) {
if (accessibilityScore < targetA11yScore) {
console.error(Target accessibility score: ${targetA11yScore}, current accessibility score ${accessibilityScore});
chrome.kill();
process.exitCode = 1;
}
}
}
}

I invite you all to play around with it and explore all the different ways Lighthouse can help monitor your site quality.
Final Notes
While I intentionally kept the example above relatively simple, I hope it gave you a good overview of what can be accomplished when running Lighthouse programmatically. And I hope it inspires you to find new ways to use this flexible, powerful tool.
As Peter Drucker said:
“If you can’t measure it, you can’t improve it.”

Being able to not only measure but monitor our website quality, especially for complex sites, will go a long way towards helping us build a better web.
Further Reading on SmashingMag:

A/B Testing For Mobile-First Experiences
How To Test A Design Concept For Effectiveness
The Importance Of Manual Accessibility Testing
Machine Learning For Front-End Developers With Tensorflow.js
Get Started With UI Design With These Tips To Speed Up Your Workflow

Visit source: Post courtesy of : An Introduction To Running Lighthouse Programmatically

Categories
Uncategorized

Get Up And Running With Craft CMS

Craft CMS is brought to you by the talented folks at Pixel & Tonic. It is actively maintained and kept in line with the changes in the modern web development world and is rising in popularity amongst CMS’s — with an impressive client list such as Netflix. It also has a very active Discord server,…

Want to Read more ? Craft CMS is brought to you by the talented folks at Pixel & Tonic. It is actively maintained and kept in line with the changes in the modern web development world and is rising in popularity amongst CMS’s — with an impressive client list such as Netflix. It also has a very active Discord server, growing to over 5,000 members in just a year of it being live.
Why Use Craft CMS?
Craft CMS has been our go-to CMS for around four years now; we’ve built client websites and even our own business on Craft. As a company, we’re constantly checking the CMS market and have always landed back at Craft. So, let’s go into the reasons we chose Craft CMS over the others on the market:

Interface familiarity, making it fairly easy for anyone coming from WordPress.
Active development community.
Flexible fields, giving you control over how your content is structured.
No lock-ins or monthly fees. Just a one-off fee if you’re going Pro/eCommerce.
Extensibility with Craft’s growing plugin store.

So, with the introduction out of the way, I’m going to show you how to get up and running with a fully set up Craft CMS local environment in around fifteen minutes. Once we’ve completed the following steps, you should have a great foundation to start your next web project, and, hopefully, be ready to move away from WordPress for good.
Installing our Development Environment
Craft CMS ships with a very handy tool to get your local environment set up. This tool is called Craft Nitro and makes setting up a Craft CMS environment simple. It’s new to the Craft scene but helps a great deal.
Setting Up Multipass
Craft Nitro requires something called Multipass which creates a Ubuntu virtual machine on your system. (Don’t worry, you won’t need to set up or ever open Ubuntu.)

Download the latest Multipass installer for your operating system from the official website.
Once downloaded, run the installer. When this is complete you should be ready to move on to the next step.

Setting Up Craft Nitro
The Craft Nitro setup is straightforward and involves one command line script to get it installed on macOS and Linux, but for Windows it’s a bit different. I’ll be going through how to set it up for both types of operating system below. The good news is that once it’s set up it’s done, and you’ll be able to easily create new Craft installs without going through this again.
Installing on macOS and Linux
Open your Terminal and paste the following script line. Once pasted, follow the option prompts on the command line to create your virtual machine with the presets that Craft Nitro has. This should be perfectly fine, but if you fancy fine-tuning, go for it. Just keep in mind that Craft has minimum requirements to run smoothly.
Run the following line in Terminal:
bash

Installing on Windows 10 Pro
Installing on Windows is fairly complex, but shouldn’t take too much time to get up and running. Just make sure you have Hyper-V enabled. Unfortunately, Hyper-V cannot be installed on the Home Edition version of Windows.

Make sure Hyper-V is enabled (more details here);
Download nitro_windows_x86_64.zip from the latest release;
Create a Nitro folder in your home folder if it does not already exist (i.e. C:Users<username>Nitro);
Extract the zip file and copy nitro.exe into the Nitro folder you just created in your home folder;
If this is your first installation, run this from the command line to add Nitro to your global path:setx path “%PATH%;%USERPROFILE%Nitro”

Start the Windows terminal (cmd.exe) with administrator permissions and run Nitro in it.

Once you have completed the above, follow the terminal instructions to create your first machine. The default presets Craft Nitro sets out should be perfectly fine for your environment.
Installing Craft CMS
So far we’ve installed Craft Nitro and created our virtual machine, and we’re now ready to install Craft CMS. In the following instructions, we’re going to download Craft and “mount” our files, allowing us to develop in our current system and see the changes reflected in our Ubuntu virtual machine. We’re also going to set up our initial database and get a local domain we can use, e.g. myfancyproject.test. Let’s get going:
Creating A New Project

Create a new folder where you’d like to develop/install Craft;
Download Craft CMS from the latest release (via Composer or Zip);
Unzip/Move contents into the folder we just created;
Open Terminal/Command Line;
Go to our created folder. $ cd /path/to/project;
Run nitro add;
Follow the on-screen command line prompts. (The presets are usually fine but modify as you wish.)

Tip: If you’re seeing “Not Readable” issues on macOS, then Multipass needs to have full disk access. To do this, ensure multipassd is checked under System Preferences → Security & Privacy → Privacy → Full Disk Access.
Connecting To Our Database
We should now have a test domain and our project files mounted — I know, pretty easy so far, and that’s the hard bit complete. Connecting to our database requires us to add our database details for our newly created site in our project’s .env file.

Open up our project’s .env file (located in the root folder);
Change the database details to the following:DB_USER=”nitro”
DB_PASSWORD=”nitro”
# ‘nitro’ is the default database
DB_DATABASE=”nitro”

Tip: If you’d like to open the database in your SQL program of choice, all you have to do is run nitro info in your command line, and you’ll see your database IP address under “IPV4”. Use the above username and password (along with the port you selected during setup) to connect.
Install Craft CMS
We’ve set up our virtual machine, set our test domain, and got our database ready to go. Now it’s time to actually install Craft CMS and get into the admin section — it should all be smooth sailing from here. So let’s get to it.

Head to the test domain you set during setup followed by /admin (e.g. testdomainyouset.test/admin);
You should see Craft CMS’s install screen (Hooray!);
Follow the on-screen installer instructions;
Once finished, you should be redirected to your new admin panel.

Tip: If you didn’t install Craft via Composer, then you may be prompted for a security key. To generate a cryptographically secure key, use a password manager like 1Password / LastPass. (There’s no length limit so it can be as complex as you’d like). Open up our .env file once more, find the following line SECURITY_KEY=””, paste your generated key inside the quotes and save.

You should now have a fully set up local development environment for Craft CMS, which will provide a great jumping-off point for anything you’re trying to develop, whether that be moving your cat blog from WordPress or creating an eCommerce store. Just remember to turn off your server once finished using nitro stop in your command line.
Here are a few helpful commands for Craft’s Nitro that will help you during development:

nitro start (starts the development server)
nitro stop (stops the development server)
nitro context (shows you information about the environments installed)
nitro info (information about the current environment, PHP version, etc.)

Setting Up Our Cat Blog
Now that we’ve got Craft up and running, we can make a start on our cat blog, and start enjoying the power that Craft offers up to us. In this section, we’re going to be setting up our content model, creating our base theme template and building out our homepage and inner-post pages.
Content models sound scary, but in Craft it’s the opposite; there’s an easy-to-use GUI system — no need for complex code around here! For our cat blog, we need to set up a section called “Cats” which needs the cat’s name, photo and a small description, and then a single page “Homepage”.
How To Create Sections And Pages
How To Create A Cat Post
How To Create Sections And Pages
We’re going to create our “Cats” section and our homepage which will be a classed as a “single” within Craft’s language. Sections are exactly what they sound like — sections of your website — and Pages are also self explanatory, single pages of your website such as legals and our homepage.
Creating Our Cats Section

Go to Settings in the left hand menu;
Click “Sections”;
Click “New Section”;
In the “Name” put Cats;
Section Type Channel(Channels are used for streams of similar content, just like our cats.)
Within “Entry URI Format” we’re going to make sure it’s /cats/{slug};
Within “Template” we’re going to put cat;
Save.

What we’ve done above is tell Craft that we’d like any post within the Cats section to have a URL format like so: ourtestdomain.test/cats/fluffy, and the template we’d like to use is cats.twig.
Creating Our Homepage

Within “Sections”, click “New Section”;
In the “Name”, put Homepage;
Section type Single;
Tick the “Homepage” checkbox;
Within “Template” we’re going to put index;
Save.

Creating Fields
Craft comes with no preconceptions of what you want to build; it gives you a completely blank slate. We create exactly what we want our post’s structure to be by generating our own “Fields”. Let’s create our cat’s “Fields” for the following name, description and photo.

Head to the admin section of your site by visiting yourchosendomain.test/admin;
Navigate to Settings in the left hand menu;
Click “Fields”;
In the top right click “New Field”.

Setting Up The Cat’s Name
We’re going to need a name for our cats, so let’s create a name field.

In the Name put “Cat’s Name”;
Choose “Plain Text” in the Field Type;
Now Save.

Setting Up The Cat’s Description
Our cats also need a description, but let’s cap the number of characters our authors can enter about each cat.

Click “New Field” again;
In the Name put “Cat’s Description”;
Choose the “Plain Text” field type again;
Create a limit by adding “2000” in the Field Limit box;
Click Save.

Setting Up The Cat’s Photo
We’re going to want to add photos to each of our cat posts, and there may be multiple photos per cat — not a problem. But before creating a field, we need to tell Craft where we want the photos to be stored on our server. (Craft also has the option of uploading to Cloud storage solutions as well.)

Head to “Settings” in the left hand menu;
Click “Assets”;
Click “New Volume”;
In the Name put “Cat’s Photo”;
Enable “Assets in this volume have public URLs”;
In “Base URL” put @web/uploads/;
In “File System Path” put @webroot/uploads/;
Save.

The above properties are telling Craft where we would like our uploaded files to be stored. You can change these to whatever you wish. You can also read more into setting environment variables for these in the documentation.
Matching Field to Sections
Now we’ve got our fields and sections set up and running, we’re going to need to combine the two together by assigning what fields we’d like our sections to have. This is as easy as dragging and dropping in Craft.

Head to Settings;
Click “Sections”;
Now click “Edit Section Type”;
Now click our “Cats” Section;
Select “Fields” tab in the right hand menu;
Drag over the “Cats” fields we previously created to the content pane;
Once dragged across, Save the Cats Section.

Tip: You can remove the “Title” field from our posts by disabling the “Show the Title Field” option. You may want the cat’s name as the title for instance.
How To Create A Cat Post
Now it’s time for us to actually create a fluffy cat post. Head over to the “Entries” in the left hand admin menu.

Click “New Entry”;
In the dropdown select “Cats”;
Create your post! (The fluffier the better.)

Listing Our Cat Articles
Now we have our content model done, we can start building the basic interface for our cat blog. Craft is written in the Twig/Liquid language. If you’ve ever dabbled in Shopify development this should be familiar to you; if not, it’s fairly easy to pick up. But first, we need to open our Craft install folder in our favourite code editor (where you unzipped the Craft install).

Open Craft Install in your code editor;
Create a new file in Templates called index.twig(Craft may have installed a default index. Open this instead and wipe it.)
Add the following code:

<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml” lang=”en-US”>
<head>
<link rel=”stylesheet” href=”https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css” integrity=”sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z” crossorigin=”anonymous”>
</head>

<body>
{# Create an entry query with the ‘section’ and ‘limit’ parameters #}
{% set myEntryQuery = craft.entries()
.section(‘cats’)
.limit(10) %}

{# Fetch the entries #}
{% set entries = myEntryQuery.all() %}

{# Display the entries #}

<div class=”container”>
<div class=”row”>
{% for entry in entries %}
<div class=”col”>
<article class=”card”>

{% set catImage = entry.catsPhoto.one() %}
{% if catImage %}
<img src=”{{ rel.url }}” class=”card-img-top” alt=”…”>
{% endif %}

<div class=”card-body”>
<h1><a href=”{{ entry.url }}”>{{ entry.title }}</a></h1>
<h2>{{ entry.catsName }}</h2>
<p>{{ entry.catsDescription }}</p>
<a class=”btn btn-primary” href=”{{ entry.url }}”>View {{ entry.catsName }}</a>
</div>

</article>
</div>
{% endfor %}
</div>
</div>

</body>
</html>

In the code above, we tell Craft about our section “Cats” and put a limit on the posts to 10. Then we fetch the entries from that section, and continue to loop over each of the cats within the fetch entries in the following code. Images are a bit different in Craft: they’re stored as an array, so we do another loop within our code to get the images of the cats.
Let’s Test
Open up your test development URL that we created during setup. (Make sure your nitro server is running using nitro start). We should now see the posts we created displayed on our index page. Clicking through to see more information gives us a 404 error, so let’s fix that next!

Tip: We included Bootstrap to make it look a bit fancier, but feel free to include any framework you’d like.
Cat Post Page
We’re going to do the same as we did with the index page. Let’s create the cat template by creating a new file within the Templates folder called cat.twig. As we’re already within the Entry context, we don’t have to re-query it.

<html>
<body>
{% block content %}

{% set catImage = entry.catsPhoto.one() %}
{% if catImage %}
<img src=”{{ rel.url }}” class=”card-img-top” alt=”…”>
{% endif %}

{{ entry.title }}
{{ entry.catsName }}
{{ entry.catsDescription }}

{% endblock %}
</body>
</html>

Save this, and refresh our test development website. We should now be able to browse to our cats entry page! Voila!
Going Headless
If you fancy going more technical with Craft and using it as your content management system to feed into your web app, you can do this by using Craft CMS’s Pro package which adds user accounts and GraphQL to your config. The Pro version of Craft is free to trial and test against, which means you can give it a thorough test before committing. Now we’ll go into how to set up a basic GraphQL API using Craft’s built-in GraphQL editor.
Start Pro Trial
Once you’ve installed Craft CMS, head over to the “Plugin Store” and look for “Upgrade” in the left-hand menu options. Click “Trial” on the “Pro” section and run through the upgrade process.
The Basic Setup
Once you’ve started your Pro Craft CMS trial, you should now notice a new menu option in your admin side panel: GraphQL. Before we jump straight in, we need some content models which can form the output. When you’ve created your content models, Craft CMS will automatically create you a GraphQL API out of the box. No need to define the schemas either!
Create Your Cat API Endpoint
We’ve got our content sorted; now we want to create the endpoint so we can fetch all our cute cat content. Let’s do that now:

Open your Craft CMS project routes.php in your IDE.
Adding the following rule will make your API endpoint available at http://yourprojecturl.test/api:return [
‘api’ => ‘graphql/api’,
// …
];

Save and close.
Test by pinging the endpoint: curl -H “Content-Type: application/graphql” -d ‘{ping}’ http://yourprojecturl.test/api
You should receive “pong” in response.

Enable Your Content
We’ve set up our endpoint to receive requests. It’s now time for us to enable/disable the certain parts of our site we’d like to be available via our API. For example, you may want to turn off certain entries that contain sensitive information. Craft makes this process extremely easy; it’s a case of ticking/unticking. (You can get more complex by writing your own schemas as well.) For now, we’ll be creating a public schema that’s publicly available. You can create private schemas which require a secret key, but this is out of scope for this guide.

Head over to the GraphQL section via your admin panel sidebar;
Click “Public Schema”;
Enable the “Cats” section.(This will make our content available through your endpoint.)
Save.

Testing Our Endpoint
Now that we’ve chosen the data we’d like to make available via our endpoint, it’s now time to give it a test. In the GraphQL dropdown in your left-hand admin panel, you’ll notice an item called “GraphiQL”. GraphiQL allows us to explore our API and query it within our dashboard.

Open GraphiQL;
Change “Full Schema” to “Public Schema”;
Write the following GraphQL query in the left-hand pane:query ($section: [String], $orderBy: String) {
entries(section: $section, orderBy: $orderBy) {
title
slug
id
}
}

Click the “Play” button.

Tip: If you’re not 100% on GraphQL queries, that’s not a problem; Craft comes with a handy guide to help you.
Wrapping Up
We’ve now done a fairly light dive into the world of Craft CMS. Let’s sum up what we’ve accomplished in the following guide:

Set up a local development environment with Multipass;
Created and set up a brand new Craft install;
Added a test domain in which we can access our install;
Created a cute cat blog;
Gone headless;
Created an API endpoint to access our cats.

If you’re interested in getting more involved with Craft CMS and being part of the community, you should join the very active Craft Discord server and read more via the official documentation.

Visit source: Post courtesy of : Get Up And Running With Craft CMS

Categories
Uncategorized

How To Build A Blog With Next And MDX

Next.js is a React framework that enables you to build static and dynamic apps quickly. It is production-ready and supports server-side rendering and static site generation out of the box, making Next.js apps fast and SEO-friendly. In this tutorial, I will first explain what exactly Next.js is and why you’d use it instead of Create…

Want to Read more ? Next.js is a React framework that enables you to build static and dynamic apps quickly. It is production-ready and supports server-side rendering and static site generation out of the box, making Next.js apps fast and SEO-friendly.
In this tutorial, I will first explain what exactly Next.js is and why you’d use it instead of Create React App or Gatsby. Then, I’ll show you how to build a blog on which you can write and render posts using Next.js and MDX.
To get started, you’ll need some experience with React. Knowledge of Next.js would come handy but is not compulsory. This tutorial would benefit those who want to create a blog (personal or organizational) using Next.js or are still searching for what to use.
Let’s dive in.
What Is Next.js?
Next.js is a React framework created and maintained by Vercel. It’s built with React, Node.js, Babel, and Webpack. It is production-ready because it comes with a lot of great features that would usually be set up in a “vanilla” React app.
The Next.js framework can render apps on the server or export them statically. It doesn’t wait for the browser to load the JavaScript in order to show content, which makes Next.js apps SEO-friendly and blazing fast.
Why Use Next.js Over Create React App?
Create React App is a handy tool that offers a modern build setup with no configuration and without the hassle of having to set up Webpack, Babel, and so on or having to maintain their dependencies. It’s the recommended way to create React apps nowadays. It has a template for TypeScript and also comes with the React Testing Library.
However, if you want to build a multi-page app, then you’ll need to install an extra library, as if you were rendering a React app on the server. The extra setup could be a problem, and any packages installed could increase the final bundle size of your app.
This is exactly the problem that Next.js is intended to solve. It offers the best developer experience, with all of the things you need for production. It comes with several cool features:

Static exporting (pre-rendering)Next.js allows you to export your Next.js app at build time to static HTML that runs without a server. It is the recommended way to generate your website because it’s done at build time and not at each request.
Server-side rendering (pre-rendering)It pre-renders pages to HTML on the server upon every request.
Automatic code splittingUnlike React, Next.js splits code automatically and only loads the JavaScript needed, which makes the app fast.
File-system-based routingNext.js uses the file system to enable routing in the app, meaning that every file under the pages directory will be treated automatically as a route.
Hot reloading of codeNext.js relies on React Fast Refresh to hot reload your code, offering a great developer experience.
Styling optionsThe Next.js framework has built-in support for Styled JSX, CSS modules, Sass, LESS, and more.

Next.js Versus Gatsby
Gatsby is a static site generator built on top of React and GraphQL. It is popular and has a huge ecosystem that provides themes, plugins, recipes, and so on.
Gatsby and Next.js websites are super-fast because they are both rendered either on the server or statically, meaning that the JavaScript code does not wait for the browser to load. Let’s compare them according to the developer experience.
Gatsby is easy to start with, especially if you already know React. However, Gatsby uses GraphQL to query local data and pages. Using Gatsby to build this simple blog might be overkill because GraphQL has a learning curve, and the querying and build time of static pages would be a bit longer. If you built this same blog twice, first with Gatsby and then with Next.js, the one built with Next.js would be much faster at build time because it uses regular JavaScript to query local data and pages.
I hope you take advantage of the power of the Next.js framework and see why it’s so much handier than some alternatives. It’s also a great choice if your website relies heavily on SEO because your app will be fast and easy for Google robots to crawl. That’s the reason why we will be using Next.js in this article to build a blog with the MDX library.
Let’s start by setting up a new Next.js app.
Setting Up
There are two ways to create a Next.js app. We can set up a new app manually or use Create Next App. We’ll go for the latter because it’s the recommended way, and it will set up everything automatically for us.
To start a new app, run the following in the command-line interface (CLI):
npx create-next-app

Once the project is initialized, let’s structure the Next.js app as follows:
src
├── components
| ├── BlogPost.js
| ├── Header.js
| ├── HeadPost.js
| ├── Layout.js
| └── Post.js
├── pages
| ├── blog
| | ├── post-1
| | | └── index.mdx
| | ├── post-2
| | | └── index.mdx
| | └── post-3
| | └── index.mdx
| ├── index.js
| └── _app.js
├── getAllPosts.js
├── next.config.js
├── package.json
├── README.md
└── yarn.lock

As you can see, our project has a simple file structure. There are three things to note:

_app.js allows us to append some content to the App.js component in order to make it global.
getAllPosts.js helps us to retrieve the blog posts from the folder pages/blog. By the way, you can name the file whatever you want.
next.config.js is the configuration file for our Next.js app.

I will come back to each file later and explain what it does. For now, let’s see the MDX package.
Installing the MDX Library
MDX is a format that lets us seamlessly write JSX and import components into our Markdown files. It enables us to write regular Markdown and embed React components in our files as well.
To enable MDX in the app, we need to install the @mdx-js/loader library. To do so, let’s first navigate to the root of the project and then run this command in the CLI:
yarn add @mdx-js/loader

Or, if you’re using npm:
npm install @mdx-js/loader

Next, install @next/mdx, which is a library specific to Next.js. Run this command in the CLI:
yarn add @next/mdx

Or, for npm:
npm install @next/mdx

Great! We are done setting up. Let’s get our hands dirty and code something meaningful.
Configuring the next.config.js File
const withMDX = require(“@next/mdx”)({
extension: /.mdx?$/
});

module.exports = withMDX({
pageExtensions: [“js”, “jsx”, “md”, “mdx”]
});

Earlier in this tutorial, I said that files under the pages folder would be treated as pages/routes by Next.js at build time. By default, Next.js will just pick files with .js or .jsx extensions. That’s why we need a config file, to add some customizations to the default behavior of Next.js.
The next.config.js file tells the framework that files with .md or .mdx extensions should also be treated as pages/routes at build time because the blog folder that contains the articles lives in the pages directory.
That being said, we can start fetching the blog posts in the next part.
Fetching Blog Posts
One of the reasons why building a blog with Next.js is easy and simple is that you do not need GraphQL or the like to fetch local posts. You can just use regular JavaScript to get the data.
In getAllPosts.js:
function importAll(r) {
return r.keys().map((fileName) => ({
link: fileName.substr(1).replace(//index.mdx$/, “”),
module: r(fileName)
}));
}

export const posts = importAll(
require.context(“./pages/blog/”, true, /.mdx$/)
);

This file can be intimidating at first. It’s a function that imports all MDX files from the folder pages/blog, and for each post it returns an object with the path of the file, without the extension (/post-1), and the data of the blog post.
With that in place, we can now build the components in order to style and show data in our Next.js app.
Building The Components
In components/Layout.js:

import Head from “next/head”;
import Header from “./Header”;

export default function Layout({ children, pageTitle, description }) {
return (
<>
<Head>
<meta name=”viewport” content=”width=device-width, initial-scale=1″ />
<meta charSet=”utf-8″ />
<meta name=”Description” content={description}></meta>
<title>{pageTitle}</title>
</Head>
<main>
<Header />
<div className=”content”>{children}</div>
</main>
</>
);
}

Here, we have the Layout component, which we’ll be using as a wrapper for the blog. It receives the meta data to show in the head of the page and the component to be displayed.
In components/Post.js:
import Link from ‘next/link’
import { HeadPost } from ‘./HeadPost’

export const Post = ({ post }) => {
const {
link,
module: { meta },
} = post

return (
<article>
<HeadPost meta={meta} />
<Link href={‘/blog’ + link}>
<a>Read more →</a>
</Link>
</article>
)
}

This component is responsible for displaying a preview of a blog post. It receives the post object to show as props. Next, we use destructuring to pull out the link of the post and the meta to show from the object. With that, we can now pass the data to the components and handle the routing with the Link component.
In components/BlogPost.js:
import { HeadPost } from ‘./HeadPost’

export default function BlogPost({ children, meta}) {
return (
<>
<HeadPost meta={meta} isBlogPost />
<article>{children}</article>
</>
)
}

The BlogPost component helps us to render a single article. It receives the post to show and its meta object.
So far, we have covered a lot — but we have no articles to show. Let’s fix that in the next section.
Writing Posts With MDX

import BlogPost from ‘../../../components/BlogPost’

export const meta = {
title: ‘Introduction to Next.js’,
description: ‘Getting started with the Next framework’,
date: ‘Aug 04, 2020’,
readTime: 2
}

export default ({ children }) => <BlogPost meta={meta}>{children}</BlogPost>;

## My Headline

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque maximus pellentesque dolor non egestas. In sed tristique elit. Cras vehicula, nisl vel ultricies gravida, augue nibh laoreet arcu, et tincidunt augue dui non elit. Vestibulum semper posuere magna, quis molestie mauris faucibus ut.

As you can see, we import the BlogPost component, which receives the meta and the body of the post.
The parameter children is the body of the blog post or, to be precise, everything that comes after the meta object. It is the function responsible for rendering the post.
With that change, we can move to the index.js file and display the posts on the home page.
Displaying Posts
import { Post } from “../components/Post”;
import { posts } from “../getAllPosts”;

export default function IndexPage() {
return (
<>
{posts.map((post) => (
<Post key={post.link} post={post} />
))}
</>
);
}

Here, we start by importing the Post component and the posts fetched from the blog folder. Next, we loop through the array of articles, and for each post, we use the Post component to display it. That being done, we are now able to fetch the posts and display them on the page.
We are almost done. However, the Layout component is still not being used. We can use it here and wrap our components with it. But that won’t affect the articles pages. That’s where the _app.js file comes into play. Let’s use that in the next section.
Using the _app.js File
Here, the underscore symbol (_) is really important. If you omit it, Next.js will treat the file as a page/route.
import Layout from “../components/Layout”;

export default function App({ Component, pageProps }) {
return (
<Layout pageTitle=”Blog” description=”My Personal Blog”>
<Component {…pageProps} />
</Layout>
);
}

Next.js uses the App component to initialize pages. The purpose of this file is to override it and add some global styles to the project. If you have styles or data that need to be shared across the project, put them here.
We can now browse the project folder in the CLI and run the following command to preview the blog in the browser:
yarn dev

Or, in npm:
npm run dev

If you open http://localhost:3000 in the browser, you will be able to see this:

Great! Our blog looks good. We are done building the blog app with Next.js and MDX.
Conclusion
In this tutorial, we walked through Next.js by building a blog using the MDX library. The Next.js framework is a handy tool that makes React apps SEO-friendly and fast. It can be used to build static, dynamic JAMstack websites in no time, because it is production-ready and comes with some nice features. Next.js is used widely by big companies, and its performance keeps improving. It’s definitely something to check out for your next project.
You can preview the finished project on CodeSandbox.

Thanks for reading!
Resources
These useful resources will take you beyond the scope of this tutorial.

Next.js documentation
Next.js and MDX documentation
“Create a Next.js App”, Next.js

Visit source: Post courtesy of : How To Build A Blog With Next And MDX

Categories
Uncategorized

Designing With Reduced Motion For Motion Sensitivities

CSS has recently added features that allow us to recognize certain user preferences and qualities of the user’s current environment. One of those new features, specifically the prefers-reduced-motion media feature, can be especially useful for designing more inclusive motion on the web. A few years back, I wrote an article about designing safer web animation…

Want to Read more ? CSS has recently added features that allow us to recognize certain user preferences and qualities of the user’s current environment. One of those new features, specifically the prefers-reduced-motion media feature, can be especially useful for designing more inclusive motion on the web.
A few years back, I wrote an article about designing safer web animation for motion sensitivity and the limited options we had at the time to design safe motion on the web. Some things have remained the same since that original article, like the types of motion effects that can be triggering, and the importance of context and user expectations. But what has changed is the existence and support of the prefers-reduced-motion media feature. That makes a big difference in how we can design the motion in our work to be inclusive and accessible.
Why Reduce Motion?
The release of iOS7 back in 2013 sparked a realization throughout the digital design world that some motion on screen — even if it was part of an interface — could have physical consequences for people with motion sensitivities. In the years since then, the major mobile and desktop operating systems have added functionality for people to reduce the amount of motion they encounter in their operating systems.
Articles like “Your Interactive Is Making Me Sick” and “Accessibility For Vestibular Disorders” share first-hand stories of how our design choices, especially around motion, can have physical consequences for those with motion sensitivities. The root causes of these motion sensitivities can vary greatly between individuals. For some, it’s rooted in a vestibular disorder, while for others it might stem from migraines or other factors. What’s triggering can also vary from person to person, or even from day to day for some. The physical symptoms individuals experience as a result of that triggering motion can range from slight dizziness or headaches to nausea or worse.
The design choices we make around animation in our work directly impacts how our work affects people with motion sensitivities. Knowing what kinds of motion are potentially triggering, and how we can mitigate them with our design choices, helps us design experiences that are safe for our audience and won’t cause unintended harm. Animation still absolutely can have a positive impact on our UX efforts, but it’s up to us to make sure we use it responsibly, just like we try to use our other design tools responsibly.
Prefers Reduced Motion On The Web
The prefers-reduced-motion media feature now has strong browser support. It’s supported in current versions of Edge, Firefox, Chrome, Safari, Opera, iOS Safari, as well as on Android Browsers and Chrome for Android. The level of support we have today makes it something that you can absolutely use in production. Also, if someone’s browser doesn’t support this feature, nothing bad happens, it will just be ignored and things will carry on as before.

On the development side, we can test for prefers-reduced-motion in the same way that we would use any other media query in CSS or JavaScript to find out if reduced motion has been requested.
In CSS that will look something like this:
@media (prefers-reduced-motion: reduce) {
/* reduced behaviour */
}

And in JavaScript:
let motionQuery = matchMedia(‘(prefers-reduced-motion)’);

const handleReduceMotionChanged = () => {
if (motionQuery.matches) //reduced behaviour;
}

motionQuery.addListener(handleReduceMotionChanged);
handleReduceMotionChanged()

Whichever way you choose to access it, this media query will return one of two values: no-preference (false), or reduce (true). Once retrieved, you can use these values to inform what you display in the browser.
Of the two values that can be returned, the only one we can be sure has been set intentionally is the reduce (true) value. No-preference (false) can mean that the person in question is fine with all types of motion, or it could mean that that preference just hasn’t been set yet. This makes any approach that equates the value of no preference (false) to the person in question opting in to all levels of motion unreliable. Because of this, the better approach is to reduce potentially triggering motion effects when a value of reduce (true) is returned.
For example, here the looping bounce animation is replaced with a fade in animation when reduced motion is requested:
/* A constant bouncing motion effect applied to the title */
h2 {
animation: bouncing 1.5s linear infinite alternate;
}

/* Replace it with a safer effect when prefers-reduced-motion returns true */
@media (prefers-reduced-motion) {
h2 {
animation: fade 0.5s ease-in both;
}

Reduced Motion From The Users’ Perspective
Most major operating systems allow people to set their preferences in their system settings. The exact wording and location of the settings vary, but the preference can be set on iOS, OSX, Windows, and Android operating systems.

The Prefers Reduced Motion Media Feature In Practice
Deciding how to put the prefers-reduced-motion media feature to use is where we have space for creating solutions that best fit the context of our products and content. For most web projects, you’ll want to first identify any potentially triggering motion effects on your site, and then use the prefers-reduced-motion media feature to provide a reduced version of that effect.
Let’s look at each step in more detail.
Identifying Potentially Triggering Motion
To find any potentially triggering motion you might have, go through some typical user flows for your site or product and take a closer look at the motion effects used: Do you have any interactions that have large movements? Any large zooms, spinning effects, or parallax effects? All of those types of animated effects are very likely to be problematic for people with motion sensitivities. In contrast, animated effects like color fades, opacity changes and small changes in scale are unlikely to be problematic. If in doubt, it can’t hurt to add the effect in question to your “to reduce” list to err on the side of caution.
The Web Content Accessibility Guidelines recommend providing a reduced version for any “motion that creates the illusion of movement…that is not essential to the content’s meaning”. I think it’s helpful to see some examples too, especially if you don’t consider yourself to be sensitive to motion on screen. I cover examples of potentially triggering motion in my previous article and this post on the Webkit blog has some too. Chances are, unless your site relies heavily on motion, you’ll end up with a fairly short list of effects to focus on here.
Create A Reduced Motion Version
Next, you want to determine the most appropriate reduced motion condition for these potentially triggering effects. Can the animation easily be adjusted to use a non-motion effect like an opacity fade or crossfade for reduced motion requests? Would pausing the motion or removing the effect entirely for reduced motion preserve the meaning of the content?
The role of the motion in question will be an important factor in deciding what the most appropriate reduced version would be. You don’t want to unintentionally remove content or degrade the overall experience. Here are a few examples of what might work well for the potentially triggering effects you find:
Large Page Transitions
Large page transition effects can likely be replaced with a crossfade effect for a reduced motion mode. The same is usually true for large zooming or spinning transitions that transition between different states or views.
Animated Illustrations
Animated illustrations, on the other hand, might be best replaced with a static version for reduced motion if they are mostly for personality or branding effect. You’ll want to make sure the static version is still meaningful, and the arrangement that has the most meaning may not always be the very beginning or very end of the animation. Adding in functionality to play animated illustrations on demand for reduced motion could also be useful by allowing people to play the animation when they’re ready for it.
Don’t forget to consider the motion in your animated gifs or auto-playing videos here as well. These can also contain potentially triggering motion and would need a reduced version if they do.
Parallax Effects
Parallax effects and exaggerated smooth scrolling effects are universally triggering for folks with motion sensitivities, so those should be significantly reduced or entirely removed for reduced motion. (Every single person I’ve talked to in my research on this has called out parallax specifically as being a problem for them.) Smooth scrolling effects can be replaced with the default browser anchor link behaviour as described here by Eric Bailey. Removing parallax effects for reduced motion is the ideal solution, but make sure to check that all the necessary content is still visible and usable with the parallax removed.
In most cases substituting the potentially triggering effect with a safer effect for reduced motion is the best way to preserve as much of the content’s intent and usability as possible. Luckily, substituting a reduced effect can be pretty straight forward too.
An Example Of Reducing Motion
For example, let’s say I flagged this header animation as potentially triggering when I went through my site. The motion is large enough to create the illusion of motion, so it’s likely to be triggering, and the multiple directions of motion are also likely to be problematic. It’s definitely one I’d put on my list of effects that need a reduced version when reviewing my site.

The Airpods Pro page also responds to reduced motion preferences, but in a very different way because of the content and effects used. Almost all of the motion on the page could be potentially triggering since it has a lot of big zooming movements and parallax-style effects. When reduced motion is requested, all the parallax and large motion effects are removed, but they do more than just pause or remove the animations. The version you see with reduced motion selected has been designed with care to preserve the same content and meaning from the full motion experience. (Here’s a video of The Airpods Pro site both with and without reduced motion selected for reference.)

Add Custom Toggles For Motion-Heavy Experiences
I mentioned above that most “task-based” sites likely have only a handful of animations that might be triggering and need a reduced version. But those aren’t the only kind of web sites out there on the web. Projects that involve a large amount of motion, like sites that are meant more for storytelling or creating an experience might benefit from a slightly different approach.
For projects like these, it would be difficult to make a list of potentially triggering motions and provide a reduced alternative for each because almost all of the motion used could be potentially triggering. Plus, the motion is very much part of the content and its meaning. Designing a reduced motion mode for these types of sites will take a more global approach and more effort to be sure the meaning of your content is preserved even as motion is reduced.
For these highly animated experience sites, providing a visible custom motion toggle is a useful thing to include. This will allow people who may not yet know about the reduced motion setting, or who are experiencing some motion sensitivity at that moment in time, to quickly adjust the experience. A motion toggle provides a way for motion-sensitive folks to participate in your content in a way that won’t make them sick. That’s definitely better for everyone involved than them having to avoid your site entirely.
Context Is A Key Factor
Remember that context also plays a big role here. No one wants to be surprised by large amounts of motion where they don’t expect it. If you’re visiting a site billed as a highly interactive storytelling experience you’ll have very different expectations than when you’re visiting your bank’s web site. Both of those sites certainly could feature large amounts of animation, but it would be an unexpected surprise on the bank site.
Building A Custom Motion Toggle
The idea of a custom toggle is something that I mentioned back in my 2015 article, but today it’s a much more viable option. On today’s web, we can create one with more ease, and even make a smarter toggle than we could have just a few years ago.
Marcy Sutton has a great example of how a modern custom motion toggle could work in this CodePen. (This example is part of her course on making accessible web apps, which is also very much worth checking out.) Her example uses a toggle to remove all motion because it only includes one animation, but this approach can be used to provide reduced motion effects across an entire application or site following the same logic as well.
The key feature of this approach is how nicely Marcy ties it in with modern web technology, i.e. prefers reduced motion and local storage. When using this approach, if someone comes to your site with reduced motion requested, they automatically get the reduced motion version without having to manually activate the toggle as well. And if someone invokes the toggle to reduce motion, that preference will be saved via local storage so they won’t have to repeatedly make this selection every time they visit.

The official Animal Crossing site is a wonderful real-world example of a custom reduce motion toggle combined with the prefers-reduced-motion media feature. It’s one of my favorite examples of handling reduced motion. The design choices they made around how to reduce potentially the triggering motion, while still keeping true to the overall feel of the site and the content, is great. I wrote more about how they pulled it off in this blog post. There are a lot of sites out there whose audience could benefit from a similar approach.
Other Ways To Use Motion Toggles
If you already have a preferences or settings panel, adding a toggle to request reduced motion could be a valuable thing to add to these settings like Twitter does on its site. In this case, there aren’t large amounts of motion immediately presented when visiting the site and there’s already a settings panel, so implementing the toggle as part of the settings preferences fits well. Twitter’s toggle also respects OS-level settings via the preferes reduced motion query and is preset to either on or off based on what the user has set at the OS level. Designing your motion toggle to respect OS settings is definitely a smart approach to implementing them well no matter where the toggle might appear.

Contextual toggles are another approach that could be used to reduce motion on specific animated illustrations or other content areas that appear throughout your site. The Dark Side of The Grid article does this nicely by adding contextual toggle buttons to each animate figure to allow the reader to play the animation when they want to see it, but not have it loop endlessly while they are reading.

Along those same lines, Dave Rupert shared a technique for combining prefers reduced motion with the picture element to show static elements in place of animated gifs when reduced motion has been requested. Chris Coyier took that one step further and suggested presenting a play toggle for those animated gifs based on the same approach. Steve Faulkner’s gif de-animator example could also be a useful approach.
All of these, or something similar, could be good options for mitigating any potentially triggering motion on the web. I bring up these examples for two reasons. The first is to show that there are a number of ways to approach providing reduced motion variations and you have lots of flexibility to find an approach that fits best for your content. And secondly, as time goes on and more folks are building sites with reduced motion options, the more innovative solutions we’ll see shared in the community.
There are many creative ways to add toggles and settings in a way that makes sense for the context of your project. It’s an interesting parallel that we’re seeing more and more web sites include settings panels or options for setting preferences like dark mode. Including an option for reduced motion could be a natural next step.
The More We Use It, The Better It Will Get For Everyone
I think it’s important for us, the people designing and building things for the web, to take advantage of the prefers-reduced-motion media feature to make our work more inclusive. By taking steps to respect motion preferences we make the web safer for more people to use, and that can only be a good thing. We absolutely can be expressive and creative with motion on the web while also being responsible and inclusive.
But the awareness level is still something we need to be, well, aware of. Not everyone who might need reduced motion is aware of the option in their OS settings. Perhaps even fewer people know that it can take effect on content in their browser too since so few websites currently take advantage of it. The more we take advantage of the prefers-reduced-motion media feature, and provide a quality reduced motion experience with it, the more meaningful of a feature it will be for those who need it.

Visit source: Post courtesy of : Designing With Reduced Motion For Motion Sensitivities

Categories
Uncategorized

Smashing Podcast Episode 24 With Cassie Evans: What Is SVG Animation?

Today we’re talking about SVG Animation. How can vector images, JavaScript and CSS all work together to provide engaging motion graphics? I spoke to SVG expert Cassie Evans to find out. Show Notes The SVG Animation Masterclass with Smashing Conference Cassie on Twitter Cassie’s personal website Weekly Update “How To Do More With Vue Router”by…

Want to Read more ? Today we’re talking about SVG Animation. How can vector images, JavaScript and CSS all work together to provide engaging motion graphics? I spoke to SVG expert Cassie Evans to find out.

Show Notes

The SVG Animation Masterclass with Smashing Conference
Cassie on Twitter
Cassie’s personal website

Weekly Update

“How To Do More With Vue Router”by Timi Omoyeni
“Building React Apps With Storybook”by Abdulazeez Adeshina
“Everything Developers Need To Know About Figma”by Jurn van Wissen
“4 Ways To Creatively Use Icons In Your Mobile Apps”by Suzanne Scacca
“Building A Component Library With React And Emotion” by Ademola Adegbuyi

Transcript
Drew McLellan: She is a front end developer and speaker with a background in graphic design and motion design. She got started with coding back in the days of MySpace and Neopets and is on a mission to make the web more whimsical again. She currently works at Clearleft in Brighton UK, and can usually be found tinkering with SVGs on CodePen. So we know she’s a skilled developer and SVG expert, but did you know she was National Junior Wing Walking Champion for three years in a row? My smashing friends, please welcome Cassie Evans. Hello Cassie. How are you?
Cassie Evans: I’m smashing, thank you.
Drew: I wanted to talk to you today about one of your passions, which is SVG, and in particular the animation side of things. I think most people listening to this podcast will have heard of Scalable Vector Graphics in some shape or form. I know I’ve used them heavily with things like logos and icons in recent years, but let’s not assume. So for anyone who isn’t really up to speed with SVG, what makes it different from other ways of adding graphics to a webpage?
Cassie: So, a lot of the clue’s in the name, of course. So, SVG stands for Scalable Vector Graphic. So, these are first the images that can be any size. You can make them really, really small or really, really big, and they’ll retain image quality and won’t get pixelated like JPEGs or PNGs.
Cassie: You can also make them really, really small, so small in file size. So, everyone’s kind of added a PNG to their site that’s a million megabytes and seen what that does to page load. So, you can add all sorts of cool illustrations and stuff to your site without impacting on performance too badly, and also you can animate them so that’s the most exciting bit. With JPEGs or PNGs, if you wanted to animate them or move bits of them around, you’d have to cut them out into little pieces or kind of layer them on top of each other, whereas with SVGs you’ve got actual elements in the SVG. It’s got a DOM structure just like HTML does.
Drew: So, I guess in a world of mobile devices with different screen sizes and different pixel densities and sort of constrained data connections, SVG really is a format that’s more suited to the modern web than the old graphic styles. Is that fair?
Cassie: Yes, definitely.
Drew: Most images are of course sort of binary based, but SVG is totally view sourcable, isn’t it?
Cassie: Yeah. So, that’s really exciting because you can actually right click and view source on an SVG and you can traverse around the DOM and kind of see what you’ve got and kind of get to learn it that way, which I find that really great. It feels a lot like the old web, like being able to go to a website and view source on it and see how it’s put together.
Drew: SVG kind of feels more sort of native and integrated into the web than things like maybe Canvas or even back in the day Flash, which of course flash was scalable vector graphics, wasn’t it? In its own way. And those technologies feel very much like a black box that’s encased on the page that you can’t sort of get in or out of. SVG is a lot more integrated isn’t it?
Cassie: Yeah. It’s funny that you’d say that because I always refer to Canvas as a black box when people are asking whether they should use Canvas or SVG for something. I think a lot of the time, obviously it depends on the use case, but one of the things with Canvas is if you don’t have JavaScript for some reason, if your code fails, you end up with a little black box with nothing in it. So you could create this crazy infographic, all sorts of things going on inside this Canvas element, and then you just lose it all. Whereas SVG, it’s a lot more aligned with progressive enhancement, so you can have an animated SVG, maybe that’s animating using JavaScript, but then without JavaScript you will still have the illustration. You’ll still have the SVG there.
Drew: And SVG isn’t new to the web, is it? It’s been around for quite a while.
Cassie: It has, yes. It’s been around for longer than I’ve been doing stuff on the web.
Drew: And it certainly seems to be coming into its own a lot more with things like animation, like you’ve been saying, but also as we were mentioning, the way that it scales just makes it perfectly suited when we’re designing sites that might be viewed on a retina display with double the pixel density, or need to be delivered over a mobile connection where you want things to be as performant as possible. So we know SVG has got a DOM, you mentioned that. Does that mean that the things in it can be manipulated with code?
Cassie: Yes, so that’s the most exciting thing. You can get at SVG elements and you can animate them and move them around just like you can with HTML DOM elements, and it also means from an accessibility perspective, SVG has a DOM so you can traverse that DOM if you’re using a screen reader or something, so you can make SVG graphics very accessible to screen readers.
Drew: Yes, so I was going to ask about the situation with accessibility because classically, graphical stuff on a page is one of the most difficult things to make accessible. So are there sort of attributes that you can add to hint? Can you use the ARIA stuff in SVG or how does that work?
Cassie: Yeah. You can use ARIA labelledby, but you also have title and description tags that you can put inside an SVG.
Drew: That’s incredible and in terms of sort of motion preferences, because that’s something that we’ve seen recently with a media query in CSS to see that the user prefers reduced motion and you can change your animations and things based on that, is that something you can do in SVG or does it have to be implemented a little bit more manually?
Cassie: Well with SVG people often talk about SVG animation like it’s its own separate kind of special thing and of course we used to have SMIL. We still do have SMIL technically. It was getting deprecated, but it’s actually not being deprecated anymore. It’s just not really as widely used and not worked on anymore, but we used to have SMIL and that was what most people refer to as SVG animation. Whereas now, SVG animation could mean any of those things. It could mean SMIL, it could mean CSS animation, or it could mean animating using JavaScript or a JavaScript animation library. So, there’s lots of different options but with CSS animation and JavaScript animation the option to use prefers reduced motion is there and should definitely be used.
Drew: So you mentioned CSS animation and of course there’s a certain amount that we can do, like with HTML elements and CSS animation, to create graphics and motion on a page. SVG just like blows that out of the water in terms of flexibility doesn’t it?
Cassie: Yeah, definitely. I think people make amazing things with just CSS, like Lynn Fisher makes really amazing things. There’s all sorts of people making crazy CSS only illustrations, but it takes a lot of time and the handover for that is pretty impossible. Like if you imagine a designer giving you an illustration and asking you to recreate that in a CSS, that would be a large ticket. So SVG kind of makes it a lot more feasible to have these interdisciplinary teams and pass things over from one person to another. So you can have an illustrator or a designer create an illustration in a vector graphics program like Illustrator, and then they can pass that SVG over to a developer who can animate it.
Drew: And I suppose that would fit quite well into people’s established workflows. We’re using things like Git, because SVG is text-based, isn’t it? So presumably, committing SVGs into Git you get all that ability to diff and merge and all those sort of powerful features that you get with other text-based stuff. Is that right?
Cassie: Yeah, exactly.
Drew: So it’s kind of like, well I say kind of like, it absolutely is graphics expressed as code.
Cassie: Yes.
Drew: Isn’t it? SVG?
Cassie: It is.
Drew: And it’s quite a lot like HTML in its syntax. It’s another XML based language, isn’t it?
Cassie: Yep.
Drew: So it has tags and attributes and nested children and all that sort of stuff that your average web developer is going to be used to.
Cassie: I think that that’s what I love the most about SVG is I’m really into creative coding and also teaching people, and I found that teaching people who are more of a creative leaning, they sometimes get a little thrown off when you immediately jump in with JavaScript or Python or something like that for creative coding, but without fail I’ve managed to get anyone that I taught on board with SVG because it’s got this really approachable entry points because it does look like HTML. So, you can give someone with an understanding of HTML and how to build websites SVG, and it looks the same, but it’s the graphics instead of documents and then you can animate that with CSS to start off with which is also a little bit more comfortable, and then you can kind of progress to animating it with JavaScript. So it’s a really good learning curve.
Drew: And of course it can be dynamic. It’s not just a case of creating motion. You can actually make the properties of it dynamic. So, one of the interesting things I’ve seen SVG used for, and it’s a grand term, but like data visualization, DataViz, and drawing graphs and charts and of course things like dashboards that we seem to have everywhere these days. SVG is sort of perfect for that isn’t it?
Cassie: Yes, definitely. SVG is great for DataViz. All the way from kind of small DataViz up to D3 which is very well known DataViz library that uses SVG under the hood. But you could also just, if you’ve got a little bit of data that you wanted to show on a web page, you could create a chart in a graphics editing program and then you could just use JavaScript to change those values and kind of change how your graph looks. So you don’t have to go all in with a massive database library. You can kind of just start off small.
Drew: Obviously sort of traditional graphs and charts and things are just sort of the tip of the iceberg when it comes to ways that SVG can help with data visualization. I saw you had an interesting project that you did at Clearleft with your solar panels on the roof. Can you tell us a little bit about that?
Cassie: That project was actually meant to be me learning D3 and then I got very distracted. We have some solar panels on the roof of our office, which I miss thoroughly actually it’s been so long, but yeah we’ve got some solar panels on the roof and I found out shortly after starting working at Clearleft that we had an API that was attached to the solar panels that you could hook into. So I was like…
Drew: Amazing.
Cassie: Right. I need this to be my side project, and I had a little look at what we got back from the API and amongst the data there was the amount of CO2 saved and they measured the amount of CO2 in trees.
Drew: Okay.
Cassie: So I was immediately like, wow, well we’re going to have to plot this somehow, but I want to measure it in trees because that’s such an interesting way of plotting this. So, all of my D3 aspirations went out of the window and I sat down in illustrator and recreated an illustration of our office building and created a jungle of trees and plants and stuff, and then I’m looking at how much CO2 we have saved and then kind of growing in these plants and vines and stuff. Yeah, it’s great. It’s really good to check back occasionally as well and just see how much the jungle’s grown.
Drew: It’s an amazingly creative way of visualizing that data, whereas if you were relying on traditional software for creating graphs and charts and things, there’s never going to be a function to create an office building with trees on top. That that just doesn’t exist, but then using JavaScript and using SVG to be able to generate those graphics and using the JavaScript to manipulate them to adjust the values that are being shown, you can come up with something completely new in a completely novel way of communicating an idea to the person using the site. So, we know we can hand codes the markup for SVGs, which me as a developer, I think that sounds great because I can go in and I can be very precise, but that is probably a technical skill that isn’t going to suit everybody, particularly those whose strengths being more visually creative than actual coding. So are there other ways to author SVGs or do you have to just do it by hand and in a text editor?
Cassie: I think I wrote a hamburger icon once just from the top of my head and I was super proud of myself, but the rest of the time I create SVGs in Illustrator or other alternatives. Affinity designer is really good. Illustrator has obviously the Adobe pricing structure, which can be a little bit out of people’s budgets, but Affinity Designer is like a once off purchase and it’s pretty good actually, and the SVG markup that you get out of it is good which is the most important thing. But yeah, I don’t think there’s anyone apart from, it’s a guy called Blake Bowen on the GreenSock forums, and I think that he could probably hand write SVG path data, but I don’t think it’s a thing that everyone can do. I don’t think that it’s a thing that we should be aspiring to do. It’s quite verbose.
Drew: So being a lightweight by using a dedicated graphics tool to author SVGs, it’s a perfectly valid route.
Cassie: It’s fine. Choose your battles.
Drew: Are there any tools out there that are free for filtering SVGs or is it all commercial?
Cassie: I think Inkscape is free, but yeah, I would really recommend Affinity Designer. I think for the kind of cheaper tier, I think it’s worth paying a little bit of money towards these tools because it can be quite frustrating working with clunky vector graphics tooling.
Drew: In terms of the output, the SVG output that you get from these tools, is it all the same? Do they all just basically generate the same SVG or some better than others?
Cassie: Yeah, that’s a very good question. I find Illustrator is a lot better than other tools, but it’s not something that should hold you back or make you feel like you need to spend that money. So at the end of the day you’ll get some markup out, some editors you might need to do a little more tweaking than others but most of them you will get workable SVG code out of it.
Drew: I’ve found personally when I’ve tried to create SVGs, and I’m not graphically skilled, that I get varying results depending on how I actually draw something in say Illustrator. Presumably when it comes to thinking about how something’s going to be animated, it matters more how you construct your shapes in the editors. Is that fair?
Cassie: Yeah, definitely. Also SVG has an implicit drawing order, so it’s not like HTML. So with HTML, you can use that index to kind of move things around and put things underneath or on top of other things, whereas with SVG the order that it is in the code will be the order that it is displayed on the web page. So that’s something to kind of keep in mind when you’re drawing out an SVG is getting your layers in the right order and then anything that you want to move as one unit you should wrap in a group and anything that you want to move separately from something else you need to make sure that it’s actually a separate shape.
Drew: Yeah, so I mean by getting your layers in order there you’re literally talking about the layers palette in Illustrator and dragging the things around before you export, is that right? Just getting them in the correct order and then exporting.
Cassie: Yes.
Drew: And once you have exported it are there tools that will help sort of optimize or, because I know with PNGs, there’s a whole load of things I use to cut all the craft out of the file and reduce the file size. Are there’s similar things for SVG?
Cassie: Yeah. There’s a tool called SVGOMG, which I use a lot, which is great and you can use that for batch processing. There’s terminal commands for it, but you can also, there’s a Gooey in the browser, which I really like for large illustrative SVGs because I think it’s nice to build it into, say your build process, if you’re dealing with a huge load of icons that you all want processed in the same way, but if you’re dealing with an illustrative SVG, it’s nice to be able to use the gooey because you can flip between the code view and the visual view and you can just make sure that the things that you’re changing in the settings aren’t visually affecting your SVG in a negative way and aren’t affecting the code in a way that you don’t want it to.
Drew: Presumably these tools, things like Illustrator, are great for creating graphics, but they’re not going to help us at all with animation are they? That all happens once we get the SVG and put it into a webpage.
Cassie: Yeah.
Drew: So what does that process look like? I mean, obviously it’s difficult to talk about animation too much on an audio podcast, but in terms of just the sort of process you’d go through. You put your SVG into a page, what happens then? How do you address parts of it or what do you do to start working with it?
Cassie: So it’s very similar to animating HTML DOM elements in that you need to be able to target the elements themselves. So that would involve putting classes or IDs on them so that you can target them, and then you can either use CSS for animation. There are some issues with transforms with CSS that are still kind of being ironed out a little bit. So I tend to recommend CSS for experimenting and playing with SVG animation. When it comes to SVG animation and production I will usually recommend GreenSock, which is a JavaScript animation library, and yeah, well with GreenSock and with CSS you basically just get the SVG elements and then do stuff to them.
Drew: So do you have full access to interacting with the complete range of JavaScript APIs and things like scroll events and mouse events and resizing and intersection and that whole browser environment presumably you’ve got at your disposal, to then have your animation interact with and respond to.
Cassie: Yeah. So anything that you would use in normal JavaScript, so like mouse events or scrolling, that kind of thing, you can look for that and then do things to your SVG on those events. You’ve also got SVG specific methods and stuff, like get PATHlink I think is one, stuff like that so there’s specific SVG methods that you can kind of play around with.
Drew: So you could do things for example, like start an animation as an SVG comes into view on the page if it’s scrolled out of place and stop it when it gets scrolled away and restart it if it comes back into view and that sort of thing.
Cassie: Yeah. There’s actually a new GreenSock plugin called ScrollTrigger and previously I think a lot of people have used ScrollMagic for scroll animations, but that was a different library to GreenSocks, so they had no kind of affiliation with each other so you were just mashing together two different libraries, one that did animation and one that did scroll events. Whereas GreenSock have now just made a scrolling plugin that works with GreenSock and it has one event listener. One scroll listener. Yeah. So it’s very, very performance and I’ve played around with it recently and it’s great. It’s really easy to use.
Drew: Is that automatically buffered so you’re not completely overrun with scroll events being fired at your code and all those sorts of traditional problems?
Cassie: Yeah all of the traditional problems, they’re kind of doing all the heavy lifting in the background for you, which is good.
Drew: Fantastic. Would GreenSock be the tool then, the sort of library, that you’d recommend people to start using if they were looking at SVG animation?
Cassie: Yes, definitely. Mostly because GreenSock, it’s the only animation library out there that handles SVG transforms consistently cross-browser and that isn’t just something that they do that they’re not focusing on anymore. It’s a constant effort from their part so they’re constantly kind of looking for SVG bugs and fixing things. So it’s very reliable. Definitely.
Drew: What is the sort of cross-browser situation like with SVG? Is it fairly reliable or are you constantly having to deal with inconsistencies across different browsers and platforms?
Cassie: If you are animating with GreenSock then you don’t. If you are animating with CSS, yeah there’s quite a few inconsistencies. It’s mostly to do with how transforms are handled. So with HTML DOM elements transforms are measured from the center of them, and with SVG transforms are measured from the top left hand corner, but in some browsers it’s the top left hand corner of the element itself, and in other browsers it’s the top left hand corner of the SVG view box parent. So you can end up, if you’re rotating things around in some browsers, they might end up going in a different trajectory than others.
Drew: That sounds like most of the animation I’ve ever tried to script. Things going in unexpected directions. We’re used to sort of traditional animation tools, having things like easing options, ease in ease out and that sort of stuff. Presumably that’s something that GreenSock then brings to the table.
Cassie: Yeah. GreenSocks got a lot of really good easing equations that you can use. Yeah, and they’ve got a great ease visualizer so you can have a little look at how will the eases work.
Drew: That’s really useful, and again that’s something I always struggle with. It’s like, I know I should do something. It shouldn’t just move linearly from A to B, but what do I do? So yeah, being able to visualize stuff is really handy.
Cassie: When I started making animations I made a lot of space animations because I hadn’t quite figured out how easing worked yet, so in space everything does move linearly because it’s just floating around. It doesn’t have gravity to contend with, so I made lots of rockets, planets bobbing around and it was fine.
Drew: I mean I guess you, being such an SVG enthusiast, you probably see people they’re putting SVG to all sorts of creative uses. What sort of things, just to get the juices flowing, what sort of things have you seen people do with SVGs that has been particularly impressive or creative?
Cassie: I think one of the things that I love with SVG is the fact that you don’t just have to use it for illustrative SVG animations by themselves because it is XML based markup, just like HTML. You can kind of mix it in with the HTML DOM. So, I think it’s a bit of a nerdy thing, but my favorite examples of SVG animation are when people mix SVG animation with semantic DOM elements, so when you have a button that is a proper button but it’s got some SVG icon illustration in it so that when you click that button something joyful happens, and I love that because it’s this perfect marriage of kind of whimsical joyfulness and proper semantic DOM elements.
Drew: You’ve said in the past that front end development has become very serious in recent times. Has all the fun gone out of the web Cassie?
Cassie: That’s a very serious question. Has all the fun gone out of the way.
Drew: Because things used to be a lot more fun, but maybe not as efficient and have we got too serious with it?
Cassie: Yeah. I think efficiency is a real killer when it comes to adding these little enhancements on. I find that in my day job at Clearleft, I quickly realized that if I wanted to have animations as an extra thing, as like another ticket or something, it was very hard to get sign off on that. It was always the thing that if the project starts being a little bit cramped on time, it’s the first thing to go. But I think that once you’ve got a good understanding of animation and SVG you can just sneak things in to start off with. So when you’re building a component and you see an opportunity for a little bit of animation and you can just add it in and it gets easier because then people start seeing the possibilities and people start realizing that the clients really like that kind of thing, and then you can kind of get a little bit more time to work on it.
Drew: It is the sort of thing that can just really elevate an experience beyond unsatisfactory or unsatisfying sort of boring transaction to something that gives the user just a little bit of joy and gives her a whole sort of perception of quality and some brand personality as well, I think with animation. There’s a…
Cassie: Yeah.
Drew: There’s a lot in terms of brand personality that can be put across with those sort of little touches.
Cassie: But I think this is something that a lot more people are realizing now as well, not just with SVG and animation, but personality in general, and I think that there’s a lot more weight that’s being given to copy that’s written well and has a bit of personality and illustrations that aren’t just from a stock library that are unique to that company or that person and animations are a big part of that. And I think that I personally feel like we’re seeing more of these websites nowadays and I think that we went through, and are probably still going through a little bit of efficiency first period, but I think as with anything people start getting bored of that and it does seem like a lot of websites suggest being churned out by some corporate mega machine and people are starting to push back, I think. Max Bock made a site recently called the whimsical web and it’s got a lot of personal sites on there that are really joyful for various different reasons and I think we’re starting to see a lot more of that.
Drew: Is it possible to go too far with adding animation and sort of too much personality perhaps to a site?
Cassie: Yes. Definitely. I’m not a huge fan of websites that are very, very, whizbang. Like websites that are animation first. You get to the page and everything’s moving and you’re trying to read text as you’re scrolling, but it’s moving while you’re trying to read it. I’m not a fan of that. I really like looking at animation as an enhancement and I think that’s why SVG, I think is so great because you can kind of build an otherwise quite sensible website, but you can have these little whimsical touches throughout it.
Drew: And it’s crucial, isn’t it, as we mentioned before, the accessibility sort of aspect of things that it is possible to create a nicely accessible SVG, even if it has sort of content, if you’re locked in there, it’s not locked. It’s accessible to screen readers and then hopefully to everyone who visits the site. As I say, it’s hard on a podcast to really get into the practicalities of, well, we can’t show animation or anything, but you’re running an online workshop with Smashing Conference all about SVG, aren’t you?
Cassie: Yes, I am.
Drew: It’s the SVG animation MasterClass and that starting on October the eighth and it’s quite an unusual format. It’s two hours on Thursdays and Fridays. That’s an unusual way to do things, isn’t it?
Cassie: Yeah. I’m actually really happy about that because I’ve done a version of this workshop before. I spent a large part of 2019 putting it together. It was my baby, my passion project, and then I had quite a few workshops booked in and then the situation happened and all of them got canceled. So I got the opportunity to run it twice before the situation, and it was really great but it was a lot of content and it was a full day workshop. About eight hours and you could tell by the end of it people’s brains are just switching off because you’re sitting in a room trying to absorb information for eight hours. So I’m quite excited about this format because it means that I could divide it up into sections that kind of work by themselves and it gives people a chance to learn that and process it a little bit and let it sink in before they get the next load of information. So I think we’re going to get some really interesting things at the end of it just because people have had more time to absorb.
Drew: So it’s a Thursday and a Friday, a Thursday and a Friday, and then a Thursday to finish it off with two hours on each of those days followed by Q and A. I think that’s right, isn’t it?
Cassie: Yes.
Drew: Q and A on each session. What would those attending expect to learn? What should their expectations be in terms of what skills they might pick up?
Cassie: So it’s more angled towards the animation coding side of SVG animation. So we’ll cover a little bit of getting SVGs out of a graphics editor, and then the whole process from getting the code out through to starting to work with it. So optimizing and adding the right classes and structuring it properly, and then we’ll work on animating SVGs. So we’ll be using CSS. We’ll also be using GreenSock, which is the animation library that I mentioned, and we’ll be covering what I kind of refer to as SVG super powers. So this is stuff that it’s, aside from the animation, it’s the things that you can do with SVG.
Cassie: So that’s like clipping, and masking, and stroke animation, and filters, and all of that stuff is just so important to understand with SVG because it unlocks all of these kinds of super powers that you can play with. And we’ll also look at performance and accessibility, and also a bunch of the kind of little tips that I’ve picked up and learned along the way. So, little handy tips that I find useful for my workflow, handy tips that help with flashes of unstyled content before you start animating. Little tips like that.
Drew: That sounds really useful. I looked just before we started our interview and there are still some early bird places available, which is great. So if people are quick they might still catch those and you can register at smashingconf.com. There’s actually a number of different master classes that are being run at the moment and there are early bird deals and bundled deals on some of them as well. So there’s things like JAMstack, CSS layout with Rachel Andrew, Vue.js, web performance, GraphQL, loads of different Masterclasses and you can find all those at smashingconf.com. So I’ve been learning all about SVG. What have you been learning about lately Cassie?
Cassie: Oh, I’ve been recently learning quite a lot about Eleventy. I did a little site redesign recently using Eleventy and I’ve also been doing Andy Bell’s Eleventy from scratch course. So I’m getting quite into static site generators in general at the moment.
Drew: That’s great. I think we’re all getting into static site generators more as time goes on.
Cassie: It’s the future.
Drew: If you dear listener, would like to hear more from Cassie you can of course sign up for this animation Masterclass with Smashing Conf, but also you can find her on Twitter where she’s @Cassiecodes and her personal website is cassie.codes and that links to her CodePen, which is a great place to explore. Thanks for joining us today Cassie. Do you have any parting words?
Cassie: I would like to say that Smashing and I are offering for free tickets to my workshop. So they are diversity tickets that are going out to anyone that’s underrepresented in tec or going through a tough financial time at the moment. So you can apply for that on the webpage about my workshop and I hope to see you there.

Visit source: Post courtesy of : Smashing Podcast Episode 24 With Cassie Evans: What Is SVG Animation?

Categories
Uncategorized

How To Automate API Testing With Postman

One of my favorite features in Postman is the ability to write automated tests for my APIs. So if you are like me and you use Postman and you are tired of manually testing your APIs, this article will show how to harness the test automation feature provided by Postman. In case you don’t know…

Want to Read more ? One of my favorite features in Postman is the ability to write automated tests for my APIs. So if you are like me and you use Postman and you are tired of manually testing your APIs, this article will show how to harness the test automation feature provided by Postman.
In case you don’t know what Postman is or you are entirely new to Postman, I will recommend you check out the Postman getting started documentation page and then come back to this article to learn how to automate testing your API with Postman.
APIs or Web APIs pretty much drive most of the user-facing digital products. With that said, as a backend or front-end developer being able to test these APIs with ease and more efficiently will allow you to move quickly in your development lifecycle.
Postman allows you to manually test your APIs in both its desktop and web-based applications. However, it also has the ability for you to automate these tests by writing JavaScript assertions on your API endpoints.
Why You Should Automate API Tests
Testing in software development is used to ascertain the quality of any piece of software. If you are building APIs as a backend for a single frontend application or you are building APIs to be consumed by several services and clients, it’s important that the APIs work as expected.
Setting up automated API tests to test the different endpoints in your API will help catch bugs as quickly as possible.
It will also allow you to move quickly and add new features because you can simply run the test cases to see if you break anything along the way.
Steps To Automating API Tests
When writing API tests in Postman, I normally take a four step approach:

Manually testing the API;
Understand the response returned by the API;
Write the automated test;
Repeat for each endpoint on the API.

For this article, I have a NodeJS web service powered by SailsJS that expose the following endpoints for:

/ — the home of the API.
/user/signup — Signs up a new user.
/user/signin — Signs in an exiting user.
/listing/new — Creates a new listing(a listing is details of a property owned by the user) for an existing user.

I have created and organized the endpoints for the demo service we would be using in this article in a Postman collection so you can quickly import the collection in postman by clicking the button below and follow along.

So let’s follow my four steps to automating API tests in Postman.
1. Test The API Manually

I will open Postman and switch over to a workspace I created called demo which has the postman-test-demo-service collection. You will also have access to the collection if you imported it from above. So my postman would look like this:

Our first test is to test the home endpoint(/) of the API. So I would open the request on the sidebar called home you can see it’s a Get request and by simply pressing Enter, I would send a GET request to the web service to see what it responds with. The image below shows that response:

2. Understand The Response Returned By The API

If you are following along and also from the screenshot above you will see the response came back with a status code of 200 OK and also a JSON body with a message property with the value of You have reached postman test demo web service
Knowing this is the expected response of the / endpoint on our service, we can proceed to step 3 — writing the actual automated test.
3. Write The Automated Test

Postman comes out of the box with a powerful runtime based on Node.js which gives it’s users the ability to write scripts in the JavaScript language.
In Postman, you add scripts to be executed during two events in the Postman workflow:

Before you make a request.These scripts are called pre-request script and you can write them under the Pre-request Script tab.
After you’ve received a response from the request you made.These scripts are called Test scripts and it is this set of scripts that are our focus in this article. You write test scripts under the Tests tab in a Postman request.

The image below shows the Tests tab opened in Postman:

If you look to your right in the already opened request Tests tab, you will notice a list of snippets available to quickly get you started writing tests. Most of the time, these snippets are sufficient for quite a number of test scenarios. So I would select the snippet title Status code: Code is 200. This will generate the code below in the Tests editor:
pm.test(“Status code is 200”, function () {
pm.response.to.have.status(200);
});

Here is also how Postman would look like after clicking on that test snippet:

If you’ve written any form of tests in JavaScript using some of the testing frameworks out there like Jest, then the snippet above will seem familiar. But let me explain: All postman test suits or scenario begins with test() function which is exposed in the pm(short for Postman) global object provided by Postman for you. The test method takes two arguments: the first is the test description which in our test suite above reads: Status code is 200, the second argument is a callback function. It’s in this function you make your assertions or verification of the response on the particular request being tested.
You will notice we have a single assertion right now but you can have as many as you want. However, I like keeping assertions in separate tests most of the time.
Our assertion above simply asks Postman if the response return has a status code of 200. You could see how it reads like English. This is intentional in order to allow anyone to write these tests with ease.
Running Our Test
To run our test we will send a request to the endpoint again. Only this time around, when Postman receives the response from that request, it will run your tests. Below is an image showing the passing test in Postman (You can access test result on the Test Results tab of the response section in postman):

So our test passed! However, it’s crucial that we make our test scenario fail first, and then make it pass; this will help make sure that the scenario you are testing is not affected by any external factor, and that the test passes for the reason you are expecting it to pass — not something else. A good test should be predictable and the end result should be known beforehand.
To make our test pass, I will make a typo in the URL we are currently sending the GET request to. This will lead to a 404 Not Found status code which will make our test fail. Let’s do this. In the address bar currently having the variable of our baseUrl, I will add /a to it (it could be anything random actually). Making the request again and our test will fail like seen below:

Removing the string /a will make the test pass again.
We have written an automated test for the home route of our demo web service. At the moment we have a test case checking the status of the response. Let’s write another test case checking if the response body contains a message property as we have seen in the response and the value is ‘You have reached postman test demo web service’. Add the below code snippet to the test editor:

pm.test(“Contains a message property”, function() {
let jsonData = pm.response.json();
pm.expect(jsonData.message).to.eql(“You have reached postman test demo web service”);
})

Your Postman window should look like this:

In the snippet above, we are creating a test case and getting the JavaScript object equivalent of the response body of the request which is originally in JSON by calling json() on it. Then we use the expect assertion method to check if the message property has a value of “You have reached postman test demo web service.”
4. Repeat!

I believe from the above first iteration of our 4 steps to writing API tests that you’ve seen the flow. So we would be repeating this flow to test all requests in the demo web service. Next up is the signup request. Let’s test on!
Signup Request
The signup request is a POST request expecting the fullName, emailAddress, and password of a user. In postman, you can add these parameters in many ways however we would opt into x-www-form-urlencoded method in the Body tabs of the request section. The image below gives an example of the parameters:

Here is the response with the above request:

{
“message”: “An account has been created for kelvinomereshone@gmail.com successfully”,
“data”: {
“createdAt”: 1596634791698,
“updatedAt”: 1596634791698,
“id”: “9fa2e648-1db5-4ea9-89a1-3be5bc73cb34”,
“emailAddress”: “kelvinomereshone@gmail.com”,
“fullName”: “Kelvin Omereshone”
},
“token”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJrZWx2aW5vbWVyZXNob25lQGdtYWlsLmNvbSIsImlzcyI6Ik15UGFkaSBCYWNrZW5kIiwiaWF0IjoxNTk2NjM0NzkxfQ.otCcXSmhP4mNWAHnrYvvzHkgU8yX8yRE5rcVtmGJ68k”
}

From the above response body, you will notice a token property is returned with the response body. So we would write a test case to assert if a JSON response body was returned and if it contains the property token. Also, we would check for the status code as well which returns 201 Created. So open the Tests tab and add the following snippets:
pm.test(“Status code is 201”, function () {
pm.response.to.have.status(201);
});

pm.test(“Response has a JSON body”, function () {
pm.response.to.be.json;
});

pm.test(“Response has a token property”, function () {
var jsonData = pm.response.json();
pm.expect(jsonData.token).to.be.a(‘string’);
});

What each test case does should be obvious enough from the test description. From top to bottom, we check if the response is a 201 Created status code, we assert also if the response body is JSON and lastly we assert if the token property has a value of type string. Let’s run our tests.
Note: Make sure you change at least the email address of the new user as the Web service won’t allow for duplicate emails.
Our tests should pass and when you check the Test Results tab of the Response section you should get 3 passing tests as shown below:

Let’s move onward to testing the signin endpoint…
Signin Request
The signin request’s response body is similar to the signup request. You could verify that by hitting the endpoint with user credentials – emailAddress and Password – you signed up already. After you have done that, add the following test cases to the tests editor:
pm.test(“Status code is 200”, function () {
pm.response.to.have.status(200);
});

pm.test(“Response has a JSON body”, function () {
pm.response.to.be.json;
});

pm.test(“Response has a token property”, function () {
var jsonData = pm.response.json();
pm.expect(jsonData.token).to.be.a(‘string’);
});

pm.test(“Response has a data property”, function () {
var jsonData = pm.response.json();
pm.expect(jsonData.data).to.be.a(‘object’);
});

Make the request to signin with a valid user credential and your test should pass and Postman should look like so:

Finally, we would be testing the listing/new endpoint of our demo API.
Listing/New Request
This test would be a little different. According to the requirement of our fictitious API, only logged in users can create listings. So we would need a way to authenticate the request.
Recall when signing in a JWT token was returned we can use that token as the authorization header for the create listing request.
To do this in postman, simply copy the token you got from signing in and go over to the Authorization tab of the Request section in Postman and select the type to be Bearer Token from the Type dropdown. You can then paste the token in the box to your right labeled Token. So the new request Authorization tab should look like this:

You can then go on and add the parameters in the Body tab of the request. You will notice the fields name are already there with sample values which you can choose to edit or not. Let’s make a request first before writing our test. A successful response will look like so:
{
“message”: “New listing created successfully”,
“data”: {
“createdAt”: 1596637153470,
“updatedAt”: 1596637153470,
“id”: “41d922ce-7326-43eb-93c8-31658c59e45d”,
“name”: “Glorious Lounge”,
“type”: “Hotel”,
“address”: “No 1. Something street”,
“rent”: “$100k per year”,
“lister”: “9fa2e648-1db5-4ea9-89a1-3be5bc73cb34”
}
}

We can see we get a JSON response body back. We can test for that and also make sure data is not empty. Add the following test case to the Test tab:
pm.test(“Status code is 200”, function () {
pm.response.to.have.status(200);
});

pm.test(“Response has a JSON body”, function () {
pm.response.to.be.json;
});

pm.test(“Response has a message property”, function () {
var jsonData = pm.response.json();
pm.expect(jsonData.message).to.be.a(‘string’);
});

pm.test(“Response has a data property”, function () {
var jsonData = pm.response.json();
pm.expect(jsonData.data).to.be.a(‘object’);
});

With that added, make another request and the tests should all pass as shown below:

Conclusion
This article aims at showing you how to utilize Postman to write automated tests for your APIs which will allow you to bridge the gap between development and quality assurance, and also minimize the surface area of bugs in your API.
Additional Resources

Automated Testing With Postman (Official Postman website)
“Snapshot Testing For APIs Using Postman,” Prashant Agrawal, Medium
“From Manual To Automated Testing: The Roadblocks And The Journey,” Kaustav Das Modak, Medium

Visit source: Post courtesy of : How To Automate API Testing With Postman

Categories
Uncategorized

Building A Component Library With React And Emotion

According to Clearleft, a component library is: “A collection of components, organised in a meaningful manner, and often (but not necessarily) providing some way to browse and preview those components and their associated assets.”— “On Building Component Libraries,” Clearleft We’ll learn how to build a component library by making one that comprises four components: ButtonA…

Want to Read more ? According to Clearleft, a component library is:
“A collection of components, organised in a meaningful manner, and often (but not necessarily) providing some way to browse and preview those components and their associated assets.”— “On Building Component Libraries,” Clearleft

We’ll learn how to build a component library by making one that comprises four components:

ButtonA wrapper around the default HTML button
BoxA container (HTML div) with custom properties
ColumnsA container whose children are spaced evenly across the x-axis
StackA container whose children are spaced evenly across the y-axis

These components could then be used in whatever application we are working on. We’ll build the component library using React and Emotion.
At the end of this piece, you should be able to create a component library that fits whatever use case you have in mind. This knowledge will come handy when you’re working with a team that needs to make use of reusable components.
First, let’s get started by establishing what the Emotion library is. The documentation explains:
“Emotion is a library designed for writing CSS styles with JavaScript. It provides powerful and predictable style composition in addition to a great developer experience with features such as source maps, labels, and testing utilities.”— “Introduction,” Emotion Docs

In essence, Emotion is a CSS-in-JavaScript library, and an interesting thing about CSS-in-JavaScript libraries is that they enable you to collocate components with styles. Being able to tie them up together in a scope ensures that some component styles don’t interfere with others, which is crucial to our component library.
Emotion exposes two APIs for React:

@emotion/core
@emotion/styled

Before we dive into how these APIs work, note that they both support the styling of components with template strings and objects.
The core API is actually like the regular style property we currently use today when building apps with React, with the addition of vendor prefixing, nested selectors, media queries, and more.
Using the object approach with the core API would typically look like this:
import { jsx } from ‘@emotion/core’

let Box = props => {
return (
<div
css={{
backgroundColor: ‘grey’
}}
{…props}
/>
)
}

This is a rather contrived example that shows how we could style a Box component with Emotion. It’s like swapping out the style property for a css property, and then we’re good to go.
Now, let’s see how we could use the template string approach with the same core API:
import { jsx, css } from ‘@emotion/core’

let Box = props => {
return (
<div
css={css`
background-color: grey
`}
{…props}
/>
)
}

All we did was wrap the template string with the css tag function, and Emotion handles the rest.
The styled API, which is built on the core API, takes a slightly different approach to styling components. This API is called with a particular HTML element or React component, and that element is called with an object or a template string that contains the styles for that element.
Let’s see how we could use the object approach with the styled API:
import styled from ‘@emotion/styled’

const Box = styled.div({
backgroundColor: ‘grey’
});

Here is one way to use the styled API, which is an alternative to using the core API. The rendered outputs are the same.
Now, let’s see how we could use the template string approach using the styled API:
import styled from ‘@emotion/styled’

const Box = styled.div`
background-color: grey
`

This achieves the same thing as the object approach, only with a template string this time.
We could use either the core API or the styled API when building components or an application. I prefer the styled approach for a component library for a couple of reasons:

It achieves a lot with few keystrokes.
It takes in an as prop, which helps with dynamically changing the HTML element from the call site. Let’s say we default to a paragraph element, and we need a header element because of semantics; we can pass the header element as a value to the as property.

Getting Started
To get started, let’s clone the setup scripts on GitHub, which we can do on the command line:
git clone git@github.com:smashingmagazine/component-library.git

This command copies the code in that repository to the component-library’s folder. It contains the code required to set up a component library, which includes Rollup to help bundle our library.
We currently have a components folder with an index.js file, which does nothing. We’ll be creating new folders under the components folder for each component we build in our library. Each component’s folder will expose the following files:

Component.jsThis is the component we’re building.
index.jsThis exports the component from Component.js and makes referencing components from a different location easier.
Component.story.jsThis essentially renders our component in its multiple states using Storybook.

It also ships with a utils folder, which defines certain properties that would be used in our components. The folder contains several files:

helpers.jsThis contains helper functions that we are going to be using across our application.
units.jsThis defines spacing and font-size units, which we will use later.
theme.jsThis defines our component library’s palette, shadows, typography, and shape.

Let’s look at what we’ve defined in the units.js file:
export const spacing = {
none: 0,
xxsmall: ‘4px’,
xsmall: ‘8px’,
small: ’12px’,
medium: ’20px’,
gutter: ’24px’,
large: ’32px’,
xlarge: ’48px’,
xxlarge: ’96px’,
};

export const fontSizes = {
xsmall: ‘0.79rem’,
small: ‘0.889rem’,
medium: ‘1rem’,
large: ‘1.125rem’,
xlarge: ‘1.266rem’,
xxlarge: ‘1.424rem’,
};

This defines the spacing and fontSizes rules. The spacing rule was inspired by the Braid design system, which is based on multiples of four. The fontSizes are derived from the major second (1.125) type scale, which is a good scale for product websites. If you’re curious to learn more about type scale, “Exploring Responsive Type Scales” explains the value of knowing the scales appropriate for different websites.
Next, let’s through the theme.js file!

import { spacing } from ‘./units’;

const white = ‘#fff’;
const black = ‘#111’;

const palette = {
common: {
black,
white,
},
primary: {
main: ‘#0070F3’,
light: ‘#146DD6’,
contrastText: white,
},
error: {
main: ‘#A51C30’,
light: ‘#A7333F’,
contrastText: white,
},
grey: {
100: ‘#EAEAEA’,
200: ‘#C9C5C5’,
300: ‘#888’,
400: ‘#666’,
},
};

const shadows = {
0: ‘none’,
1: ‘0px 5px 10px rgba(0, 0, 0, 0.12)’,
2: ‘0px 8px 30px rgba(0, 0, 0, 0.24)’,
};

const typography = {
fontFamily:
“Inter, -apple-system, BlinkMacSystemFont, ‘Segoe UI’, Roboto, Ubuntu, ‘Helvetica Neue’, sans-serif”,
};

const shape = {
borderRadius: spacing[‘xxsmall’],
};

export const theme = {
palette,
shadows,
typography,
shape,
};

In the theme file, we’ve defined our palette, which is essentially the colors we’re going to be using across all components in our library. We also have a shadows object, where we define our box-shadow values. There’s also the typography object, which currently just defines our fontFamily. Finally, shape is used for properties such as border-radius. This theme’s structure is inspired by Material-UI.
Next, our helpers.js file!
export const isObjectEmpty = (obj) => {
return Object.keys(obj).length === 0;
};

Here, we only expose the isObjectEmpty function, which takes in an object and returns true if the object is empty. It returns false if it has any values. We’re going to make use of this function later.
Now that we’ve gone through all of the files in the utils folder, it’s about time to start building our components!
Buttons

Buttons are one of the most used components on the web. They’re used everywhere and can take different forms, shapes, sizes, and more.
Here are the buttons we’re going to build in Figma.

These subtle variations are going to be applied as properties to our button. We would like the buttons in our component library to accept properties such as variant, size, enableElevation (i.e. box-shadow), and color.
Starting with the button component, let’s create a Button folder, where we will define everything related to buttons, as discussed earlier.
Let’s create our button component:
import styled from ‘@emotion/styled’;
import isPropValid from ‘@emotion/is-prop-valid’;

const StyledButton = () => {};

const IGNORED_PROPS = [‘color’];

const buttonConfig = {
shouldForwardProp: (prop) =>
isPropValid(prop) && !IGNORED_PROPS.includes(prop),
};

export const Button = styled(‘button’, buttonConfig)(StyledButton);

Here, we’ve started off by setting up our button component with a buttonConfig. The buttonConfig contains shouldForwardProp, which is used to control the properties that should be forwarded to the DOM, because properties such as color show up on the rendered element by default.
Next, let’s define our button sizes, which we’re going to use in the button component!
const buttonSizeProps = {
small: {
fontSize: fontSizes[‘xsmall’],
padding: `${spacing[‘xsmall’]} ${spacing[‘small’]}`,
},
medium: {
fontSize: fontSizes[‘small’],
padding: `${spacing[‘small’]} ${spacing[‘medium’]}`,
},
large: {
fontSize: fontSizes[‘medium’],
padding: `${spacing[‘medium’]} ${spacing[‘large’]}`,
},
};

buttonSizeProps is a map of our size values (small, medium, and large), and it returns fontSize and padding values based on the sizes. For a small button, we’d need a small font with small padding. The same goes for the medium and large sizes to scale them appropriately.
Next, let’s define a function that provides valid CSS properties based on the passed variant:
const getPropsByVariant = ({ variant, color, theme }) => {

const colorInPalette = theme.palette[color];

const variants = {
outline: colorInPalette
? outlineVariantPropsByPalette
: defaultOutlineVariantProps,
solid: colorInPalette
? solidVariantPropsByPalette
: defaultSolidVariantProps,
};

return variants[variant] || variants.solid;
};

Here, the getPropsByVariant function takes in variant, color, and theme properties and returns the properties of the specified variant; if no variant is specified, it defaults to solid. colorInPalette retrieves the palette assigned to the specified color if found, and undefined if not found in our theme object.
In each variant, we check whether a palette actually exists for the color specified; if we don’t, then we use colors from the common and grey objects of our theme, which we will apply in defaultOutlineVariantProps and defaultSolidVariantProps.
Next, let’s define our variant properties!
const defaultSolidVariantProps = {
main: {
border: `1px solid ${theme.palette.grey[100]}`,
backgroundColor: theme.palette.grey[100],
color: theme.palette.common.black,
},
hover: {
border: `1px solid ${theme.palette.grey[200]}`,
backgroundColor: theme.palette.grey[200],
},
};

const defaultOutlineVariantProps = {
main: {
border: `1px solid ${theme.palette.common.black}`,
backgroundColor: theme.palette.common.white,
color: theme.palette.common.black,
},
hover: {
border: `1px solid ${theme.palette.common.black}`,
backgroundColor: theme.palette.common.white,
color: theme.palette.common.black,
},
};

const solidVariantPropsByPalette = colorInPalette && {
main: {
border: `1px solid ${colorInPalette.main}`,
backgroundColor: colorInPalette.main,
color: colorInPalette.contrastText,
},
hover: {
border: `1px solid ${colorInPalette.light}`,
backgroundColor: colorInPalette.light,
},
};

const outlineVariantPropsByPalette = colorInPalette && {
main: {
border: `1px solid ${colorInPalette.main}`,
backgroundColor: theme.palette.common.white,
color: colorInPalette.main,
},
hover: {
border: `1px solid ${colorInPalette.light}`,
backgroundColor: theme.palette.common.white,
color: colorInPalette.light,
},
};

Here, we define the properties that are going to be applied to our button based on the selected variants. And, as discussed earlier, defaultSolidVariantProps and defaultOutlineVariantProps use colors from our common and grey objects as fallbacks for when the color specified isn’t in our palette or when no color is specified for what we put in place.
By the way, the solidVariantPropsByPalette and outlineVariantPropsByPalette objects use the color from our palette as specified by the button. They both have main and hover properties that differentiate the button’s default and hover styles, respectively.
The button design we’ve used accounts for two variants, which we can check out in our component library design.
Next, let’s create our StyledButton function, which combines all we’ve done so far.

const StyledButton = ({
color,
size,
variant,
enableElevation,
disabled,
theme,
}) => {
if (isObjectEmpty(theme)) {
theme = defaultTheme;
}

const fontSizeBySize = buttonSizeProps[size]?.fontSize;
const paddingBySize = buttonSizeProps[size]?.padding;
const propsByVariant = getPropsByVariant({ variant, theme, color });

return {
fontWeight: 500,
cursor: ‘pointer’,
opacity: disabled && 0.7,
transition: ‘all 0.3s linear’,
padding: buttonSizeProps.medium.padding,
fontSize: buttonSizeProps.medium.fontSize,
borderRadius: theme.shape.borderRadius,
fontFamily: theme.typography.fontFamily,
boxShadow: enableElevation && theme.shadows[1],
…(propsByVariant && propsByVariant.main),
…(paddingBySize && { padding: paddingBySize }),
…(fontSizeBySize && { fontSize: fontSizeBySize }),
‘&:hover’: !disabled && {
boxShadow: enableElevation && theme.shadows[2],
…(propsByVariant && propsByVariant.hover),
},
};
};

In the StyledButton function, we’re assigning defaultTheme to the theme if the theme object is empty which makes it optional for the consumers of our library to use Emotion’s ThemeProvider in order to make use of the library. We assigned fontSize and padding based on the buttonSizeProps object. We defined several default button properties, such as fontWeight and cursor, which aren’t tied to any property, and we also derived color, backgroundColor, and border values based on the result of propsByVariant.
Now that we’ve created our Button component, let’s see how we can use it:
<Button
variant=”solid”
color=”primary”
size=”small”
enableElevation
disabled
>
Small Outline Elevated Button
</Button>

We can check what that looks like on CodeSandbox:

That’s how to use the Button component. We define the following properties:

We define a variant with a solid value. We could have specified outline instead. If the variant prop isn’t provided, we would also default to solid.
We define color, with a value of primary. We also support error as a color value or a color from a theme object. If the color property isn’t specified, we would fall back to our default color state.
We define size, with a value of small. It could be medium (the default) or large.
We define EnableElevation because we want some box-shadow on our button. We could have chosen not to use it.
Finally, we define disabled because we want our button to be disabled. The additional thing we do to a disabled button is reduce its opacity.

The button doesn’t need to take any property. It defaults to a solid medium-sized button.
Box Component

A box component is a container that can hold any component or HTML element. It accepts but is not limited to properties such as padding, margin, display, and width. It can also be used as a base component for some of the other components we’ll get into later.
Here’s what it looks like on Figma:

Before diving into the code, let’s not forget to create a new folder for this component.
Now, let’s create our Box component:

import styled from ‘@emotion/styled’;
import isPropValid from ‘@emotion/is-prop-valid’;
import { spacing, theme as defaultTheme } from ‘../../utils’;

const StyledBox = ({
paddingX,
paddingY,
marginX,
marginY,
width,
display,
theme,
…props
}) => {

if (isObjectEmpty(theme)) {
theme = defaultTheme;
}

const padding = spacing[props.padding];
let paddingTop = spacing[props.paddingTop];
let paddingRight = spacing[props.paddingRight];
let paddingBottom = spacing[props.paddingBottom];
let paddingLeft = spacing[props.paddingLeft];
if (paddingX) {
paddingLeft = spacing[paddingX];
paddingRight = spacing[paddingX];
}
if (paddingY) {
paddingTop = spacing[paddingY];
paddingBottom = spacing[paddingY];
}
let margin = spacing[props.margin];
let marginTop = spacing[props.marginTop];
let marginRight = spacing[props.marginRight];
let marginBottom = spacing[props.marginBottom];
let marginLeft = spacing[props.marginLeft];
if (marginX) {
marginLeft = spacing[marginX];
marginRight = spacing[marginX];
}
if (marginY) {
marginTop = spacing[marginY];
marginBottom = spacing[marginY];
}
return {
padding,
paddingTop,
paddingRight,
paddingBottom,
paddingLeft,
margin,
marginTop,
marginRight,
marginBottom,
marginLeft,
width,
display,
fontFamily: theme.typography.fontFamily,
};
};

const IGNORED_PROPS = [‘display’, ‘width’];

const boxConfig = {
shouldForwardProp: (prop) =>
isPropValid(prop) && !IGNORED_PROPS.includes(prop),
};

export const Box = styled(‘div’, boxConfig)(StyledBox);

The spacing rule we defined earlier is being applied to both padding and margin, as we can see in the Box component. We receive contextual values for padding and margin, and we look up their actual values from the spacing object.
We accept paddingX and paddingY props to update padding across the horizontal and vertical axis, respectively. We do the same for marginX and marginY as well.
Also, we don’t want the display and width props to get forwarded to the DOM because we only need them in CSS. So, we add them to our list of props to ignore, and pass that on to our config.
Here’s how we could use the Box component:
<Box
padding=”small”
paddingTop=”medium”
paddingBottom=”medium”
>
Simple Box Component
</Box>

We can see what this looks like on CodeSandbox.

In this Box component, we’ve assigned small as a value to our padding property, and medium to the paddingTop and paddingBottom properties. When rendered, the Box component will have its padding-left and padding-right properties set to 12px each, and its padding-top and padding-bottom properties set to 20px. We could have replaced paddingTop and paddingBottom with paddingY and gotten the same result.
Columns Component

The Columns component is a variation of our Box component, with a display type of flex and with children spaced evenly across the x-axis.
Here is a representation of the Columns component in Figma:

Let’s build our Columns component!

import React from ‘react’;
import { Box } from ‘../Box’;

export const Columns = ({ children, space, …props }) => {
return (
<Box display=”flex” {…props}>
{React.Children.map(children, (child, index) => {
if (child.type !== Box) {
console.warn(
‘Each child in a Columns component should be a Box component’
);
}

if (index > 0) {
return React.cloneElement(child, {
marginLeft: space,
width: ‘100%’,
});
}

return React.cloneElement(child, { width: ‘100%’ });
})}
</Box>
);
};

We’re using React.Children to map over the Columns component’s children. And we’re adding marginLeft and width properties to each of the children, except the first child, which doesn’t need a marginLeft property because it’s the leftmost child in the column. We expect each child to be a Box element to ensure that the necessary styles are applied to it.
Here’s how we could use the Columns component:
<Columns space=”small”>
<Box> Item 1</Box>
<Box> Item 2</Box>
<Box> Item 3</Box>
</Columns>

We can see what that looks like on CodeSandbox.

The Columns children here are spaced evenly across the x-axis by 12 pixels because that’s what the value of small resolves to, as we’ve defined earlier. Because the Columns component is literally a Box component, it can take in other Box component properties, and we can customize it as much as we want.
Stack Component

This is also a variation of our Box component that takes the full width of the parent element and whose children are spaced evenly across the y-axis.
Here is a representation of the Stack component in Figma:

Let’s build our Stack component:
import React from ‘react’;
import { Box } from ‘../Box’;
import { Columns } from ‘../Columns’;

const StackChildrenTypes = [Box, Columns];
const UnsupportedChildTypeWarning =
‘Each child in a Stack component should be one of the types: Box, Columns’;

export const Stack = ({ children, space, …props }) => {
return (
<Box {…props}>
{React.Children.map(children, (child, index) => {
if (!StackChildrenTypes.includes(child.type)) {
console.warn(UnsupportedChildTypeWarning);
}

if (index > 0) {
return React.cloneElement(child, { marginTop: space });
}

return child;
})}
</Box>
);
};

Here, we map over each child with React.Children and apply a paddingTop property to it with the value of the space argument. As for the first child, we need it to take its original position, so we skip adding a marginTop property to it. We also accept each child to be a Box so that we can apply the necessary properties to it.
Here’s how we could use the Stack component:
<Stack space=”small”>
<Box marginTop=”medium”> Item 1</Box>
<Box> Item 2</Box>
<Box> Item 3</Box>
</Stack>

We can see what that looks like on CodeSandbox.

Here, the Box elements are spaced evenly with the small unit, and the first Box takes a separate marginTop property. This shows that you can customize components however you wish.
Conclusion
We’ve gone through the basics of using Emotion to create components in React using the APIs that it provides. This is just one of many ways to go about building a component library. There are some nuances to building it for a brand because you might not have to take theming and some other things into consideration. But if you plan to release the library to the public one day, then you’ll have to deal with requests for those missing pieces, so consider that possibility and make the library a little flexible ahead of time.
If you have any questions, feel free to drop them as comments.
The repository for this article is on GitHub, and the button designs we’ve used are on Figma.
References

“On Building Component Libraries”, Mark Perkins, Clearleft
“Exploring Responsive Type Scales”, Joseph Mueller
“Design Systems With React and Storybook”, Emma Bostian, Frontend Masters
Emotion official documentation

Visit source: Post courtesy of : Building A Component Library With React And Emotion

Categories
Uncategorized

4 Ways To Creatively Use Icons In Your Mobile Apps

There’s nothing novel about using icons within mobile apps. From the home screen icon to the navigation menu, they’re pretty much a standard part of the apps that designers build. They come with big benefits too: Minimized distractions, More attractive UIs, Empowerment of users to easily engage with the app, Elimination of language barriers, Improvement…

Want to Read more ? There’s nothing novel about using icons within mobile apps. From the home screen icon to the navigation menu, they’re pretty much a standard part of the apps that designers build.
They come with big benefits too:

Minimized distractions,
More attractive UIs,
Empowerment of users to easily engage with the app,
Elimination of language barriers,
Improvement of brand recognizability.

But are we using icons as best as we can or are there ways to improve the mobile UX even further with iconography? Today, I want to look at a number of ways you can creatively add icons or icon-like elements to your apps and bring more life (and engagement) to them in the process.
Making The Most Out Of Icons
Icons are super useful design elements for mobile interfaces. While we do have to be careful with icons (like making sure navigational icons are always paired with text as well as not using so many that the interface becomes like a puzzle to be solved), there are some additional use cases I want you to consider:
1. Show Hints Of Branded Icons Throughout The App
Users will first get a glimpse of an app’s branded logo icon from the app store. Once installed, this icon will become a persistent presence on the user’s smart device, which will foster greater awareness of the app.
What I’ve noticed with many apps, though, is that the brand icon doesn’t often appear past that point. In some cases, it makes total sense. An app isn’t like a website that needs that steady logo anchor so users can always quickly get “Home”. But…
I can’t help but feel like small branded elements throughout could add a unique touch to the experience. They wouldn’t detract from the experience. Instead, they’d show up in bite-sized chunks that add something extra to the experience.
One example I really like is the CheapOair app. This is the logo that appears when a user first opens it. It’s the same one that appears at the top of the corresponding website:

Now, if you were to look at the app store page for CheapOair or how it appears on a user’s home screen, you’d see that the full logo isn’t used. Instead, users see the luggage-shaped “O” icon:

It’s unique. It’s memorable. And it works well in tiny spaces, like as the desktop favicon or on smaller mobile screens.
Now, for an app like CheapOair that aggregates travel listings from different airlines, hotels, car rental agencies and so on, it’s only natural to expect some lag time as users move through the app. And while the designers could’ve used a more traditional loading icon (like the spinning wheel or progress bar), it uses its branded icon instead:

The stamps are in the shape of a moon. It’s not officially part of Hotels.com’s branding, but it’s a very recognizable icon for its rewards members.
Because of this recognizability, its placement within hotel search results pages is helpful as it allows users to quickly scroll through and see which hotels they can earn another stamp with:

There are many different factors that users consider when booking a hotel room, including price, distance, average user rating and so on. But rather than bog down the main listing with this extra detail that’s only relevant to rewards members, the use of the icon and its placement in the bottom-left corner of the image for eligible hotels is a good choice.
So, even if you don’t feel like using the actual brand logo within the app (or find no reason to), this example proves that there are other ways to use brand-adjacent iconography to improve the experience.
2. Use Icons To Encourage More Gestures And Actions
One of the keys to retaining more app users is to give them a reason to regularly engage with it. And if your users can’t remember which gestures to use when they’re inside the app or they find the act of interacting with it to be boring, that may be enough reason for them to go looking for apps that do a better job of capturing their attention.
Even if your users don’t have any problem with how the engaging elements are presented to them, what happens if someone they know suggests an app that they like better? And they see how much more they like the presentation of different elements?
Either way, you don’t want to give them a reason to lose interest or look for greener pastures. And I think that icons added to gestures and clickable targets can help with this.
This, for instance, is the Boomerang for Gmail app:

I needed a way to “pause” my Gmail inbox during the workday (to prevent distractions) as well as in my off hours (to keep myself from working). While there are a number of distraction-blocking tools available, I loved the simplicity and elegance of this one. I especially appreciated this sorting gesture.
There’s no need to open the message and use the options bar to select the right option. When messages appear in my inbox, it takes no more than a second to swipe left and take action because of how clearly labeled they are. And because I use this app every day, my finger automatically knows which icon to flick the message to: archive, mark as read, Boomerang (for another day/time), move or delete.
Again, if you can make engaging with an app go more smoothly — which, in this case, I attribute to the complex gesture simplified by recognizable icons — you’ll find users are more likely to use it.
Your app doesn’t need to have swiping gestures in order to play around with engaging icon design. Duolingo, for example, has brought its language modules to life thanks to these animated icons:

Have you ever read something online that was so good (or maybe even so bad) that you had to know who wrote it? For the most part, online publications just put a byline at the top and a short bio under the post. BuzzFeed, however, gives its author more than just name recognition. It pairs their byline with an iconized headshot.
This is a great touch. It tells readers from the get-go that they have real writers behind this piece and lets them connect to the writer on a more personal level.
It’s also just too easy for this detail to get lost on a page because of the title, subtitle, read-minutes and other metadata that publications put at the top. I’d say in terms of making an article more attractive and welcoming, even this small of an icon helps set the stage for an enjoyable reading experience.
Food service apps could probably benefit from this as well. Only, in this case, it would be food items and products that become iconized. Like what the SONIC Drive-in app does:

There was a study done by Durham University on the connection between images and satisfaction with a food order. The study looked at a number of variables, but this one is particularly relevant to what we’re looking at in the SONIC app:
“Our research revealed that if a restaurant wants to make use of imagery and visual prompts on their menu, this needs to be combined with commonly used and ‘accurate’ food names to increase marketing power. While it may seem a basic approach, photos can act as a positive reinforcement for customers who have made a visual connection that reflects the name of that dish.”

This is exactly what SONIC does in the above example. Rather than show one of their cups filled with the soft drink or show no photo at all, it displays the brand logos as icons beside each.
These brands are so deeply ingrained in the consumer consciousness that it will make the ordering process go much easier. It should also lead to greater satisfaction overall as there’s no surprise about what they’re getting.
Then, there’s the use case for marketplaces, like Rakuten:

This ebates app helps users make money off of their online purchases.
Now imagine if this app were just a text-only list of deals. Sure, it would still be usable and useful… but users would likely resort to the search bar to find deals as opposed to actually reading through what’s available. And if your users can only find what they want through search, there’s something wrong — especially if you’re presenting them with the hottest offers or products of the day.
I looked around and couldn’t find any ecommerce marketplace that does something like this — pairing a product or deal with a brand icon — which I find surprising. While I realize users can sort through listings by brand name, wouldn’t an iconized brand logo help users more easily locate items they want to buy from search results?
I guess the big argument against this would be for marketplaces pushing their own products (like Amazon does). By displaying a brand icon either in search results or on a product’s page, it might deter users from buying the item if it’s from a lesser-known and unrecognizable brand.
For concepts like Rakuten, however, it totally works and I’d urge you to use it when you can.
Wrapping Up
As you can tell by these examples, you’re not going to completely revamp the look and feel of your mobile app with icons. Instead, by adding very subtle touches here and there — that users are bound to take notice of — you’ll impress them with your attention to detail while making the overall experience more enjoyable. This, in turn, can lead to greater levels of engagement and higher rates of user retention.
Further Reading on SmashingMag:

Responsive Web And Desktop Development With Flutter
Visual Design Language: The Building Blocks Of Design
How To Design Mobile Apps For One-Hand Usage
5 Things To Stop Doing In Mobile App Design

Visit source: Post courtesy of : 4 Ways To Creatively Use Icons In Your Mobile Apps