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-controls
class is the class-name assigned to ourControlToolbar
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;
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
opacity
property. We set it to1
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;
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
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 : ""};
`;
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
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!
Top comments (0)