DEV Community

Cover image for How I build a YouTube Video Player with ReactJS: Building the Play Button
Keyur Paralkar
Keyur Paralkar

Posted on • Edited on

How I build a YouTube Video Player with ReactJS: Building the Play Button

In the previous blog post, we dug deep into the architecture of the Project, if you haven't read it please do read it here. This post is going to be a very short one. In this post, we will be building our first control toolbar component which is the Play/Pause button. Before we jump into building the play and pause control button, let us first start with building the ControlToolbar Container component.

So without any further ado let us get started.

Building the ControlToolbar Component

ControlToolbar

Do you see the portion highlighted at the top(the pink one)? That’s ControlToolbar component and that’s what we are going to be building in this section.Before we start building, let us set some basic expectations from this component:

  • While the video is playing, the toolbar should be visible when the mouse is hovering over the video. This bar would be hidden if we were not hovering over the video.
  • If the video is paused, this toolbar would be visible all the time irrespective of mouse being hovered over video or not.

Toolbar visibility in different states

💡 NOTE: If you have doubts check out YouTube and you will understand what I am trying to say. Ok now let us start building this component.

From our previous blog post, we know that this project comprises 3 components that come under one parent component which we call YoutubePlayer component. We use this same parent component to drive the hovering expectations(discussed above) with the help of CSS.

Inside YoutubePlayer.tsx component, add the following CSS inside the StyledVideoContainer component such that the whole CSS looks like below

const StyledVideoContainer = styled.div`
    position: relative;
    width: fit-content;

    .video-controls {
        opacity: 0;
    }

    &:hover .video-controls {
        opacity: 1;
    }
`;
Enter fullscreen mode Exit fullscreen mode

So here is what’s happening:

  • .video-controls class is the class-name assigned to our ControlToolbar component which we will look into it later in this post.
  • At start, while the video is playing we keep the opacity of the toolbar to 0. In this way, the toolbar will be hidden.
  • When we hover over the entire video which is YoutubePlayer component we want to show the toolbar, so we set its opacity to 1.

There is one caveat though, we didn't implement the behavior of toolbar where it should be always visible when the video is paused. Hold on to this thought, we will come to this when we have the ControlToolbar component ready.

Building the ControlToolbar component

ControlToolbar component is a container component that will comprise multiple controls such as:

  • Play/Pause Button
  • Mute/Unmute Button
  • Volume Slider etc.

To proceed with the implementation of the Play/Pause button, we must build this toolbar component. So without further ado let us get started. Create a ControlToolbar.tsx file inside the components folder and place the following content in it:

import { motion } from "framer-motion";
import { useContext } from "react";
import styled from "styled-components";
import { PlayerContext } from "../context";
import PlayButton from "./PlayButton";
import VolumeControl from "./VolumeControl";

const ControlToolbar = () => {
  return (
    <div className="video-controls">
      <PlayButton />
    </div>
  );
};

export default ControlToolbar;
Enter fullscreen mode Exit fullscreen mode

Next, we convert the div with class video-controls to a styled component. Create a styled component named StyledVideoControl and place the following CSS in it:

const StyledVideoControl = styled(motion.div)<{ isPlaying?: boolean }>`
    position: absolute;
    width: 100%;
    color: #eee;
    bottom: 0rem;
    background: #ffffff00;
    background: linear-gradient(180deg, #ffffff00, #010101);
    ${(props) => (!props.isPlaying ? 'opacity: 1 !important' : '')};
`;
Enter fullscreen mode Exit fullscreen mode

This styled component does two things:

  • Its position is absolute so that it always stays on top of the video.
  • The other is the opacity property. We set it to 1 because whenever the video is paused we want the toolbar to be displayed all the time irrespective of hover. This was the case we talked about in the previous section.

Now, we use this styled component by replacing the existing div.video-controls with StyledVideoControls:

import { motion } from "framer-motion";
import { useContext } from "react";
import styled from "styled-components";
import { PlayerContext } from "../context";
import PlayButton from "./PlayButton";
import VolumeControl from "./VolumeControl";

const StyledVideoControl = styled(motion.div)<{ isPlaying?: boolean }>`
    position: absolute;
    width: 100%;
    color: #eee;
    bottom: 0rem;
    background: #ffffff00;
    background: linear-gradient(180deg, #ffffff00, #010101);
    ${(props) => (!props.isPlaying ? 'opacity: 1 !important' : '')};
`;

const ControlToolbar = () => {
    const { isPlaying } = useContext(PlayerContext);

  return (
    <StyledVideoControl className="video-controls" isPlaying={isPlaying}>
      <PlayButton />
    </StyledVideoControl>
  );
};

export default ControlToolbar;
Enter fullscreen mode Exit fullscreen mode

Also make sure that you call our ControlToolbar component inside its parent i.e. YoutubePlayer like below

import styled from "styled-components";
import { PlayerProvider } from "../context";

const StyledVideoContainer = styled.div`
  position: relative;
  width: fit-content;
`;

const YoutubePlayer = () => {
  return (
    <PlayerProvider>
      <StyledVideoContainer>
              <Video />
                    <BezelIcon />
                    <ControlToolbar />
      </StyledVideoContainer>
    </PlayerProvider>
  );
};

export default YoutubePlayer;
Enter fullscreen mode Exit fullscreen mode

Pretty cool right!. Awesome now we have our basic structure ready for the toolbar, now it is time to develop our first control which is the Play and Pause button

Building Play/Pause Control

Create a file named: PlayButton.tsx inside the components folder and place the following content in it:

import { useContext } from "react";
import { HiMiniPlay, HiMiniPause } from "react-icons/hi2";
import { PlayerContext, PlayerDispatchContext } from "../context";
import { PLAY_PAUSE } from "../context/actions";

export const StyledIconButton = styled.button<IconButtonProps>`
  background-color: transparent;
  border: none;
  width: 45px;
  float: left;
  margin-bottom: 3px;
  color: inherit;
  font-size: ${(props) =>
    props.iconSize || props.iconSize !== "" ? props.iconSize : ""};
`;

const PlayButton = () => {
  const { isPlaying } = useContext(PlayerContext);
  const dispatch = useContext(PlayerDispatchContext);
  const onPlayPause = () => {
    dispatch({ type: PLAY_PAUSE, payload: !isPlaying });
  };

  return (
    <StyledIconButton onClick={onPlayPause}>
      {isPlaying ? <HiMiniPause size="25px" /> : <HiMiniPlay size="25px" />}
    </StyledIconButton>
  );
};

export default PlayButton;
Enter fullscreen mode Exit fullscreen mode

This component is pretty similar to BezelIcon component. It makes use of both the state and action context i.e. PlayerContext and PlayerDispatchContext and dispatches the action PLAY_PAUSE whenever button container: StyledIconButton is clicked. Based on the value of isPlaying we show the play and pause button.

💡 Tip: Since Icons are something that we are going to use a lot, therefore, we move the StyledIconButton to the utils where it is accessible to more components.

Create a folder outside of components named: utils and create a new file: index.tsx:

import styled from "styled-components";

type IconButtonProps = {
  iconSize?: string;
};

export const StyledIconButton = styled.button<IconButtonProps>`
  background-color: transparent;
  border: none;
  width: 45px;
  float: left;
  margin-bottom: 3px;
  color: inherit;
  font-size: ${(props) =>
    props.iconSize || props.iconSize !== "" ? props.iconSize : ""};
`;
Enter fullscreen mode Exit fullscreen mode

We make use of react-icons to display the play and pause indications.

import { useContext } from "react";
import { HiMiniPlay, HiMiniPause } from "react-icons/hi2";
import { PlayerContext, PlayerDispatchContext } from "../context";
import { PLAY_PAUSE } from "../context/actions";
import { StyledIconButton } from "../utils";

const PlayButton = () => {
  const { isPlaying } = useContext(PlayerContext);
  const dispatch = useContext(PlayerDispatchContext);
  const onPlayPause = () => {
    dispatch({ type: PLAY_PAUSE, payload: !isPlaying });
  };

  return (
    <StyledIconButton onClick={onPlayPause}>
      {isPlaying ? <HiMiniPause size="25px" /> : <HiMiniPlay size="25px" />}
    </StyledIconButton>
  );
};

export default PlayButton;
Enter fullscreen mode Exit fullscreen mode

So here we are all set up, with our first control the play pause button is finally done. Here is how it will look

Our outcome

Summary

To summarize, we learned,

  • What a ControlToolbar component is, we also learned how to implement it.
  • We looked into the implementation of Play/Pause control.

In the next blog post of this series we are going to talk about building one of the crucial controls which is VolumeControl so stay tuned for more!!

The entire code for this tutorial can be found here.

Thank you for reading!

Follow me on twittergithub, and linkedIn.

Top comments (0)