The initial markup

We will start with the HTML. For this component we need just a container and the buttons. As I just mentioned above, we will use the FontAwesome icons for the buttons, they’re not exactly the same as in the original submission but they’re good enough.

Right now we should have the four icons, it’s time to make it look more like the final product.

Styling

In the container we need a background color, I’ll use black for now but later we will change that programatically. Also I’ll use `flex` and `justify-content` to center the elements horizontally, then just some padding to vertically align them.

The behavior

Now in our Vue instance we will start declaring the data that we need to use on the component. With a color picker, I took the different colors for buttons and backgrounds and put them inside a structure so we can reference them in the future:

This code is also already binding the background color to the btn-container div style.

Notice that we added an @click handler that should trigger a function called selectButton, also the ref attribute will help us reference the buttons when we need to animate them.

Clicking a button

We need to declare first the `selectButton` method in our Vue instance:

// ... data,
methods: {
selectButton (id) {
this.selectedId = id
}
}

After this the selectedId will change on every click to values between 0-3, but that doesn’t seem to do anything to our component. We need to start animating things!

Let’s begin animating the simplest part, the background color. For that we need to make a computed property that will get the selected button data which will help us to get the corresponding background color.
Later when we change the selectedId we will be able to tween the color to the current selected one.

Before coding that part we need to stop and think how the buttons should animate. If we analize the gif, the button animation can be split in two changes, one for the colors of the button and icon and the other one for the width of the button.

The colors transition looks really straightforward, the button’s background changes to white when inactive, and to the color property when active. For the icon, it just changes between gray and white.

The interesting thing is with the button width animation, it looks kinda “elastic” because it goes a bit back and forth at the end.

Playing with the GSAP ease visualizer I came with the props that closely match the easing of the original animation. Now we can finish coding the animateIn and animateOut methods:

We’re almost done, there’s just a small detail. When the app starts, the component doesn’t look to have a selected button. Luckily that can be quickly solved by calling the selectButton method inside the mounted hook: