How to replicate the Zelda BOTW interface with React, Tailwind and Framer-motion: Part 3
Tags: react, tailwind, framermotion
Published: 2020-07-19 09:25:52

---
series: zeldabotwgameui
---

For the final part of the Zelda series we're going to add a lot of little details, more animations and sounds !

## Checkpoint

After the [second part](https://github.com/Flow11/zelda-botw-starter/tree/part2-checkpoint) our interface should look like this.

![Part 2 checkpoint](https://dev-to-uploads.s3.amazonaws.com/i/dm5u2mt6avd3gkx4xhj7.png)

# Items actions

## Creating the modal

![modal wireframe](https://dev-to-uploads.s3.amazonaws.com/i/k8hhu5frin746uqzxn0f.png)

We are going to start by creating a `Modal` component in order to interact with the item selected. The modal will provide the `equip` and `drop` actions. For this step we will display the modal when either a click or the enter key is pressed on a selected item. The actions will be handled later on, we can close the modal instead when they are selected. We will also handle keyboard navigation inside the modal actions and create a `useClickOutside` hook to close the modal when we click elsewhere.

**Notes**

We also must not forget to reset the focus when the modal is closed to keep the interface navigable with the keyboard.

**Solutions**

In the first commit below, only the keyboard is handled to open the modal. The onClick handle is done in the second commit.

- [Checkpoint commit](https://github.com/Flow11/zelda-botw-starter/commit/88019ab674bb039abd2f2b365a5e94e0956b41b8)
- [Commit for missing onClick event](https://github.com/Flow11/zelda-botw-starter/commit/ddb347b8ac23ddd534e1572908ca9306c1a44408)


## Handling modal actions

We are now going to handle the `equip` and `drop` actions inside the modal.
For the equip feature we have some requirements. Link can have equip at the same time the following items:
- 1 Weapon
- 1 Shield
- 3 Armors:
   - 1 Helm
   - 1 Armor
   - 1 Greaves

![Item Equipped](https://dev-to-uploads.s3.amazonaws.com/i/pqu8danvl7590r0fxk9l.png)

We can also add some visual indicators to show that an item is equipped like a radial background in the item cell and a blue bar inside the `ItemInformation` component. The blue color should be defined in our Tailwind config file.

![Item information equipped](https://dev-to-uploads.s3.amazonaws.com/i/d0ujx2wqeg8dggobqmz3.png)

For the data structure of our new state we can use for instance an object with the `item.category` string as key and the item data as value.

```ts
{
  [key: string]: ItemType
}
```

The drop feature should be simpler, we just want to remove the item selected and add an empty item at the end instead.

**Solutions**

- [Checkpoint commit](https://github.com/Flow11/zelda-botw-starter/commit/b16257cba3a2895cf08d14b965970c9687b3aecb)

## Handling items with special bonus

![bonus wireframe](https://dev-to-uploads.s3.amazonaws.com/i/0q9w0yoplua1vodhvqs1.png)

We are now going to handle the bonus for armor's items. To do so we have to:
1) Display the bonus icon of an item inside its cell
2) Compute all the active bonus based on what items are equipped
3) Display the active bonus, with a new component, inside the right column

For the first step we need to create a `BonusIcon` component which takes for example a `bonusType` as props and returns the appropriate bonus icon (fire, swimming or climbing). Then we can use this component inside the `Item` component.

For the second step we need to create a state to store the active bonus. These bonuses will be updated whenever the items equipped change. We can use a `useEffect` hook for that. For the data structure of our new bonus state it could look like that (if you are using TS, otherwise define key as usual):

```ts
{
   [ItemsBonusType.FIRE]: 0,
   [ItemsBonusType.SWIMMING]: 0,
   [ItemsBonusType.CLIMBING]: 0,
}
```

For the final step we are going to create two new components `BonusBox` and `BonusList`.
- `BonusBox` will display a `BonusIcon` and little bars, up to a max of 3, to show how many items which have this bonus type are equipped.
- `BonusList` will receive the data we've created on step 2 and display a bonus for each of the bonus types.

**Solutions**

- [Checkpoint commit](https://github.com/Flow11/zelda-botw-starter/commit/f9d6a30ed0c6901182938066ea6833c47872e77c)

# Adding little details

## Sounds

To add sounds to our interface we are going to use the handy [use-sound](https://github.com/joshwcomeau/use-sound) hook from [Joshua Comeau](http://joshwcomeau.com/).
The sounds has been added in the [repository](https://github.com/Flow11/zelda-botw-starter/commit/b4b49c34624ec87376dbac2172bdbaa7c510812f). There is one for selection (arrow keys, click) and other one for actions (equip, drop). The sounds should be playable from anywhere inside the app so we should create a new context for that. We might need to create a wrapper for our main `App` component for the new sound context.
Then we should use the sounds wherever it feels necessary.

**Solutions**

- [Checkpoint commit](https://github.com/Flow11/zelda-botw-starter/commit/ddb347b8ac23ddd534e1572908ca9306c1a44408)

## Endurance gauge

![Endurance gauge](https://dev-to-uploads.s3.amazonaws.com/i/nxwb0kd1ye2zvl2rxzda.png)

This is going to be a small step but details matter. We are going to display an endurance gauge with css only.
We are going to need two `divs`, one for the outer circle and one for the inner circle. To create the circle effect we just just have to apply a `border-radius: 50%` to them.

**Notes**

It might be easier to create a custom css file for this rather than add all missing values to Tailwind, since we're not going to need them elsewhere.

**Solutions**

[Checkpoint commit](https://github.com/Flow11/zelda-botw-starter/commit/b9ac0472ba2c0f3b5d5ceea54726ad6f43114938)

## Full durability star

![Durability star](https://dev-to-uploads.s3.amazonaws.com/i/uqzhbunb646n6caf43kj.png)

For the final touch we are going to add a sparkle animation for items with full durability (items with the `isNew` property in the dataset).
Like we've done before we need to convert the sparkle SVG from the asset folder with [SVGR](https://react-svgr.com/playground/?typescript=true).

After that we need to create an animation, still with [framer-motion](https://www.framer.com/api/motion/animation/), to rotate and scale the sparkle at the same time and infinitely.

**Ressources**

- Joshua Comeau has written a [great article](https://joshwcomeau.com/react/animated-sparkles-in-react/) on the subject.

**Solutions**

- [Checkpoint commit](https://github.com/Flow11/zelda-botw-starter/commit/ed4beedeca5f1295814ca898f4a4234301d00d1f)


# Wrapping up

Wow we're finally done with the ZeldaUI, congrats for completing it !
I hope that you learned new things and that you had fun at the same time.
If you're interested, I'll be sending updates on the new GameUI I'll be working on here: [GameUIonWeb newsletter](https://www.gameuionweb.com/). I look forward to it, it will be a ton of fun I think.
If you have any ideas or feedback you can send them here gameui.on.web@gmail.com, I will gladly try to address them.

See you then !