Archive

Archive for June, 2020

How Web Designers Can Help Restaurants Move Into Digital Experiences

June 23rd, 2020 No comments
A blurred-out website to demonstrate how independent restaurants still have unresponsive designs

How Web Designers Can Help Restaurants Move Into Digital Experiences

How Web Designers Can Help Restaurants Move Into Digital Experiences

Suzanne Scacca

2020-06-23T12:00:00+00:00
2020-06-23T14:38:23+00:00

As much as I’ve always loved the experience of going out to eat and ordering in takeout, it’s very rare that I enjoy visiting a restaurant’s website. But I get it. The restaurant industry tends to run on very slim profit margins, so it’s hard to justify spending money on a professionally designed website when all they want it to do is list their hours of operation and menu.

However, I envision all that changing in 2020 (and beyond) as restaurants are forced to expand into digital in order to survive. Unlike a website that a novice might hack together with a cheap site builder, establishing a competitive digital presence isn’t something they’re going to be able to do on their own.

That’s why web designers should seriously start thinking about expanding into this niche.

How Web Designers Can Help Restaurants Move into Digital

Usually, when something serious shakes up the restaurant industry, those that want to survive will adopt newer and better technologies to adapt. So, it’s not like restaurants are strangers to digital transformation. Until now, though, the focus has mainly been on investing in technology that improves how they work in-house.

With everything that’s happened in 2020, though, restaurants are going to need web designers’ help in doing three things that ensure their survival in an increasingly digital world:

1. Modernize The Restaurant Website

Whenever I write one of these posts, I spend time reviewing a few dozen websites to find the best examples to make my point. I’m not going to lie, this one was tough. While I knew I could turn to national chain restaurants to find modern-looking websites, I had a really hard time with others.

While it’s not impossible to find an independent restaurant operator or local chain that has a great-looking website in 2020, I’d say that at least half of them are way behind the times, if they even have a website at all.

Remember when websites were designed like this?

A blurred-out website to demonstrate how independent restaurants still have unresponsive designs

An outdated restaurant website in 2020, blurred out to protect its identity. (Source: Anonymous) (Large preview)

I’ve blurred out the restaurant’s name and details to protect its identity, but you can still get a sense of how bad this design is for 2020.

Restaurant websites can’t afford to be crappy, non-responsive placeholders anymore. They need to become impressive digital presences that set the stage for what customers will experience when interacting with restaurants as diners.

Let’s take a look at how In-N-Out Burger has nailed modern web design. The first thing you’ll notice is it’s a responsive design. On desktop, the website fits the full width of the screen, so there’s no wasted space around the border. It looks good on a mobile device, too:

In-N-Out Burger website on mobile

The In-N-Out Burger mobile website is responsive and easy to read. (Source: In-N-Out Burger) (Large preview)

Also, take notice of the images. This is a burger joint, so you should expect the website to be full of burger photos, which it is. However, there’s something interesting to note about the burgers you find on the site.

In-N-Out Burger website photos and transitions

The In-N-Out Burger website uses perfectly framed images and well-chosen transitions. (Source: In-N-Out Burger) (Large preview)

When someone enters a page where there’s a burger photo, the food slides into the frame as if someone were sliding it over to a customer in the restaurant. It’s a neat little transition and many visitors to the site might not even realize what’s happening, but it makes the experience feel more lifelike and interactive.

Transitions aren’t the only things you can do to create this sort of experience. Background videos taken within the establishment work just as well as it gives customers the opportunity to walk through the establishment instead of relying on static images that only paint part of the picture.

Another thing restaurant websites need to improve is how they’re organized.

When people are ready to go out to eat or to dine in, don’t waste their time trying to force the restaurant’s history down their throats (which many of these sites surprisingly do). The navigation as well as the order in which CTAs appear on the home page should reflect the actions customers want to take.

The thought process most likely goes like this:

  1. “I’m not sure what to order. Where’s the menu?” (Menu)
  2. “Do I need to make a reservation or can we just go whenever?” (Reservations)
  3. “Where is this place again?” (Locations or Contact)

Or, these days, #2 looks more like this:

  • “Do they do takeout? I wonder if they’ll deliver it.” (Order Online)

There are other things customers might want to do on the website. Like buy gift cards or merchandise, sign up for rewards or apply for a job.

So, while the above tasks should be a priority in terms of what visitors see first, make sure to look at the site’s data to see what else they’re interested in doing. Then, make sure those popular actions take center stage in the navigation and site design.

2. Empower Them to Diversify Their Income

Under normal circumstances, profitability is a problem for many restaurants. Add a crisis to the mix and it’s going to become downright impossible to generate any profit — that is if they rely solely on dine-in business.

Long before COVID-19, consumers were already showing a growing preference for digital dining solutions.

According to Peapod, 77% of U.S. consumers said they preferred eating at home than going out. But that doesn’t necessarily translate to ordering in from a restaurant.

  • 27% preferred to order groceries online and pick them up from the store.
  • 26% planned to use grocery delivery.
  • 20% were interested in meal kits.

Then, you have information from Technomic and the National Restaurant Association that found that about 60% of all restaurant sales in the U.S. come from off-premise dining.

For restaurants that haven’t yet made the leap to digital dining options, they’re going to have to ASAP. This isn’t just a temporary thing either.


Restaurants that fail to digitize going forward won’t survive.

So, web designers are going to be needed to help them build out the following:

  • An online ordering system for their website or a link to an external service,
  • A reservation system (for when in-house dining is available).

That’s just the bare minimum though. For instance, this is what Snooze Eatery has done:

Snooze Eatery online delivery or pickup

Snooze Eatery advertises delivery or pickup on its website. (Source: Snooze Eatery) (Large preview)

The first thing visitors see on the website is the online ordering option. When they click “Place Your Order”, they’re taken to the restaurant’s proprietary ordering portal:

Snooze Eatery online ordering portal

Snooze Eatery’s online ordering portal. (Source: Snooze Eatery) (Large preview)

This in and of itself is a great solution for restaurants to have available through their websites as it allows them to control the ordering process and capture more of the profits (but that’s up to your clients to decide, of course). That said, many restaurants are getting creative and going beyond traditional online ordering options.

Below the fold on the Snooze Eatery site, visitors will find this banner:

Snooze Eatery neighborhood provisions: family-style meal kits and food essentials

Snooze Eatery now offers neighborhood provisions. (Source: Snooze Eatery) (Large preview)

As I mentioned earlier, there’s a good number of people who want to be able to order food online but then prepare it for themselves at home. While that would previously have left restaurants high and dry, that’s not the case anymore as many restaurants are expanding their offering to include family-style meal kits and groceries like Snooze.

This alone means that web designers are going to become increasingly more important for restaurants. And don’t expect the work to end there. Restaurants will also need your help building other monetized offerings into their websites. For instance:

  • Gift cards;
  • Merchandise;
  • Subscription services for meal kits, alcohol deliveries and more;
  • Online memberships for cooking classes, premium recipes, etc.

If they don’t have one yet, they’ll also probably need help creating a rewards and account management system as well.

3. Fix Their Brand Images on Third-party Sites

Although the website should be the engine that powers everything for the business online, restaurants need other sites to help with visibility, too. For example:

  • Facebook to share photos, advertise location information and collect customer reviews;
  • Instagram to share photos, restaurant updates and customer-generated content;
  • Yelp and TripAdvisor to collect customer reviews and feedback;
  • Google My Business to create a local presence in Google search and Maps as well as to collect reviews;
  • Delivery services like DoorDash to outsource delivery to;
  • Reservation sites like OpenTable to outsource reservation bookings to.

If customers are looking for restaurants online, they need to be willing and able to meet them where they are… before eventually bringing them to the website.

Although it’s ultimately the restaurant’s responsibility to create these pages, you should provide assistance when it comes to the visual branding piece. For one, it ensures that there’s some consistency between all their platforms. Also, it enables you to fill in missing pieces that restaurateurs might not think about.

Let’s take a look at Rhode Island staple, IGGY’S:

IGGY'S website with picture of clamcakes and 3 options for online ordering

IGGY’S website visitors are introduced to the restaurant with an image of its iconic clamcakes. (Source: IGGY’S) (Large preview)

The waterfront eatery immediately gets down to business and provides visitors with 3 options for ordering online (based on which location they want to go to).

Here’s what the online ordering portal looks like:

IGGY'S online ordering portal

IGGY’S restaurant’s online ordering portal. (Source: IGGY’S) (Large preview)

Notice how good this looks. It takes what would otherwise be a text-only menu and turns it into something much more attractive and, arguably, more effective in driving up sales.

Now, contrast that with IGGY’S online ordering through DoorDash:

DoorDash online ordering for IGGY's

DoorDash customers can order online from IGGY’s restaurant. (Source: DoorDash) (Large preview)

The items on this page rarely come with descriptions or images.

Now, IGGY’S is a well-known restaurant around Rhode Island, so this might not be a dealbreaker for online customers. However, new customers might approach the menu with more trepidation than the one available through the IGGY’S website since it’s devoid of details.

This is where your visual-centric approach comes in handy. By making sure each item comes with a high-resolution and mouth-watering photo (the same as the one used on the site), you can optimize this sales opportunity for them.

It’s also important to ensure the brand elements are consistently presented. That way, if an existing customer runs across their favorite restaurant on DoorDash, they won’t hesitate to order because they’ll instantly know it’s their favorite restaurant.

For example, the logo on DoorDash is nothing like the one on the website in terms of quality or looks:

DoorDash logo and location information for IGGY'S RI

The DoorDash logo for IGGY’S doesn’t match the one on the website. (Source: DoorDash) (Large preview)

Be it the logo or another branded element, you want to make sure that 1) it matches the website and 2) looks good. This goes for online ordering sites like DoorDash as well as all the other ones I mentioned earlier.

Wrapping Up

We’re at a point now where restaurants can no longer be reluctant or stingy about improving their digital presence. And, as a web designer, this should get you excited.

There’s a lot you can do to help businesses in this space beyond designing basic websites. Because so much of their digital transformation involves making sales online, you’ll get to design experiences that are intuitive, modern, and mouth-watering while also creating new monetized pathways for them.

(ra, yk, il)

Categories: Others Tags:

8 Ways To Promote Your Business Without A Marketing Budget

June 23rd, 2020 No comments

If you want to run a successful business, you need to invest time and resources in marketing. A good marketing strategy would help you get your products or services in front of your target audience, increase sales, and reach your business goals.

However, traditional forms of marketing like television, billboard advertisements, radio, and newspapers can be very expensive. This might not be an issue if you are a huge enterprise with an entire marketing department with millions of dollars budgeted for marketing. But what happens if you are a small business with little or no marketing budget? How can you effectively market your product or service without breaking the bank? Does this mean that you have to pause all your marketing efforts until you can raise money?

In this article, we would see 8 ways you can promote your business without a marketing budget.

1. Start A Blog

Running a business blog is a free marketing tactic to help your business become more visible online and also reach a much larger audience. Research has shown that companies with blogs have an average of 67% more leads monthly than companies that do not blog.

To increase sales for your business, you would need leads. You can quickly get these leads by placing a ton of paid ads to drive new prospects to your business. But this method is quite expensive and the leads stop coming in after you have run out of cash.

So, how can you get new leads without spending money? In two words: blogging and search engines.

Every time you write a new blog post, it is one more indexed page on your website, which means it’s one more opportunity for you to show up on search engines and drive more visitors to your website. Your intended customers are using search engines like Google to search for businesses they would work with. The more blog content you publish on your website, the higher your chances of these customers locating you.

The moment traffic starts coming into your site from search engines, you have the opportunity to convert these traffic into leads. Every new blog post you write is an avenue to generate new leads.

All you need to do is to add a call-to-action button to every blog post. This call to action is basically any content asset that would be valuable enough to visitors of your blog that they would be willing to exchange their information. If you sell software, you can offer a free demo as a content asset. If 10 visitors sign up for your free demo and 2 of them eventually sign up for a paid version, that is two new customers and you didn’t spend even a dime on ads.

2. Create Marketing Videos

If you aren’t using videos as part of your marketing strategy, then you’re missing out on a ton of opportunities to promote your business. The popularity of video as a content marketing format has grown in the past few years. In fact, a report from HubSpot research showed that 50% of customers want to see more videos from brands than any other form of content.

The best part about the video is that it can be used by any business regardless of size, team, or budget. Gone are the days where you need an expensive 4k camera before you can make high-quality marketing videos. All you need is a quality smartphone and you can start making videos immediately. In fact, most customers would prefer low-quality videos that feel “authentic” than high-quality videos that feel “inauthentic”.

Before you start filming your video, you need to decide on the kind of video you want to make. They are several marketing video types you can implement into your strategy. Here is a short explanation of some of them:

  1. Demo videos: A demo video is used to showcase to the customer how your product works. It can be a video of the unboxing of a physical product or a tour on how your software works.
  2. Brand videos: Brand videos are used to create awareness for your business and attract customers. You typically showcase your brand’s vision, mission, products, or services in this video type.
  3. Event videos: Do you have a conference or product launch coming soon? You can use an event video to create awareness for the event. It can be in the form of a highlight reel that shows the attendees what they would gain from attending the event.
  4. Instructional videos: These videos are great for teaching your audience. They can be in the form of educational or how-to videos that show your audience how to use your business solutions better.
  5. Testimonial videos: Customers want to know that a product or service they are about to invest in would solve their specific problem. The best way to show them that your product is valuable is by creating customer testimonial videos where your loyal customers describe how your company helped them solve the challenges they were facing.
  6. Live videos: You can use live videos to show your customers a special behind the scenes view of your company. Almost all social media platforms now offer live video capabilities so you can directly connect with customers on their favorite social media channels.

3. Post on Quora

Quora is a very powerful platform that can help you reach a wider brand audience. It is one of the most effective marketing channels you can use in promoting your business or service.

The platform receives more than 300 million visitors monthly. So if you are looking to increase brand awareness, confirm your authority in your niche, and develop your thought leadership presence, you should check out Quora.

What is Quora?

Quora is an international question-and-answer website where questions are asked, answered, followed, and edited by Internet users, either factually or in the form of opinions.

Why do you need a Quora marketing strategy?

Here are some reasons you should be interested in marketing on Quora:

  • The platform has over 300 million monthly visitors so it is a great channel for increasing your business reach. It is also one of the best user-generated content (UGC) platforms in the world.
  • Improved search visibility: Your content on Quora is also searchable via Google. What this means is that you can also drive traffic and leads to the site through Google even if the content was written on Quora.
  • Several high profile writers use the platform to reach their audience. Even former President Obama answers questions on Quora. You can use Quora to build your reputation as a thought leader in your industry.
  • Quora also offers insights into your audience. You can use the platform to answer the questions your customers have concerning your brand and also offer up solutions to difficulties they encounter when using your product; making it ideal for customer service management.

How to get the most out of Quora marketing:

1. Create a brilliant bio: Regardless of the social media channel, a brilliant bio is essential. What makes Quora unique is that you cannot create profiles for a brand unless in special cases. You would have to create a profile for the individual in your organization that would be answering the questions.

Make sure that you fill out the interest, “About Me”, employment and credential sections of your bio. A complete bio would help people find you faster on Quora. Don’t forget to add an eye-catching profile picture to your bio. Your bio should give off the vibe that there is a real person behind the account; customers would connect with you faster that way.

2. Look for questions that fit your industry/business to answer: The point of Quora is to attract customers to your business. You need to answer questions that you know your target audience is searching for. A good way to do this is by answering questions on a problem that your product/services solve.

3. Find question threads with the highest upvotes: Quora uses the upvote point system to show the most popular questions and answers on the platform. Question threads with tons of upvotes usually have a lot of views. If you offer good answers to these questions, you can have thousands of views fast.

4. Run a Giveaway Contest

Running a giveaway is one of the best ways to promote your business without a marketing budget. It is a quick way to create brand awareness and also connect with your customers.

When done correctly, it would cost you close to nothing. This is especially true when you use social media to run the giveaway contest.

The first step to every giveaway contest is determining the kind of promotion you want to run. There are three main types of promotions you can run:

  • Contests
  • Sweepstakes
  • Lottery

Contests

In a contest, the participants would be required to have a skill or make some kind of effort before they can win the prize. The winners are chosen either through voting or by judges.

Some of the most popular contests are video, photo, or essays.

A good example is this Facebook contest by Eggo held in two parts. The first part is a recipe contest where participants submitted their best recipe for waffles. The second part is fans voting for their favorite recipe. The winner receives $5000.

Note: You don’t have to offer money as your prize. You can give the winner a 10% discount off the price of a product you are selling. If you run an ecommerce business you can offer coupons or free shipping as the prize.

Sweepstakes

In sweepstakes, winners are chosen randomly. It requires no skill or any effort on the part of the customer. The winners are selected by chance.

Pro Tip: Of the two, regular contests are the most effective in promoting your business. When customers know that their efforts are what increases their chances of winning, they become more engaged. The more people that participate in the contest, the wider your brand’s reach.

5. Start An Affiliate Program

63% of businesses say that their biggest challenge is generating leads and traffic. One method of generating leads to your business is affiliate marketing.

Affiliate marketing involves an affiliate signing up to an affiliate program set up by the advertiser to sell and promote their product on a commission-based model. The affiliate would promote the advertiser’s product or service using a unique link, which sends traffic to the advertiser’s website. If the lead sent to the website purchases a product, a commission is paid to the affiliate.

In the context of this article, you would be the one creating an affiliate program that affiliates can sign up for. Starting an affiliate program can be thought of as a way of expanding your marketing team by hiring people who are paid only after successful sales are made.

The best part of an affiliate program is that you are not losing any money. You only pay the affiliate a commission after they have made a successful sale.

Setting up an affiliate program is also very easy. They are several sales tools you can use in launching and scaling your affiliate program in a couple of hours. But, before you go ahead and launch your affiliate program, make sure you carry out research. Analyze what your competitors are doing before starting out.

Understanding the competitive environment informs your decisions on how you will launch the program as well as your commissions, commercial arrangements, and targets.

6. Submit Press Releases

Press releases can be an effective form of marketing, especially for small businesses. If used correctly, press releases are an efficient way to promote your brand and create goodwill in the local marketplace without paying a dime.

For example, when Green Rivers Adventures was about to launch The Gorge, a high-speed zip line, they issued a press release announcing the launch and a number of publications including The Associated Press and Costco Connection, which reached up to 8 million people picked up the story. As a result of this huge press, the company had a sold-out year before its official launch.

You should note that there are right and wrong ways to create and distribute press releases.

Unless you are a well-known brand like Apple, nobody cares about your company or product. Your press releases should not be in the form of a pitch. Journalists or the media are not interested in promoting you or your business so that you can just sell your products (unless you are paying them to do so).

A strong press release would involve sharing expert advice or opinions on a topic relevant to the journalist and their readers. This is some things you can put in your press release:

  • An interesting solution to a popular consumer problem
  • Offer a controversial opinion on a popular topic
  • Bring attention to your business when you receive an award. This works best for local press releases.
  • Piggyback off the news by offering an opinion or information relative to the topic at hand.

You can use online press release services like PRWeb, Business Wire, and PR Newswire to get started.

7. Setup G2 Crowd & Capterra

Setting up G2 Crowd is free and very easy to do. You can set up a profile for your business in minutes and have the opportunity to be seen by millions.

G2 is a peer-to-peer review site headquartered in Chicago, Illinois. It was launched in May 2012 with a focus on aggregating user reviews for business software. The platform compares the best business software and services based on user ratings and social data.

Your future customers are researching their next purchase on G2. So if you sell software, you can reach more customers by claiming your G2 profile.

Capterra is similar to G2 Crowd. It is an online marketplace vendor serving as an intermediary between buyers and sellers within the software industry. The company assists consumers with selecting the best software for their needs.

Both of these services are available internationally so you can reach a very wide audience by setting up your profile. To increase your ratings, ask your users to add a review of your product on G2 Crowd/Capterra.

8. Start a Podcast or Get Featured In One

Podcasts are a great way to promote your product and services. There is a huge number of people listening to podcasts daily. In fact, the proportion of Americans listening to podcasts has increased in the past few years. According to musicoomph, 22% of Americans (approximately 103 million) listen to podcasts, weekly people.

You should take advantage of this trend and start your own podcast show. The best part is that there are a lot of quality free podcast hosting services that you can use to get started. All you need is great content and a good microphone and you are good to go.

The key to running a successful podcast is creating engaging content that delivers value to your listeners. When done well, a podcast can be very beneficial to your brand. For example, given the audio nature of podcasts, listeners tend to hang on to every word, making it excellent for advertisers trying to make their brand known.

Just like with your business blog, create podcasts that are niche based and targeted to a specific audience. When you create content that resonates with your audience, you would receive a high level of engagement.

Another way to boost your podcast is by interviewing other experts. This would bring variety to your show and you also get exposed to their audience that may not have known about your podcasts.

If you don’t want the workload of starting your own podcast, you can get featured in other podcasts in your industry. Reach out to other podcasts hosts and offer to be interviewed in their show. You can use targeted email outreach to connect with these hosts. When you eventually get invited, be sure to deliver immense value to their audience.

Conclusion

It is very possible to market your products or services and create brand awareness without spending a lot of money. With the strategies mentioned in this article, you can promote your business without a marketing budget.

With a little commitment and creativity on your part, you can start generating tons of leads fast.

Which of the tips in this article would you start using first? Leave your thoughts in the comment section.


Technology vector created by freepik – www.freepik.com

Categories: Others Tags:

An Overview of Scroll Technologies

June 22nd, 2020 No comments

Scroll-related animations have been used on the web for years. In recent years, they’ve started to become more common, perhaps in part due to devices being higher-performing and thus able to handle more animation.

There are a number of scroll related technologies out there, so this article’s aim is to provide an overview of them and tools to help choose the one that’s right for you. I’d argue that these technologies can be broken down into two broad categories: ones for specific scroll-related behaviors and ones for more generic scroll-related behaviors.

Technologies for specific scroll-related behaviors

There are a few simple native CSS scroll effects that are supported by modern browsers. In some limited use cases they can be sufficient for your scroll animation needs.

position: sticky;

If all you need is for an element to stay in the same place on scroll for a portion of the page, using position: sticky is a good option. It’s straightforward and built into modern browsers. That said, a polyfill is required for IE support and some mobile browsers. For a solid overview, check out this article by Preethi.

CodePen Embed Fallback

CSS parallax

This isn’t a technology as much as a technique, but it’s pretty handy for simple parallax effects where you want different pieces of the page to move at different speeds on scroll. There’s a good write up of the technique on Alligator.io and a bunch of examples on CodePen, like this Firewatch header. The biggest downside for me is that it’s difficult to understand what values to use to set the perspective and transforms in order to get the parallax effect exactly right.

CodePen Embed Fallback

CSS scroll snap points

Scroll snap points allow the browser to snap to particular scroll positions that you set after a user is done with their normal scrolling. This can be helpful for keeping certain elements in view. However, the API is still in flux so be careful to use the most up to date API and be careful about relying on it in production. This CSS-Tricks article by Max Kohler is a good place to learn about it right now.

Smooth scrolling

Smooth scrolling is supported natively when jumping from section to section within a page using window.scrollTo() in JavaScript or even the scroll-behavior property in CSS. Generic smooth scrolling that smooths out mouse wheel actions is not supported natively in all browsers at this time. There are various JavaScript libraries that attempt to add smooth scroll support for the mousewheel action, but I’ve yet to find one that is bug-free and plays nicely with all other scroll technologies. Plus, smooth scrolling isn’t always good in the first place.

Technologies for generic scroll behaviors

Currently, there is no way to create or fire generic animations based on the scroll position using just CSS (though there is a proposal that could support some form of generic scroll based animations in CSS in the distant future) or to scrub through part of an animation. As such, if you want to animate elements on scroll, you’ll need to use at least some JavaScript to create the effect you want. There are two broad methods of using JavaScript to fire animations on scroll: using intersection observers and using the scroll event.

IntersectionObserver

Intersection observers are great if all you need for your animation is information related to whether or not and how much of an element is visible in the viewport. This makes them a good option for reveal animations. Even then, some things are difficult (though not impossible) using intersection observers, such as firing different animations depending on the direction an element enters the viewport. Intersection observers also aren’t very helpful if you want to do any scroll animations when an element is in between and not overlapping with the start and end points.

Using the scroll event

Using the scroll event will give you the most freedom in controlling animations on scroll. It allows you to affect an element on scroll no matter where it is in terms of the viewport and set up starting and ending points exactly as you need for your project.

With that being said, it can also be intense on performance if it isn’t throttled correctly and doesn’t have a convenient API to create particular behaviors. This is why it’s oftentimes helpful to use a good scrolling library that can handle the throttling for you and give you a more handy API to work with. Some can even handle a lot of the resizing issues for you!

Tools to create generic scroll behaviors

There are a few holistic scrolling libraries that attempt to give you full control over animations on scroll without you having to perform all of the calculations yourself.

ScrollMagic

ScrollMagic provides a relatively simple API to create various effects on scroll and can be hooked into different animation libraries like GSAP and Velocity.js. However, it has become less maintained over the past few years, which lead to the creation of ScrollScene.

ScrollScene

ScrollScene is essentially a wrapper to try and make ScrollMagic and/or the intersection observer more usable. It uses a custom, more maintained version of ScrollMagic and adds additional features like video playback, scene init breakpoints, and scene duration breakpoints. It also makes use of GSAP.

ScrollTrigger

ScrollTrigger is an official GreenSock plugin for GSAP. It a long list of features as the most easy to use API of any scroll library (at least to me). Using it, you can have complete control to define where your scroll animations start and end, animate anything (WebGL, canvas, SVG, DOM, whatever) on scroll, pin elements in place while the animation is running, and more. Plus it has the support of GreenSock and the GreenSock forums.

Notable mention: Locomotive Scroll

While it doesn’t attempt to be as comprehensive of a scrolling library as the other libraries mentioned above, Locomotive Scroll is focused on providing custom smooth scrolling. You can also animate certain properties of DOM objects by adding data attributes or hook into the onscroll event to animate other types of objects.

In summary

For some particular scroll animation effects, like sticky positioning and parallax, CSS technologies may be sufficient, at least when using a polyfill for browsers that don’t support those properties.

I generally recommend using GSAP’s ScrollTrigger because it can do everything that CSS properties can do, plus much more. ScrollTrigger will handle the browser support and calculations so that you can focus on animating!

Here’s a table covering which tools you can use to create particular effects:

position: sticky CSS parallax CSS scroll snap points Smooth Scrolling Intersection observers ScrollMagic ScrollScene Locomotive Scroll ScrollTrigger
Pinning ? ? ? ? ? ? ? ?? ?
Parallax effects ? ? ? ? ? ? ? ? ?
Scrubbing through animation with easing ? ?? ? ? ?? ?? ?? ?? ?
Snaps scroll position ? ? ? ? ?? ?? ?? ?? ?
Dynamic Batching / Staggering ? ? ? ? ? ? ? ? ?
Supports horizontal scroll effects ? ? ? ? ? ? ? ? ?

Here’s a table comparing various other aspects of scroll technology:

position: sticky CSS parallax CSS scroll snap points Smooth scrolling Intersection observers ScrollMagic ScrollScene Locomotive Scroll ScrollTrigger
Usable in production (good browser support) ?? ? ?? ?? ?? ? ? ?? ?
Complete freedom in animation ? ? ? ? ? ? ? ?? ?
Maintained n/a n/a n/a n/a n/a ? ? ? ?
Works with DOM, Canvas, WebGl, SVG ? ? ? ? ? ? ? ?? ?
Works easily with resizing ? ? ? ? ? ?? ? ? ?
Restricts animation to relevant section ? ? ? ? ? ?? ?? ? ?
Directionally aware ? ? ? ? ?? ? ? ?? ?
Native technology ? ? ? ? ? ? ? ? ?
? = Yes
?? = Partial support
? = No

The post An Overview of Scroll Technologies appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Rough Notation

June 22nd, 2020 No comments

This is a neat little library. It uses SVG to insert hand-drawn looking annotations to elements (probably text), like underlines and box highlights (there are 6 design options, all configurable). Super clever.

Here’s a little demo:

CodePen Embed Fallback

Aside from it just being cool, I really like how it was released. You can use it from npm. It’s ready to be used via ES6 imports. You can just use it as a . Then, if you happen to be using a JavaScript framework, there are wrappers for React, Vue, Svelte, Angular, and Web Components. Nice.

Not all projects take that approach. Here’s another very cool project: gooey-react. It takes the gooey effect concept and essentially gives it an API via React/JSX.

Again, this is very cool and clever and I love it — but imagine another approach instead, perhaps an HTML wrapper with data-* attributes to control the effect. With that, wrappers could be (easily?) made in any JavaScript framework.

Direct Link to ArticlePermalink

The post Rough Notation appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Using Custom Property “Stacks” to Tame the Cascade

June 22nd, 2020 No comments

Since the inception of CSS in 1994, the cascade and inheritance have defined how we design on the web. Both are powerful features but, as authors, we’ve had very little control over how they interact. Selector specificity and source order provide some minimal “layering” control, without a lot of nuance — and inheritance requires an unbroken lineage. Now, CSS Custom Properties allow us to manage and control both cascade and inheritance in new ways.

I want to show you how I’ve used Custom Property “stacks” to solve some of the common issues people face in the cascade: from scoped component styles, to more explicit layering of intents.

A quick intro to Custom Properties

The same way browsers have defined new properties using a vendor prefix like -webkit- or -moz-, we can define our own Custom Properties with an “empty” -- prefix. Like variables in Sass or JavaScript, we can use them to name, store, and retrieve values — but like other properties in CSS, they cascade and inherit with the DOM.

/* Define a custom property */
html {
  --brand-color: rebeccapurple;
}

In order to access those captured values, we use the var() function. It has two parts: first the name of our custom property, and then a fallback in case that property is undefined:

button {
  /* use the --brand-color if available, or fall back to deeppink */
  background: var(--brand-color, deeppink);
}

This is not a support fallback for old browsers. If a browser doesn’t understand custom properties, it will ignore the entire var() declaration. Instead, this is a built-in way of handling undefined variables, similar to a font stack defining fallback font families when one is unavailable. If we don’t provide a fallback, the default is unset.

Building variable “stacks”

This ability to define a fallback is similar to “font stacks” used on the font-family property. If the first family is unavailable, the second will be used, and so on. The var() function only accepts a single fallback, but we can nest var() functions to create custom-property fallback “stacks” of any size:

button {
  /* try Consolas, then Menlo, then Monaco, and finally monospace */
  font-family: Consolas, Menlo, Monaco, monospace;

  /* try --state, then --button-color, then --brand-color, and finally deeppink */
  background: var(--state, var(--button-color, var(--brand-color, deeppink)));
}

If that nested syntax for stacked properties looks bulky, you can use a pre-processor like Sass to make it more compact.

CodePen Embed Fallback

That single-fallback limitation is required to support fallbacks with a comma inside them — like font stacks or layered background images:

html {
  /* The fallback value is "Helvetica, Arial, sans-serif" */
  font-family: var(--my-font, Helvetica, Arial, sans-serif);
}

Defining “scope”

CSS selectors allow us to drill down into the HTML DOM tree, and style elements anywhere on the page, or elements in a particular nested context.

/* all links */
a { color: slateblue; }

/* only links inside a section */
section a { color: rebeccapurple; }

/* only links inside an article */
article a { color: deeppink; }

That’s useful, but it doesn’t capture the reality of “modular” object-oriented or component-driven styles. We might have multiple articles and asides, nested in various configurations. We need a way to clarify which context, or scope, should take precedence when they overlap.

Proximity scopes

Let’s say we have a .light theme and a .dark theme. We can use those classes on the root element to define a page-wide default, but we can also apply them to specific components, nested in various ways:

CodePen Embed Fallback

Each time we apply one of our color-mode classes, the background and color properties are reset, then inherited by nested headings and paragraphs. In our main context, colors inherit from the .light class, while the nested heading and paragraph inherit from the .dark class. Inheritance is based on direct lineage, so the nearest ancestor with a defined value will take precedence. We call that proximity.

Proximity matters for inheritance, but it has no impact on selectors, which rely on specificity. That becomes a problem if we want to style something inside the dark or light containers.

Here I’ve attempted to define both light and dark button variants. Light mode buttons should be rebeccapurple with white text so they stand out, and dark mode buttons should be plum with black text. We’re selecting the buttons directly based on a light and dark context, but it doesn’t work:

CodePen Embed Fallback

Some of the buttons are in both contexts, with both .light and .dark ancestors. What we want in that case is for the closest theme to take over (inheritance proximity behavior), but what we get instead is the second selector overriding the first (cascade behavior). Since the two selectors have the same specificity, source order determines the winner.

Custom Properties and proximity

What we need here is a way to inherit these properties from the theme, but only apply them to specific children. Custom Properties make that possible! We can define values on the light and dark containers, while only using their inherited values on nested elements, like our buttons.

We’ll start by setting up the buttons to use custom properties, with a fallback “default” value, in case those properties are undefined:

button {
  background: var(--btn-color, rebeccapurple);
  color: var(--btn-contrast, white);
}

Now we can set those values based on context, and they will scope to the appropriate ancestor based on proximity and inheritance:

.dark {
  --btn-color: plum;
  --btn-contrast: black;
}

.light {
  --btn-color: rebeccapurple;
  --btn-contrast: white;
}

As an added bonus, we’re using less code overall, and one unified button definition:

CodePen Embed Fallback

I think of this as creating an API of available parameters for the button component. Sara Soueidan and Lea Verou have both covered this well in recent articles.

Component ownership

Sometimes proximity isn’t enough to define scope. When JavaScript frameworks generate “scoped styles” they are establishing specific object-element ownership. A “tab layout” component owns the tabs themselves, but not the content behind each tab. This is also what the BEM convention attempts to capture in complex .block__element class names.

Nicole Sullivan coined the term “donut scope” to talk about this problem back in 2011. While I’m sure she has more recent thoughts on the issue, the fundamental problem hasn’t changed. Selectors and specificity are great for describing how we build detailed styles over top of broad patterns, but they don’t convey a clear sense of ownership.

We can use custom property stacks to help solve this problem. We’ll start by creating “global” properties on the element that are for our default colors:

html {
  --background--global: white;
  --color--global: black;
  --btn-color--global: rebeccapurple;
  --btn-contrast--global: white;
}

That default global theme is now available anywhere we want to refer to it. We’ll do that with a data-theme attribute that applies our foreground and background colors. We want the global values to provide a default fallback, but we also want the option to override with a specific theme. That’s where “stacks” come in:

[data-theme] {
  /* If there's no component value, use the global value */
  background: var(--background--component, var(--background--global));
  color: var(--color--component, var(--color--global));
}

Now we can define an inverted component by setting the *--component properties as a reverse of the global properties:

[data-theme='invert'] {
  --background--component: var(--color--global);
  --color--component: var(--background--global);
}

But we don’t want those settings to inherit beyond the donut of ownership, so we reset those values to initial (undefined) on every theme. We’ll want to do this at a lower specificity, or earlier in the source order, so it provides a default that each theme can override:

[data-theme] {
  --background--component: initial;
  --color--component: initial;
}

The initial keyword has a special meaning when used on custom properties, reverting them to a Guaranteed-Invalid state. That means rather than being passed along to set background: initial or color: initial, the custom property becomes undefined, and we fallback to the next value in our stack, the global settings.

We can do the same thing with our buttons, and then make sure to apply data-theme to each component. If no specific theme is given, each component will default to the global theme:

CodePen Embed Fallback

Defining “origins”

The CSS cascade is a series of filtering layers used to determine what value should take precedence when multiple values are defined on the same property. We most often interact with the specificity layers, or the final layering based on source-order — but the first layer of cascade is the “origin” of a style. The origin describes where a style came from — often the browser (defaults), the user (preferences), or the author (that’s us).

By default, author styles override user preferences, which override browser defaults. That changes when anyone applies `!important` to a style, and the origins reverse: browser `!important` styles have the highest origin, then important user preferences, then our author important styles, above all the normal layers. There are a few additional origins, but we won’t go into them here.

When we create custom property “stacks,” we’re building a very similar behavior. If we wanted to represent existing origins as a stack of custom properties, it would look something like this:

.origins-as-custom-properties {
  color: var(--browser-important, var(--user-important, var(--author-important, var(--author, var(--user, var(--browser))))));
}

Those layers already exist, so there’s no reason to recreate them. But we’re doing something very similar when we layer our “global” and “component” styles above — creating a “component” origin layer that overrides our “global” layer. That same approach can be used to solve various layering issues in CSS, which can’t always be described by specificity:

  • Override » Component » Theme » Default
  • Theme » Design system or framework
  • State » Type » Default

Let’s look at some buttons again. We’ll need a default button style, a disabled state, and various button “types,” like danger, primary and secondary. We wan’t the disabled state to always override the type variations, but selectors don’t capture that distinction:

CodePen Embed Fallback

But we can define a stack that provides both “type” and “state” layers in the order that we want them prioritized:

button {
  background: var(--btn-state, var(--btn-type, var(--btn-default)));
}

Now when we set both variables, the state will always take precedence:

CodePen Embed Fallback

I’ve used this technique to create a Cascading Colors framework that allows custom theming based on layering:

  • Pre-defined theme attributes in the HTML
  • User color preferences
  • Light and dark modes
  • Global theme defaults

Mix and match

These approaches can be taken to an extreme, but most day-to-day use-cases can be handled with two or three values in a stack, often using a combination of the techniques above:

  • A variable stack to define the layers
  • Inheritance to set them based on proximity and scope
  • Careful application of the `initial` value to remove nested elements from a scope

We’ve been using these custom property “stacks” on our projects at OddBird. We’re still discovering as we go, but they’ve already been helpful in solving problems that were difficult using only selectors and specificity. With custom properties, we don’t have to fight the cascade or inheritance. We can capture and leverage them, as-intended, with more control over how they should apply in each instance. To me, that’s a big win for CSS — especially when developing style frameworks, tools, and systems.

The post Using Custom Property “Stacks” to Tame the Cascade appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

An Introduction To SWR: React Hooks For Remote Data Fetching

June 22nd, 2020 No comments
fetching

An Introduction To SWR: React Hooks For Remote Data Fetching

An Introduction To SWR: React Hooks For Remote Data Fetching

Ibrahima Ndaw

2020-06-22T12:00:00+00:00
2020-06-23T14:38:23+00:00

SWR is a lightweight library created by Vercel (formerly ZEIT) that allows fetching, caching, or refetching data in realtime using React Hooks. It’s built with React Suspense which lets your components “wait” for something before they can render, including data. SWR ships also with great features such as dependent fetching, focus on revalidation, scroll position recovery, and so on. It’s also a very powerful tool since it’s backend agnostic and has good support for TypeScript. It’s a package that has a bright future.

Why should you care? You should care if you’ve been looking for a library that does not only fetch data from APIs but also make it possible to do things like caching and dependent fetching. What will be covered in this tutorial will come in handy when building React applications with a lot of moving parts. It’s expected that you should have made use of Axios and the Fetch API, even though we’ll compare how they differ from SWR, we won’t be going into details on how they’ll be implemented.

In this guide, I will introduce you to React Hooks for Remote Data Fetching by building a Pokedex app that requests data from the Pokemon API. We will also dive into other features that come with SWR as well, and highlight its differences compared to popular solutions such as the Fetch API and the Axios library and give you the reasons why using this library and why you should keep an eye on SWR.

So, let’s start by answering a fundamental question: What is SWR?

What Is SWR?

SWR is an initialism of stale-while-revalidate. It’s a React Hooks library for remote data fetching. SWR works with three main steps: first, it returns the data from the cache (the stale part), then sends the fetch request (the revalidate part), and finally comes with the up-to-date data. But no worries, SWR handles all these steps for us. The only thing we have to do is give the useSWR hook the needed parameters to make the request.

SWR has also some nice features such as:

  • Back-end agnostic
  • Fast page navigation
  • Revalidation on focus
  • Interval polling
  • Request deduplication
  • Local mutation
  • Pagination
  • TypeScript ready
  • SSR support
  • Suspense mode
  • React Native support
  • Lightweight.

Sounds magical? Well, SWR simplifies things and increases for sure the user experience of your React app. And once we start implementing it in our project, you will see why this hook is handy.

It’s important to know that the name of the package is swr or SWR and the hook used to get SWR features is named useSWR.

In theory, the SWR is maybe what you need to enhance your data fetching. However, we already have two great ways of making HTTP requests in our app: the Fetch API and the Axios library.

So, why using a new library to retrieve data? let’s try answering this legit question in the next section.

Comparison With Fetch And Axios

We already have many ways to make HTTP requests in our React Apps, and two of the most popular is the Fetch API and the Axios library. They are both great and allows us to fetch or send data easily. However, once the operation is done, they will not help us to cache or paginate data, you have to do it on our own.

Axios or Fetch will just handle the request and return the expected response, nothing more.

And compared to SWR, it’s a bit different because the SWR under the hood uses the Fetch API to request data from the server — it’s kind of a layer built on top of it. However, it has some nice features such as caching, pagination, scroll position recovery, dependent fetching, etc, and to be precise a certain level of reactivity out of the box that Axios or Fetch do not have. It’s a big advantage because having such features help to make our React Apps fast and user-friendly and reduce markedly the size of our code.

And to conclude, just keep in mind that SWR is not the same as Axios or Fetch even if it helps to deal with HTTP requests. SWR is more advanced than them, it provides some enhancements to keep our app synchronized with the back-end and hence increases the performance of our app.

Now we know what’s differences SWR has compared to the Axios library or the Fetch API, it’s time to dive into why using such a tool.

Recommended reading: Consuming REST APIs In React With Fetch And Axios

Why Using SWR For Data Fetching?

As I said earlier SWR ships with some handy features that help to increase the usability of your app easily. With SWR, you can paginate your data in no-time using useSWRPages, you can also fetch data that depends on another request or recover a scroll position when you get back to a given page, and so much more.

Usually, we show to the user a loading message or a spinner while fetching data from the server. And with SWR, you can make it better by showing to the user the cached or stale data while retrieving new data from the API. And once that operation is done, it will revalidate the data to show the new version. And you don’t need to do anything, SWR will cache the data the first time you fetch it and retrieve it automatically when a new request is made.

So far, we already see why using SWR over Axios or Fetch is better depending obviously on what you are aiming to build. But for many cases, I will recommend using SWR because it has great features that go beyond just fetching and returning data.

That said, we can now start building our React app and use the SWR library to fetch remote data.

So, let’s start by setting up a new project.

Setting Up

As I said earlier in the introduction, we will build an app that fetches data from the Pokemon API. You can use a different API if you want too, I will stick with it for now.

And to create a new app, we need to run the following command on the terminal:

npx create-react-app react-swr

Next, we need to install the SWR library by first navigating to the folder that holds the React app.

cd react-swr

And run on the terminal the following command to install the SWR package.

yarn add swr

Or if you’re using npm:

npm install swr

Now we have all set up done, let’s structure the project as follow to start using SWR:

src
├── components
|  └── Pokemon.js
├── App.js
├── App.test.js
├── index.js
├── serviceWorker.js
├── setupTests.js
├── package.json
├── README.md
├── yarn-error.log
└── yarn.lock

As you can see, the folder structure is simple. The only thing to notice is the components folder that holds the Pokemon.js file. It will be used later as a presentational component to show a single Pokemon once we get data from the API.

Great! With that in place, we can now start fetching data from the API using useSWR.

Fetching Remote Data

The SWR package has some handy features as we have seen above. However, there are two ways of configuring this library: either locally or globally.

A local setup means that every time we create a new file, we have to setup SWR again to be able to fetch remote data. And a global setup allows us to reuse a part of our configuration within different files because a fetcher function can be declared once and used everywhere.

And no worries, we will see both in this article, but for now, let’s get hands dirty and add some meaningful code in the App.js file.

Displaying The Data

import React from 'react'
import useSWR from 'swr'
import { Pokemon } from './components/Pokemon'

const url = 'https://pokeapi.co/api/v2/pokemon'

const fetcher = (...args) => fetch(...args).then((res) => res.json())

function App() {
    const { data: result, error } = useSWR(url, fetcher)

    if (error) return <h1>Something went wrong!</h1>
    if (!result) return <h1>Loading...</h1>

    return (
        <main className='App'>
            <h1>Pokedex</h1>
            <div>
                {result.results.map((pokemon) => (
                    <Pokemon key={pokemon.name} pokemon={pokemon} />
                ))}
            </div>
        </main>
    )
}
export default App

As you can see, we start by importing useSWR from the SWR library. This declares the URL of the API you want to get data from, and a function to fetch these data.

The function fetcher is used here to transform the data into JSON. It receives the data fetched as an argument and returns something.

Notice that here, I use the Rest operator ((...args)) since I’m not sure of the type and length of data received as a parameter, therefore, I copy everything before passing it again as an argument to the fetch method provided by useSWR which transforms the data into JSON and returns it.

That said, the fetcher and the url of the API can be now passed as parameters to the useSWR hook. With that, it can now make the request and it returns two states: the data fetched and an error state. And data: result is the same as data.result, we use object destructuring to pull result from data.

With the returned values, we can now check if the data is successfully fetched and then loop through it. And for each user, use the Pokemon component to display it.

Now we have the data and pass it down to the Pokemon Component, it’s time to update Pokemon.js to be able to receive and display the data.

Creating The Pokemon Component

import React from 'react'
import useSWR from 'swr'

const fetcher = (...args) => fetch(...args).then((res) => res.json())

export const Pokemon = ({ pokemon }) => {
    const { name } = pokemon
    const url = 'https://pokeapi.co/api/v2/pokemon/' + name

    const { data, error } = useSWR(url, fetcher)

    if (error) return <h1>Something went wrong!</h1>
    if (!data) return <h1>Loading...</h1>

    return (
        <div className='Card'>
            <span className='Card--id'>#{data.id}</span>
            <img
                className='Card--image'
                src={data.sprites.front_default}
                alt={name}
            />
            <h1 className='Card--name'>{name}</h1>
            <span className='Card--details'>
                {data.types.map((poke) => poke.type.name).join(', ')}
            </span>
        </div>
    )
}

Here, we have a component that receives a single Pokemon data from the API and displays it. However, the data received does not contain all fields needed, hence we have to make another request to the API to get the complete Pokemon object.

And as you can see, we use the same process to retrieve the data even if this time we append the name of the Pokemon to the URL.

By the way, if you are not familiar with destructuring, ({ pokemon }) is the same as receiving props and accessing to the pokemon object with props.pokemon. It’s just a shorthand to pull out values from objects or arrays.

With that in place, if you navigate to the root folder of the project and run on the terminal the following command:

yarn start

Or if you’re using npm:

npm start

You should see that the data are successfully fetched from the Pokemon API and displayed as expected.

fetching

Fetching illustration. (Large preview)

Great! We are now able to fetch remote data with SWR. However, this setup is a local one and can be a bit redundant because you can already see that App.js and Pokemon.js use the same fetcher function to do the same thing.

But luckily, the package comes with a handy provider named SWRConfig that helps to configure SWR globally. It’s a wrapper component that allows child components to use the global configuration and therefore the fetcher function.

To setup SWR globally, we need to update the index.js file because it’s where the App component is rendered using React DOM. If you want, you can use SWRConfig directly in the App.js file.

Configuring SWR Globally

import React from 'react'
import ReactDOM from 'react-dom'
import { SWRConfig } from 'swr'
import App from './App'
import './index.css'

const fetcher = (...args) => fetch(...args).then((res) => res.json())

ReactDOM.render(
    <React.StrictMode>
        <SWRConfig value={{ fetcher }}>
            <App />
        </SWRConfig>
    </React.StrictMode>,
    document.getElementById('root')
)

As you can see, we start by importing SWRConfig which is a provider that needs to wrap the higher component or just part of your React app that needs to use SWR features. It takes as props a value that expects an object of config. You can pass more than one property to the config object, here I just need the function to fetch data.

Now, instead of declaring the fetcher function in every file, we create it here and pass it as value to SWRConfig. With that, we can now retrieve data at any level in our app without creating another function and hence avoid redundancy.

Besides that, fetcher is equal to fetcher: fetcher, it’s just syntactic sugar proposed by ES6. With that change, we need now to update our components to use the global config.

Using The Global SWR Config

import React from 'react'
import useSWR from 'swr'
import { Pokemon } from './components/Pokemon'

const url = 'https://pokeapi.co/api/v2/pokemon'

function App() {
    const { data: result, error } = useSWR(url)

    if (error) return <h1>Something went wrong!</h1>
    if (!result) return <h1>Loading...</h1>

    return (
        <main className='App'>
            <h1>Pokedex</h1>
            <div>
                {result.results.map((pokemon) => (
                    <Pokemon key={pokemon.name} pokemon={pokemon} />
                ))}
            </div>
        </main>
    )
}
export default App

Now we only need to pass the url to useSWR, instead of passing the url and fetcher method. Let’s also tweak the Pokemon component a bit.

import React from 'react'
import useSWR from 'swr'

export const Pokemon = ({ pokemon }) => {
    const { name } = pokemon
    const url = 'https://pokeapi.co/api/v2/pokemon/' + name

    const { data, error } = useSWR(url)

    if (error) return <h1>Something went wrong!</h1>
    if (!data) return <h1>Loading...</h1>

    return (
        <div className='Card'>
            <span className='Card--id'>#{data.id}</span>
            <img
                className='Card--image'
                src={data.sprites.front_default}
                alt={name}
            />
            <h1 className='Card--name'>{name}</h1>
            <span className='Card--details'>
                {data.types.map((poke) => poke.type.name).join(', ')}
            </span>
        </div>
    )
}

You can already see that we have no fetcher function anymore, thanks to the global configuration which passes the function to useSWR under the hood.

Now, you can use the global fetcher function everywhere in your app. The only thing that the useSWR hook needs to fetch remote data is the URL.

However, we can still enhance the setup furthermore by creating a custom hook to avoid declaring the URL again and again, and instead, just pass as parameter the path.

Advanced Setup By Creating A Custom Hook

To do so, you have to create a new file in the root of the project named useRequest.js (you can name it whatever you want) and add this code block below to it.

import useSwr from 'swr'

const baseUrl = 'https://pokeapi.co/api/v2'

export const useRequest = (path, name) => {
    if (!path) {
        throw new Error('Path is required')
    }

    const url = name ? baseUrl + path + '/' + name : baseUrl + path
    const { data, error } = useSwr(url)

    return { data, error }
}

Here, we have a function that receives a path and optionally a name and appends it to the base URL to build the complete URL. Next, it checks if a name parameter is received or not and handle it consequently.

Then, that URL is passed as a parameter to the useSWR hook to be able to fetch the remote data and return it. And if no path is passed, it throws an error.

Great! we need now to tweak the components a bit to use our custom hook.

import React from 'react'
import { useRequest } from './useRequest'
import './styles.css'
import { Pokemon } from './components/Pokemon'

function App() {
    const { data: result, error } = useRequest('/pokemon')

    if (error) return <h1>Something went wrong!</h1>
    if (!result) return <h1>Loading...</h1>

    return (
        <main className='App'>
            <h1>Pokedex</h1>
            <div>
                {result.results.map((pokemon) => (
                    <Pokemon key={pokemon.name} pokemon={pokemon} />
                ))}
            </div>
        </main>
    )
}
export default App

Now, instead of using the SWR hook, we use the custom hook built on top of it and then pass as expected the path as an argument. With that in place, everything will work like before but with a much cleaner and flexible configuration.

Let’s also update the Pokemon component.

import React from 'react'
import { useRequest } from '../useRequest'

export const Pokemon = ({ pokemon }) => {
    const { name } = pokemon
    const { data, error } = useRequest('/pokemon', name)

    if (error) return <h1>Something went wrong!</h1>
    if (!data) return <h1>Loading...</h1>

    return (
        <div className='Card'>
            <span className='Card--id'>#{data.id}</span>
            <img
                className='Card--image'
                src={data.sprites.front_default}
                alt={name}
            />
            <h1 className='Card--name'>{name}</h1>
            <span className='Card--details'>
                {data.types.map((poke) => poke.type.name).join(', ')}
            </span>
        </div>
    )
}

You can already see how our custom hook makes things easier and more flexible. Here, we just need to pass additionally the name of the Pokemon to fetch to useRequest and it handles everything for us.

I hope you start enjoying this cool library — However, we still have things to discover because SWR offers so many features, and one of them is useSWRPages which is a hook to paginate data easily. So, let’s use that hook in the project.

Paginate Our Data With useSWRPages

SWR allows us to paginate data easily and request only a part of it, and when needed refetch data to show for the next page.

Now, let’s create a new file in the root of the project usePagination.js and use it as a custom hook for pagination.

import React from 'react'
import useSWR, { useSWRPages } from 'swr'
import { Pokemon } from './components/Pokemon'

export const usePagination = (path) => {
    const { pages, isLoadingMore, loadMore, isReachingEnd } = useSWRPages(
        'pokemon-page',
        ({ offset, withSWR }) => {
            const url = offset || `https://pokeapi.co/api/v2${path}`
            const { data: result, error } = withSWR(useSWR(url))

            if (error) return <h1>Something went wrong!</h1>
            if (!result) return <h1>Loading...</h1>

            return result.results.map((pokemon) => (
                <Pokemon key={pokemon.name} pokemon={pokemon} />
            ))
        },
        (SWR) => SWR.data.next,
        []
    )

    return { pages, isLoadingMore, loadMore, isReachingEnd }
}

As you can see, here we start by importing useSWRPages which is the helper that allows paginating data easily. It receives 4 arguments: the key of the request pokemon-page which is also used for caching, a function to fetch the data that returns a component if the data are successfully retrieved, and another function that takes the SWR object and request data from the next page, and an array of dependencies.

And once the data fetched, the function useSWRPages returns several values, but here we need 4 of them: the pages that is the component returned with the data, the function isLoadingMore which checks if the data are currently fetched, the function loadMore that helps fetching more data, and the method isReachingEnd which determines whether there is still data to retrieve or not.

Now we have the custom hook that returns the needed values to paginate data, we can now move to the App.js file and tweak it a bit.

import React from 'react'
import { usePagination } from './usePagination'
import './styles.css'

export default function App() {
    const { pages, isLoadingMore, loadMore, isReachingEnd } = usePagination(
        '/pokemon'
    )

    return (
        <main className='App'>
            <h1>Pokedex</h1>
            <div>{pages}</div>
            <button
                onClick={loadMore}
                disabled={isLoadingMore || isReachingEnd}
            >
                Load more...
            </button>
        </main>
    )
}

Once the usePagination hook imported, we can now pass the path as a parameter and get back the returned values. And since pages is a component, we don’t need to loop through the data or anything like that.

Next, we use the function loadMore on the button to fetch more data and disable it if the retrieving operation is not finished or if there is no data to fetch.

Great! with that change, we can now browse on the root of the project and start the server with this command to preview our app.

yarn start

Or if you’re using npm:

npm start

You should see that the data are successfully fetched and if you click on the button, new data will be retrieved by SWR.

Pagination. (Large preview)

So far, we have seen in practice the SWR library, and I hope you are finding value on it. However, it still has some features to offer. Let’s dive into these functionalities in the next section.

Other Features Of SWR

The SWR library has a bunch of handy things that simplifies the way we build React apps.

Focus Revalidation

It’s a feature that allows updating or revalidating to be precise the data when you re-focus a page or switch between tabs. And by default, this functionality is enabled, but you can disable it anyway if it does not fit your need. It can be useful especially if you have data with high-level-frequency updates.

Refetch on Interval

The SWR library allows refetching data after a certain amount of time. It can be handy when your data changes at high speed or you need to make a new request to get a piece of new information from your database.

Local Mutation

With SWR, you can set a temporary local state that will update automatically when new data are fetched(revalidation). This feature comes in play particularly when you deal with an Offline-first approach, it helps to update data easily.

Scroll Position Recovery

This feature is very handy, especially when it comes to dealing with huge lists. It allows you to recover the scroll position after getting back to the page. And in any case, it increases the usability of your app.

Dependent Fetching

SWR allows you to fetch data that depends on other data. That means it can fetch data A, and once that operation is done, it uses it to fetch data B while avoiding waterfalls. And this feature helps when you have relational data.

That said, SWR helps to increase the user experience in any matter. It has more features than that, and for many cases it’s better to use it over the Fetch API or the Axios library.

Conclusion

Throughout this article, we have seen why SWR is an awesome library. It allows remote data fetching using React Hooks and helps to simplify some advanced features out of the box such as pagination, caching data, refetching on interval, scroll position recovery, and so on. SWR is also backend agnostic which means it can fetch data from any kind of APIs or databases. In definitive, SWR increases a lot the user experience of your React apps, it has a bright future and you should keep an eye on it or better use it in your next React app.

You can preview the finished project live here.

Thanks for reading!

Next Steps

You can go on to check the following links which will give you a better understanding beyond the scope of this tutorial.

Further Reading on SmashingMag:

(ks, ra, yk, il)

Categories: Others Tags:

Understanding and Addressing Stress during Remote Working

June 22nd, 2020 No comments
remote work stress

There is something different about this pandemic infused remote working stint all across the globe. For starters, everyone is working from home, and most importantly people are being forced to work at home/remotely due to the prevailing circumstances.

While remote working seems to be a great idea(and it is!), a mass and forced remote working stint is bound to take a toll on many professionals. Add into the mixture the ingredient of the pay cut and you have got the perfect recipe for stress during remote working.

Let’s look at some ways of understanding stress during remote working and what we can do to deal with them.

Socially Remote

This is one of the biggest drawbacks of remote working and often the biggest player in increasing stress in employees. According to a survey conducted by, Buffer, Loneliness was the biggest struggle in remote working.

The lack of social interaction often takes a toll on the mental health of employees and this deteriorates both their standard of living and professional performance. The biggest problem with the employer, in this case, is that since the affected person is working remotely, it is difficult to identify such problems let alone find some sort of solution for it.

What can employers do?

To deal with a mental health issue is always a tricky issue for employers. But there are a few steps they can follow to make sure things don’t go out of control.

  • Proper and regular communication with your employees is the key. Most employees don’t tend to speak up about mental frustrations and social exclusion to their employers. You need to break the ice here and make sure that there are open conversations in your organization.
  • Organize frequent and periodic meetings for all employees in your organization. This makes sure that employees working permanently remotely have a chance to interact with their colleagues. This also helps in creating a great bond between your employees.

Burnout

Wait, isn’t remote work supposed to be the antidote to burnout? In most cases it is but sometimes things tend to go a bit haywire.

From our experiences, we have identified two ways in which remote employees can face burnout.

Firstly, since employees aren’t on-site, they feel the need to show their commitment to the organization. This leads to employees going overboard and working longer and harder than other employees.

Secondly, since employees are working from home, their managers and employers tend to overload them with work well beyond the working hours. Since employees never “leave” their working stations, it is not uncommon for them to receive after office hours work.

What can employers do?

  • The biggest step employers can take is respecting the routine and work hours. The culture of not giving tasks and work after office hours should be practiced in your organization. This makes a great case for your employer brand as well.
  • Employers should make sure that they acknowledge the efforts of their remote employees. This boosts the confidence of the remote workers and acknowledges the fact that their work is being held in high regard and doesn’t have to jeopardize their mental health to deliver great output.

Lack of Resources

It doesn’t come off as a big surprise that remote workers often face problems in their day to day activities due to lack of resources.

This lack of resources can range anywhere from lack of a proper system to the proper access of a document. This often leads to employees not being able to meet their deadlines. This further leads to an increase in frustration and stress. They also end up feeling neglected and invaluable to the organization. This slowly, but surely, takes a toll on the mental health of the employees.

What can employers do?

Employers can make sure proper communication between various departments happens seamlessly with the remote employees. They should also prepare a checklist of the proper system requirements of the employees and bridge the gaps.

Overall, a channel for proper and effective communication can act as a great way to resolve various gaps in the allocation of resources.

Improper Onboarding

Onboarding is a real headache for every human resource department. Add into the mix a remote and online onboarding process, the difficulty goes to a whole new level. This finally leads to an improper onboarding experience for the new remote employee.

This becomes really stressful and frustrating, especially for people without experience. Employees end up not getting a clear understanding of the work process and various other nuances related to their job. It also becomes difficult to reach other team members. This leads to a really stressed out a few months.

What can employers do?

  • Employers need to create a culture of constant feedback loop. New employees should find it easy to provide feedback about their work. You can create feedback surveys and get insights into the proper onboarding process of the new employees.
  • Conducting an informal meet-up session before the actual onboarding process will increase the efficiency of the onboarding process. An informal meet-up session will encourage peer to peer mentoring which will be a savior for the new remote employee.

De-Stressing

We cannot avoid stress. What we can do is minimize their occurrence and try to find ways to de-stress.

Working on-site provides you various opportunities to relax and de-stress. Be it the regular water cooler chit chat or a small stroll with colleagues during the lunch break.

But working from home or working remotely adds another layer of complexity because of the lack of proper ways of de-stressing. Suddenly remote workers start craving the boring office party they once hated.

What can employers do?

Employers need to encourage both their onsite workers and remote workers to de-stress and take a break. But it’s easier said than done in the case of remote workers. Here are a few ways in which employers can motivate their remote workers to de-stress.

  • Encourage workers to improve their physical health. Motivating employees to work-out can have a really great impact on the mental health of your employees and finally lead to an increase in productivity and efficiency. You can even conduct virtual group activities where employees can do a mini 7 minutes workout together.
  • Employers should conduct webinars on the importance of mental health. If that is not really feasible, then you can at least educate your employees regarding certain help-line numbers or agencies which cater to de-stressing and resolves mental health issues.

Everyone goes through stressful periods at some point or another. Employers should be able to correctly identify any strange change in behavior in their employees. One easy way to achieve this is to monitor the outputs of your employees. If there is a substantial decrease in the output of an employee then maybe employers can have a friendly chat and try to figure out the issue.

Mental health is a serious issue and probably the most impactful aspect that affects the output of an employee. Improving the mental health of your employees not only de-stress and improves their quality of life, but also increases productivity and efficiency in your workplace.

Categories: Others Tags:

10 Tools I Can’t Design Without

June 22nd, 2020 No comments

No matter how skilled you are as a designer, you need tools. A surgeon can’t operate without a scalpel; the same goes for designers. To get the job done effectively, you need to right tools in your arsenal.

Tools certainly don’t make the craftsman, but they do make your job easier (and mostly fun).

There are so many tools available today, it can be daunting to start seeking out the right tools for you. In this semi-regular series, designers introduce us to the tools they rely on regularly; some may be just what you’re looking for, others you might be familiar with already, some you might not like at all.

Today, Marvellous Aham-adi introduces us to the tools he uses when designing…

1. Sketch

Bohemian Coding’s Sketch is a vector graphics editor for macOS. The powerful vector-based tool is used for desktop and mobile UI designs, creating mockups and prototypes, and also allows collaboration among designers.

The main con to the tool is that it is a Mac-only app, so only mac users can use the app. Aside from that, the tool is user friendly. It doesn’t have a steep learning curve unlike other design tools. The tool was created strictly for designing websites and apps so there are no unnecessary features that cluster the design interface. This makes designing easier and less complicated. Another advantage is that since it’s a vector-based app, the file sizes are significantly smaller.

You can choose from hundreds of plugins and extensions that help you do everything from creating charts with random, tabular, or JSON data. You can also create 3D mockups in Sketch with full control over angles and perspectives. It also comes with an SVGO compressor, Bitmap Compressor, and allows easy grabbing of images from Unsplash.

2. Procreate

Procreate is a powerful and intuitive digital illustration app for iPad. The app allows you to create illustrations, animations, rich paintings, and sketches. With its creative tools and unique features, it can serve as a complete art studio.

The app comes with a huge library of over 200 handcrafted brushes. You get access to artist brushes, pencils, inks, and charcoal. You can also make your own custom brushes or customize any brush to suit your style with the Brush Studio. It also comes with a Valkyrie graphics engine that allows you to draw, paint, and sketch designs at incredible speeds. The engine takes advantage of Apple’s ProMotion technology to help you get the best performance out of your iPad.

It also comes with unique features like QuickShape that helps you get the perfect shape every time and StreamLine that helps you create strokes with smoother curves and fewer imperfections.

3. Dribbble

Dribbble is a social network for designers. The app is a go-to resource for discovering and connecting with the world’s top designers and creatives. Dribbble can be used in creating your personal portfolio, getting inspiration, and interacting with other designers.

What I love about the tool is its use of basketball metaphors. Its users are called “Dribbblers”. Dribbblers can post “shots” ( 800 x 600 sized images). Dribbble has a feature known as “bucket” which is similar to Pinterest boards. Other users can like, comment, or follow your bucket. You can also “rebound” by posting a design that is inspired by another post. You can also create design competitions also known as “playoffs”. Design agencies can create “teams” so that their designers can collaborate in one place.

Dribbble also serves as a marketplace so if you’re a freelance designer looking for design jobs, then you should check the platform regularly.

4. Adobe Capture

Adobe Capture is a powerful vector converter that allows you to convert images on your mobile devices into patterns, color themes, types, brushes, and shapes. You can then proceed to use these assets in other creative tools like Adobe Photoshop and Illustrator.

The tool allows you to convert an object or your entire photo into a vector graphic. You can adjust the contrast on the amount of detail you want to capture and also invert the black and white areas on the vector image.

One of my favorite features is the ability to create custom palettes. You can pick colors from your photos to use in a project. You can take a photo and use the colors in it to create a palette. So if you see a visually pleasing design and don’t know what exact color it is, you can capture the image, and Capture will create a palette automatically for you.

Other interesting features the app comes with is the ability to convert any part of your image into brushes, create kaleidoscopic patterns from photos, collect 3D textures, and create your own high-quality 3D (PBR) materials to use in Adobe Dimension.

5. InVision Studio

InVision Studio is an advanced prototyping and animation tool that allows you to create vector-based screen designs. Thanks to its flexible layers and infinite canvas, you can design workflows at incredible speeds. The tool allows you to create interesting prototypes, test your designs and make changes before the development stage, and also communicate your designs ideas with your team or clients.

InVision Studio works on both Mac and Windows. You can import files from Sketch into InVision. Some of its interesting features are intelligent image cropping that automatically crops images as you change screen size. You can create a responsive prototype without writing a line of code, test an animation or prototype on your phone, create swipe triggers for animations that occur on scroll, and link several artboards into one animation.

6. Wappalyzer

Wappalyzer is a tool that allows you to find out what technology websites are built with. The best part is that it is free to use and you can look up any website. It comes with a free extension for Chrome, Edge, and Firefox that works locally and offline.

The Wappalyzer API provides you instant access to a website’s technology stack, enriches your own datasets, and analyzes a large number of websites in real-time. You can perform up to 1000 lookups at once.

7. W3C CSS Validator

W3C CSS Validator is a simple but effective tool that allows you to check the markup validity of Web documents in HTML, XHTML, SMIL, MathML, etc. To validate a URL, all you need to do is put in the address and run the test. The tool also automatically detects character encoding and document type. You can also clean up Markup with HTML-tidy, group error messages by type, and validate error messages.

8. Figma

Figma is an online UI/UX design tool that allows teams to collaborate in real-time. With its interactive prototyping capabilities, you can create vector illustrations, design apps, and screens. Although it is a browser-based tool, there are versions that work on Windows and Mac.

With Figma, you can create libraries with reusable components. When a component in the library is updated, changes would be automatically made to any design that uses that component. Team libraries are available on the paid version only. You can also generate CSS and SVG, iOS and Android code; export files as JPG, PDF, PNG, or SVG, and also import Sketch files. You can also automate repetitive tasks, create custom workflows, and bring in data using plugins.

9. Proto.io

Proto.io is a tool that allows you to create high-fidelity prototypes in real-time. With this tool, you can test your designs before you build. You can test flow, interactions, and animations without writing a single piece of code.

The tool comes with customizable templates that help you create prototypes and wireframes easily. It also comes with a huge icon library (including animated icons) that can be resized and recolored. With its effect library, you can also add interactions, sounds, animations, and video files to your prototypes. Since it’s a 100% web-based editor, you don’t need to download any software.

10. Startup 3

Startup 3 is an application that helps designers and developers create Bootstrap website themes. It is a powerful drag and drop bootstrap theme builder to help you create landing pages. It has an easy to use intuitive interface with no learning curve.

You get access to over 300 blocks of pre-coded and pre-designed elements and styles that you can easily customize. Designs from the app are automatically optimized for mobile and are compatible with all retina devices. It also integrates with other tools like Hubspot, MailChimp, Gmail, and Captcha. You can also export all your website designs (including image, text, and styles) directly to your PC.

Source

Categories: Designing, Others Tags:

6 Ways to adapt your eCommerce Business to the Coronavirus Quarantine

June 22nd, 2020 No comments

During difficult times, online businesses have to find new ways to make their businesses relevant and manage to make a profit. The Coronavirus quarantine has caused many physical stores to close but this doesn’t have to be the case for eCommerce stores.

On the contrary, this situation has caused most consumers to use online stores as an easy alternative. This way, they are still able to buy their favorite items while staying safe at home. Here are some of the most useful tips to help adapt your eCommerce business to this new reality and make the most out of it.

1. Inform customers about your urgent measures

First and foremost, you need to make sure to have a section on your eCommerce store dedicated to the safety of your employees, customers and business. While you might be taking all the measures necessary to keep your employees and customer safe, the later will have no way of knowing that. Therefore, it is important to let them know how your company is dealing with this situation.

In addition to this, it is important to let your customers know about any shortages your business might face because of the sudden demand. Many people end up having a lot of free time and this can lead them to buy things in large quantities. You should make sure you work closely with your suppliers and inform your customers so you can be prepared for such situations.

2. Provide online chat support

In order for your business to be able to survive this new situation, you need to make sure to provide your online customer with enough information about your products. Making your products attractive is important during this situation and the best way to do it is by providing as much information as possible.

The online chat support will help solve questions about product details, lacks in stock, shipping information and many other things. All of these are essential pieces of information which will help your customer decide on making a purchase. In addition, it will make working from home a little easier for your employees.

3. Offer sales and discount codes

While so many people end up having a lot of free time, they tend to do a lot of internet shopping for various items. If you were going to launch a promotional campaign for a sale or give away some discount codes, this might be the perfect time to do so. You can target both existing and new clients and expand your sales easily.

You should definitely try and make this sale targeted towards the Coronavirus crisis and how you wish to welcome new people and allow them access to their favorite items. Making your sales all about the current situation is the most important thing when trying to increase your sales during a crisis. Any sale you decide to hold should be Covid-19 targeted so you can promote it accordingly, even if the products you are selling are not exactly related.

4. Consider offering free shipping

Something many companies have been trying to implement during the Covid-19 crisis is offering their customers the option of free shipping. This is a tactic you could use instead of a sale on your eCommerce website and you can advertise it.

The number one thing you should expect is a big rise in your sales, and you should be able to make a deal with the shipping company you are working with, especially if you will be sipping our more orders than usual. This will make your customers a lot more likely to purchase more things, since they will not have to worry about the shipping costs.

5. Reply to emails quickly

While the live chat option might satisfy certain customers, others will still want to reach out to you in a more traditional way. People being at home all day can become a little impatient so you should make sure that your employees get back to everyone on time. Shipping might be a little delayed because of the whole situation but you can reassure your customers that their orders will arrive.

Emails should still be an option for anyone that has questions about their orders and does not mind waiting for a little. While a live chat provides immediacy, emails can supply the customer with more information. You can also easily use proofreading tools of your choice from any writing services websites and make sure your emails are free of any errors that a live chat agent can accidentally make.

6. Use social media to your advantage

Social media platforms would be one of your top priorities during this time. Targeting new customers is going to be important even during this time, as you need to be able to increase your sales and keep your store open. Your social media platforms can be a great means of immediate communication with your customers where you can promote your business and products easily however you wish.

Another great idea is to host giveaways on your social media platforms during the quarantine. Since people will have more time on their hands they will be more likely to go through your page after seeing your giveaway post. This can help you increase your sales easily and help your business survive the crisis.

Helping your business thrive through the pandemic

While this situation might be difficult for many store owners, there are quite a few different tactics you can implement in order to make sure your eCommerce store thrives. No matter what you choose to do there are always new things to try and find which offer the best results.

Just remember to be as helpful as possible and show your customers that you care about their shopping experience even during these difficult times. This will set you apart from other stores and help you build better relationships with your customers, both new and existing.


Photo by Pixabay from Pexels

Categories: Others Tags:

Popular Design News of the Week: June 15, 2020 – June 21, 2020

June 21st, 2020 No comments

Every week users submit a lot of interesting stuff on our sister site Webdesigner News, highlighting great content from around the web that can be of interest to web designers.

The best way to keep track of all the great stories and news being posted is simply to check out the Webdesigner News site, however, in case you missed some here’s a quick and useful compilation of the most popular designer news that we curated from the past week.

Online Tools I Recommend to Every Web Developer

The 7 Habits of Exceptionally Creative People

5 User Experience Goals to Enhance your SEO Strategy

What Happens When a Graphic Designer Opens a Bar…

Bootstrap 5 Alpha!

Designing a Responsive Website for a Local Gym — a UX Case Study

Worry Less About Spacing in Figma

Remembering Windows 2000, Microsoft’s Forgotten Masterpiece

4 Visual Principles for Junior Designers

Benefits of Digital Illustration in Web Design

Building ADA-Compliant Websites: Most Common Accessibility Issues

The Anatomy of a Dev Team

The Most Important Thing your Clients Should Know About their Website

15 Best Photoshop Actions to Create Spectacular Dispersion Effects

Adobe Flash Player End of Life: December 31

A Guide to Measuring the User Experience

Meet Orwell, Russia’s Cute and Totally not Sinister New Facial Recognition System for Kids

203+ Web Design Resources You’d Actually Want to Use (& Bookmark)

15 Amazing Examples of Clean Web Design for your Inspiration

Design Exercises are Evil

Inclusively Hiding & Styling Checkboxes and Radio Buttons

A Comprehensive Guide to Notification Design

10 Exceptional Product Design Portfolios with Case Study Breakdowns

The Badass Project

The Customer Journey Through Automated Email

Want more? No problem! Keep track of top design news from around the web with Webdesigner News.

Source

Categories: Designing, Others Tags: