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
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.
💡 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;
}
`;
So here is what’s happening:
-
.video-controlsclass is the class-name assigned to ourControlToolbarcomponent 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
YoutubePlayercomponent 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;
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' : '')};
`;
This styled component does two things:
- Its position is absolute so that it always stays on top of the
video. - The other is the
opacityproperty. We set it to1because 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;
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;
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;
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
StyledIconButtonto 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 : ""};
`;
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;
So here we are all set up, with our first control the play pause button is finally done. Here is how it will look
Summary
To summarize, we learned,
- What a
ControlToolbarcomponent is, we also learned how to implement it. - We looked into the implementation of
Play/Pausecontrol.
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!



Top comments (0)