Build a Fullstack Music App with Next.js Player Controls UI
A second version of this course released using Next 13+, but this course is great if you want to see another example fullstack project. We now recommend you take the Build a Fullstack App with Next.js, v2 course.
Transcript from the "Player Controls UI" Lesson
>> So, let's hop right into it and get these controls done for the actual player. So if we zoom in on this a little bit ,it looks like we have a shuffle button. A previous button, a play slash pause button, a next button, and then a repeat button.
[00:00:17] And then followed by a track or seek bar, however you wanna call it. That shows the current runtime and then the full duration. So and as you anticipate, we do expect that to move as time goes on and click to seek drag to seek. So we will attempt to get all of that done.
[00:00:35] And let's hop right into it. So what we'll do is we'll come into our code. And we'll make a new component here and we're gonna call this just the player. Player dot TSX in the component folder. So, first thing first is we're gonna import some of the things for our UI, which is gonna come from chakra.
[00:00:52] It's been so good to us lately. We'll just keep using it, and it's gonna be a lot of stuff here. So, a couple things. They have this really cool thing called a button group. We'll use that that's just basically a bunch of buttons put together next to each other.
[00:01:10] So we gotta use a flex container to do that. We're gonna use a box obviously, we're gonna use the icon button. We use that one another component that was really cool. I think for that big play button we use that. Then a bunch of things for the actual seekbar.
[00:01:23] There's a range slider, that we're gonna use. And some other things that come with that is gonna be a range slider field to track. A range slider track, yeah there we go and then another one is range slider thumb. So all those are gonna work together that give us that nice seekbar.
[00:01:50] We're gonna use the center component which I'm pretty sure just figures out how to center things based off. Whatever situation is basically a magic flexbox thing. It's pretty awesome. We're using the flex container and then we're gonna use the text. So we're gonna use all of those. And then we're also gonna import a really cool library called react.
[00:02:44] It doesn't do any UI stuff for us it just gives us the mechanism of loading of playing a foul or a sound. Without this it would be much, much difficult. Or I guess we could just use an issue of file player or audio. That's not so bad, this thing just abstract a lot.
[00:02:59] Makes it so easy to do so we'll be interacting with this but we still gotta do all of the UI all the state stuff ourselves. We just don't have to manipulate the actual song itself. So we got that we're gonna import some stuff from react. So we're gonna have here is gonna be I've got some use effects going on.
[00:03:20] We're gonna have some use refs going on so we get a reference to the react taller when it's rendered. And some states because we gotta keep track of a bunch of stuff. So you state and then we're gonna also pull in some icons and stuff. So from the icons, we're gonna pull from react icons.
[00:03:41] And I think it's gonna be slash MD for material. I really like their icons. The ones we're gonna use are gonna be MD shuffle for that shuffle. There we go. We're also gonna use MD, previous lines on the wifi like a component there we go. And then we're gonna also use MD next otherwise or I'm sorry in the skip previous MD skip that Next let's do that.
[00:04:14] And then we're gonna use MD outline play cicle filled, I think we did that one before, outline play circle filled. And then another one MD outline circle filled. And then the last one is Md, outline, repeat. Md, my repeats repeats there we go okay. So we got that and then lastly we're gonna do a little more import for our action that we just created in our store.
[00:05:01] So we wanna be able to use that so we can import from easy-peasy and we're gonna use a hook called use store action. And that'll let us use the action that we created. Cool, so lots of imports, a lot of things happen there. And it's totally fine if you don't import all these right now because as we go along well we can import them.
[00:05:28] So which is what I would normally do in the code anyway, I will import them as I'm building them. I just don't wanna be scrolling up and down to the page as I'm building for the sake of teaching. Yes.
>> Did you just import easy-peasy we didn't actually import our store?
>> We imported something called use store actions from easy-peasy but yeah we're not gonna import the store. It's already provided through the provider that we added so every component has access to it already, yeah. All right, let's make this player, so const player, equals our component here. Always, I'm just gonna default export it right quick and put something in there.
[00:06:09] And get it rendered on the page so we can build it and see it at the same time. Just gonna return a box here. Save that, and then the player is gonna go into player bar. So we'll default export that go to the player bar, here where I put controls which is basically in this box.
[00:06:32] That's, has a 40% width. This is where we're gonna put the player, so, player in here, I need to import it, there we go. So let's go verify that it works. You can see hello from player, players loaded up. Now we can actually make this thing look good.
[00:06:57] So there's a lot going on here I keep saying. So what we're gonna do first is just try to get the UI down with no interactions no state. And then we'll move on to adding the state and the handlers. And then lastly, we'll get the interaction down and we can finally play it.
[00:07:10] So a couple steps to get this player working. So heading back to the player, I said, we're just gonna start with the UI first. Let's just kinda get that going and then we'll move up and do all the other things. So the first thing is let's we have our box, put this on another line here.
[00:07:25] Got our box here, which is gonna be the container for everything. And then what I need to do is I need to render the react handler. It's actually a component. Like I said, it doesn't have a visual interface to it. It's just something that has to be put in the Dom and then we can reference it using the use ref hook.
[00:07:45] So I'm gonna add another box here. And then I'm gonna render the reacts. Howler component like this. It has a bunch of props on it. We won't deal with those props right now. We'll wait till we get to actually adding state and stuff like that but we have that there so we have this box.
[00:08:04] The next thing I'm gonna do is I'm gonna use the center component. I'm using this component for the buttons, yeah, that thing's gonna freak out because I want some props. I'm using the center component for these buttons here because I wanna center them. It's gonna center those buttons in the center.
[00:08:23] So do that. And as we're building it's out if we don't wanna see this error if you actually wanna see where you're doing. Just comment out the react taller until we get to it stellify. You'll need to put it in there if you don't wanna, I'll leave my commented out so it doesn't break everything.
[00:08:40] So do the center component here. Then we'll do the button group. So we get all those buttons in there. So we got our button group here. And then for the button group, you can just throw whatever buttons you want to here. We're gonna use the icon buttons, so when I say icon button, this be the first one.
[00:08:59] And this one is gonna be pretty sure this will be the shuffle one, so this will be the shuffle one. So we're gonna go back here. We're gonna give it a outline of nuns, I think by default they have this weird outline on him. So we're gonna take that off, which looks like a border variance will be the link variants.
[00:09:22] And then what we're gonna do is as far as color, we'll just say gray. 600 like that in fact all these are probably gonna be the same color. So what I'll probably do is just move this color up to the center so everything but needed has the same color.
[00:09:44] It's gonna freak out if we don't add an ARIA label to these icon buttons on ARIA label. And I'm just gonna call it shuffle, like so. Font size is gonna be 24 pixels or whatever you feel works. Let's save it so I can format it. And then for the icon we're gonna render.
[00:10:05] And make sure you render this as an use these JSX brackets, the MD shuffle. So I'm not sure how familiar you all might be with JSX. But at the end of the day, if you look at the output of JSX, each one of these components is a function call.
[00:10:23] Right? And props are arguments to that function, children arguments to that function. And when you render a component like this with the brackets, you're invoking the function you're calling it. So they just think about that when you see these components, the difference between. Just referencing a component out here versus wrapping it in brackets.
[00:10:43] Is the difference between just referencing a function versus actually calling it. Cool so we got our MD shuffle there, to show up, I don't know if mine actually showed up let's see I can't actually see it. Maybe I can make sure it's not a different colors. I'll just let me check the DOM.
[00:11:06] I put icons with poro should be icon singular. That'll do it. There we go. So now we got the shuffle icon there, it's gray. And we'll do the same thing for all the other icons. So the next one is gonna be, previous than play pause the next repeat.
[00:11:23] So I'm just gonna copy and just switch them out so look at this other icon here for shuffle for underneath it we'll change this to MD. Skip previous so we got that. And then we're gonna make two for the play and we're gonna make one for the play and one for the pause.
[00:11:46] But then when we add our state will toggle them depending on if we're playing or not. So it's gonna look weird right now until we add the state because they're both gonna be on the page. But when we get the state we'll only show one depending on if we're playing or not.
[00:11:57] So I'm gonna make one here for the playing so for playing this one's gonna be in the outline play. In the outs line, play circle fields like so. And we're gonna make this a little bigger because other ones are 24. But look at that button is actually a lot bigger.
[00:12:21] And the color is always gonna be white because when it's on it's active question.
>> Shouldn't the ARIA label actually change?
>> Yes, we should change our labels if we wanna be. Yeah compliance so change our labels this one will be skip. This one will be was this one play.
[00:12:42] There we go. We're gonna make another one for pause. Should just be able to replace that with pause, make that 40 pixels, change that to pause. If you go back, but it's looking good, they're all lined up perfectly. Got a play, got a pause, got a previous got a skip, all we need is a next and a repeat.
[00:13:11] So for the next one I believe it's called indy skip next make sure you go back to 24 pixels for that one. That looks good yeah this also should not be white, should be great, looks great. And then the last one will just be, repeat. So this will be, what is it?
[00:13:44] Md outline repeat. And change the label to repeat. There we go. So we got all our icons, I mean it's kinda quite a lot of JSX here, I mean that I guess we could. Do what I did before and take some of this out, put it in an array iterate over it, but because a lot of these are gonna have.
[00:14:08] Click handlers on them, that's where it gets complicated is, okay, but now you have to find click handlers. And some array outside of a component where the functions don't even exist yet. So probably not each kept do a bunch of crazy stuff. So we're just gonna render them in here like this.