Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
June 20, 2020 02:22 pm GMT

How to replicate the Zelda BOTW interface with React, Tailwind and Framer-motion: Part 1

In this article series we'll learn how to replicate the menu inventory interface of Zelda: Breath Of The Wild on the web !

Click on the image bellow to check the final demo:
Zelda BOTW demo

Articles structure

This will be a series of 3 articles:

  • PART1: Setup the Item Grid + Adding navigation + Selection Animation
  • PART2: Adding pagination + page transition animation + display additional items data
  • PART3: Handling actions with a modal + Handling items with bonus + new item animation + add sound

Target audience:

Intermediate Front-end developper.
If you are more experienced you might not learn much (at least for part 1) but it might still be an interesting exercice to do.

Why doing that ?

I find GameUI very inspiring, they shared different problematics than web interfaces and also similar ones. They are usually designed to not get in the way of a player experience of a game (Zelda BOTW is a perfect example of that). Web is not much different in that regard. When we design a website we're actually building an experience, the interface is just the way to interact with the experience.
Also GameUI are often filled with a lot of little details, these details are not always meant to be notice at first glance yet they amount for a significant part of an enjoyable interface.

About this interface

Zelda inventory interface

screenshot from interfaceingame.com

The interface is basically a two layout column.

  • The first column contains a grid of items grouped by categories.
  • The second column is used to display informations about the item selected.

There are a lot of animations on the interface that all serve a purpose:

  • arrows moving in and out the edge of the selected items
  • arrows at the horizontal edge of the grid to indicate that you can navigate between categories
  • when you change the selected item, the item description is typed progressively to catch your eye on the fact that these data have changed
  • item that are new (max durability) have a little shiny star. This animation is really subtle compare to the other, because it concerns a detail about the item

The first 3 animations, which are the most visible, act as signifiers (This a UX term that comes from Donald Norman, the author of The design of everyday thing), and help the player understand the actions he can do on the interface.

About the format

At first I thought of just providing some code samples with explanations but I don't think it would have provided much value.
You might have come to realize that we, as developper, learn best by actively doing something. That's why this article article series will actively encourage you to code your own version of the Zelda BOTW interface.
I'll give you a goal to reach at each step and provide leads for realizing it.
If you're stuck or if you just want to keep reading, the solutions will be provided at each step in separate gists.
I have setup a based repository with all the ressources to get you started immediately:

GitHub logo Flow11 / zelda-botw-starter

Template for reproducing the Zelda BOTW inventory interface

Zelda BOTW starter

Zelda BOTW demo

Complete demo

https://www.gameuionweb.com/zelda-botw

Articles links:

Stack

  • React
  • Tailwind
  • Framer-motion (beta)

Useful links for Tailwind:

Credits




The repository is setup with Typescript but no obligation here, you can use either ts or js as you prefer.

Prior requirements and notes about technologies used

This articles series is based on the following stack:

  • ReactJS and leverage some libraries of its ecosystem
    • Some prior knowledge is expected but nothing advanced
  • TailwindCSS
    • No prior knowledge expected, we'll introduce it briefly if you are not familiar with it.
  • Framer-motion:
    • This is the main library used for animation, no prior knowledge expected

Tailwind quick introduction

You can skip this part if you're already familiar with Tailwind

Tailwind logo

Tailwind is a CSS utility framework, it provides a set of css classes with low responsability like w-full for width: 100% or flex for display: flex.

These classes are generated base on a JS configuration file. In this file you define design tokens like color, spacing, ... and then tailwind will generate all the css classes based the design contraints you defined.

You can find the structure of this file here: Default configuration

I choose Tailwind for the article series because it allows me to prepare the design configuration upfront so you can focus on the most interesting part.
Also I will be able to put tailwind classes needed directly on schemas provided in the article to make implementation even easier.

If this is your first time with tailwind you could use this cheatsheet to help you find class at the beginning: https://nerdcave.com/tailwind-cheat-sheet
I also strongly recommend to install a plugin to get autocompletion on tailwind classes (see starter readme for the links).

Starting with the layout

We're going to start by creating the base layout of our interface.
What we want here is a responsive layout with the following constraints:

  • Extra large screen (XL): a two columns layout column, with each column taking 1/2 of the screen.
  • bellow extra large screen (<XL): there should should only be one column taking full width.
  • The layout should be contained inside a centered responsive container.

Once your layout is done you can add the bg-zelda-darkGreen class to your main div and we're good for that part.

Layout

Ressources:

Solution:

https://gist.github.com/Flow11/e440ac5c56f21ef9b9db37d1c780ad20

Adding the items grid

We'll now create our ItemsGrid and Item components.

Alt Text

We want to create a 5 columns Grid, with css-grid, which reduce to 3 columns on mobile, that displays an Item component in each cell.
To create the Item component we will need the following data available in src/data/items.js. An item data looks like this:

    {      name: "Tree Branch",      category: "weapon",      icon: "/zelda-botw/items/weapons/BotW_Tree_Branch_Icon.png",      value: "2",      isNew: true,      description:        "Wooden branches such as this are pretty common, but it's surprisingly well-balanced. It doesn't do much damage but can serve as a weapon in a pinch.",    }

For now our component will just have to display its icon and value and also his name for the image title.
Our item should look like this:

Alt Text

Ressources:

Solution:

Items selections

Now we want to be able to select an item by clicking on it by applying the following classes.

Item selected

Our app structure should look like this at this point:

<App>  <ItemsGrid>    <Item>

We will need to:
- store the index position of the selected item using React.useSate in App component
- create a context with React.createContext to store the selectedItem position and the setSelectedItem from the previous useState
- Retrieve the context value inside the Item component using useContext hook.
- Activate the selected classes from above using classnames utils and the value from the context.

Ressources:

Solution:

https://gist.github.com/Flow11/d0627032cb459166dd454110337a1ab1

Keyboard navigation

For this part we will have to convert the index position of an item to a 5x4 matrix position and an other one to revert it.
The grid position should be like this:

Grid position

So we will need a method that convert for instance 6 to {x:1 ,y:1}
And an other method that convert {x:1 ,y:1} to 6
The first method signature should be:

  • (index: number) => {x:number, y:number}

The second method signature should be:

  • ({x:number, y:number}) => number

We will then need four methods to compute the new position base on the direction goUp, goRight, goLeft, goBottom
I strongly recommend doing tests for these methods, but no obligation here.

Test example:

it("should convert 6 to x:1, y:1 position", () => {  // Given  const index = 6;  // When  const result = convertIndexToPosition(index);  // Then  expect(result).toEqual({ x: 1, y: 1 });});

Finally a handleKeyPressed function inside App component to handle the behaviour to execute based on the key pressed.

Note: the keyboard navigation is expected to work only for the 5 columns grid (since we have 3 columns for the mobile layout).

Ressources:

Solution:
https://gist.github.com/Flow11/dbce8e6be44e39f37a9f8e459a39f28c

Animation

Item selection animation schema

To close this first part we'll add some animation with framer-motion.
We will now add triangles at the edge of the selected item and animate them.
The triangles will be done using css. The css classes to create the triangles are already available, you have zelda-botw-triangle-up and zelda-botw-triangle-bottom.

We will need to create two components:

A Triangle component with the following props:

type Props {  animateParams: {    rotate: string,     x: [number, number, number],    y: [number, number, number]  },  className: string}
  • rotate should be something like "-10deg"
  • x should be something like [8, 2, 4], it will animate the triangle on the x axis through the values provided in the array. The values given here are random, I let you find the right ones.
  • y same a x but for the y axis
  • className will be used to apply a list of css classes

A TrianglesBox component that have no props but display 4 Triangle components.

  • To position the triangles we can apply a position absolute on them and position relative on parent Item. To animate the triangle component we will have to use the motion api from framer-motion
import { motion } from "framer-motion";const DummyComponent ({ animateParams }) => (  <motion.div    animate={animateParams}  />);

We will also need to apply a transition parameter to motion.div to obtain the desired effect.

Ressources:

Solution:

  • Triangle component:

https://gist.github.com/Flow11/8143023838936fb4b7cf81eae1c52d54

  • TrianglesBox component:

https://gist.github.com/Flow11/9587f518c4cf7f8ca991c63a8144b75b

What's next

Congratulation for completing the first part, I hope you enjoyed it !
On part 2 we will implement the pagination between the items categories, the page transition animation and display additional data about the items.
If you encountered any issues or if you have feedbacks let me know here or on twitter, I will gladly try to address them !

Notes

All the schemas were done using Excalidraw. Thanks to the team for providing such a great tool for free.


Original Link: https://dev.to/flagrede/how-to-replicate-the-zelda-botw-interface-with-react-tailwind-and-framer-motion-part-1-298g

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To