Check out a free preview of the full Build an AI-Powered Fullstack Next.js App, v3 course
The "New Journal Entry UI" Lesson is part of the full, Build an AI-Powered Fullstack Next.js App, v3 course featured in this preview video. Here's what you'd learn in this lesson:
Scott creates EntryCard and NewEntryCard components. These components are responsible for displaying existing entries and creating new entries. They are added to the journal page, and additional Tailwind CSS classes are applied.
Transcript from the "New Journal Entry UI" Lesson
[00:00:00]
>> Let's work on trying to finish out this journal page. We're getting as close as we can so we can actually create a journal and start to see those journals fold in. Cuz we're gonna run into, I wouldn't say issue, but we're gonna run into a business decision that we're gonna have to make when it comes to getting this data.
[00:00:19]
And I can't wait to talk about it. Or at least showing the data, mostly because we're getting data server side on this journal page, but at some point we're gonna have to create something. And yes, with server actions you can create things on the server. If you've seen the intro Next.js, I've talked about server actions.
[00:00:38]
You also heard me say that I don't like to do that when a UI is waiting. So I probably won't use server actions for that, so I'll do it on the client. So if I'm doing that on the client as I'm creating something, but all the entries are being fetched on the server, how does the server know that it needs to go refetch all the entries that was created on the client?
[00:00:57]
So there's a miscommunication there. So solving that is a really good exercise in what Next.js is capable of. But we'll get to that. What we'll do now is let's just create some components for the entries we don't have and a component to create a new entry and we'll go from there.
[00:01:13]
So let's do that. First things first is, let's go to where we'll make some components. So what I like to do is to make a components folder on the root, so I'll say components, like so. And then inside of here, I'll make a EntryCard.tsx, and then I'll say NewEntryCard.tsx.
[00:01:47]
So for the entry card, well, let's just say EntryCard, it's gonna take in an entry, like so. Gonna be exported. And then for now we'll just show the IDs. We'll make it look good in a minute. Let's just say entry.id, super simple. And let me rename this so I spell it right, EntryCard.
[00:02:21]
And then for the new entry card, it's very similar. Actually, that's the whole point, it's supposed to look similar, it's jus for a new card. This won't take an entry cuz it's creating a new one. And instead we'll just say, new entry, like that. I always like to make my components just show a div, some hello world thing, render them, and then go back and make them.
[00:02:53]
That way I can actually see them on the screen when I'm making them. It's very rare that I'll go make a component and just flesh it out completely before I even render it somewhere. Unless I know exactly what I'm doing or I copied and pasted something, it's very rare that I'll do that.
[00:03:10]
Because I need to build it visually because It's a UI component, I need to see it. So very rare. So I always do this back and forth motion of getting them, just make it render something, go render it, and then come back and make it look good. Because a lot of the time in CSS, it's just me opening the browser, playing around with the CSS in the browser to see what styles I need, and then going back and adding those classes to the component.
[00:03:35]
It's a lot easier to design in the browser with the the dev tools than it is to go in here and add the stuff. Although Next.js and Tailwind makes it really quick, you just hit save and it refreshes immediately. But sometimes, lmaybe the state, maybe the thing that you're designing is hidden behind a few clicks.
[00:03:52]
And then this thing's got to happen, and this thing's got to happen, it's a modal. So having to do that, saving it and open it back up and do this stuff is a little annoying. It's a lot easier just to open the browser sometimes and just go play with the CSS there and then figure out what you got to do in the code.
[00:04:07]
Okay, so we have those components. Now we're gonna go back to our journal page, and we're gonna just gonna bring those in. So first thing I wanna do though is, I wanna make a grid. So I'm gonna make a grid here. I'm gonna call this grid. And I'm gonna say grid-cols.
[00:04:34]
I want this to be three columns, so grid-cols-3, and then I want them to have a gap of 4 which is about 16 pixels. So the first thing in the grid is always going to be the new entry card. It's always gonna be at the top. And then everything after that are just gonna be the entries.
[00:05:06]
So then I can just say, entries like this and .map, get myself an entry, and then just render out a EntryCard, And parse in the entry as a prop. And if you really just hate that red squigly, go ahead and give it a key of entry.id. Cool. I also prefer to do layout first before I do UI design because I feel like layout affects the UI design when you don't have a design.
[00:05:49]
Obviously, if you're at work and you already have a design, this doesn't matter. But if I'm designing, I'm just like, I mean, actually, I'll still probably do the layout first anyway. Because it's a lot easier to do the broad strokes than do the details, than having to do the details, bring it into the layout, just to find out, wait, well, that's not gonna work.
[00:06:09]
So I feel like you shouldn't sacrifice good layout for a design, the layout should come first, and then the details should come after it. That's come from somebody that knows nothing about design, so don't listen to me. All right. Cool, so we're really not gonna see anything here, right, cuz we don't have anything.
[00:06:35]
But let's start to make it look a little better. So I want these to kind of look like cards almost, so that's what we're gonna do. But the first thing that's truly bothering me is the fact that there's no padding on this. I just can't take it, so I'm gonna put a padding of 10 on all this.
[00:06:53]
There we go, so much better. And actually what I wanna do, I wanna put a title on this page. So I'm gonna wrap this div in another div Like this. That way I can put an H2 here that says turn or entries or journal. Something like that, give it a class name.
[00:07:24]
Let's try 3xl for the texts. Let's do a margin bottom of 8, see what that looks like. Yeah, there we go. But now I gotta bring that padding up to the root diff. There we go. So we get something like that.
>> Can I see your top level imports-
[00:07:51]
>> Absolutely.
>> For the two components we just made?
>> Yep. So I've used at which will give me root slash components slash the name.
>> I tried to destructure them both in one.
>> Yeah, so if you try to destructure them, that would be a named export.
[00:08:06]
So some people do that as a, there's really no wrong or right way. The only thing you have to do is you can't do that for pages. For pages, anything that's a special file in Next.js as a component has to be a default export. Otherwise, Next.js doesn't know what the name of the export is, so it can't import it.
[00:08:24]
And it's not gonna do some static analysis like TypeScript is gonna do and read your files to get the names of the exports. So it just has the default exports. Components, you can do whatever the hell you want. These aren't special files. You just got to make sure you import them the way that you exported them.
[00:08:39]
But pages and layouts and templates and things like that that are specially named have to have the specific exports. Okay, let's work on this card here. So I already have a bunch. And this is where I said, you don't remember all the CSS, so I'm actually just going to go see all the CSS I already made for this, cuz it's a lot and there's no way in hell I'm gonna remember all that or try to do it again, so, Here we go, actually, wait.
[00:09:21]
There we go. So it actually kind of looks like this. Worry about the on-click for now. I mean, I guess it's not that hard now that I'm looking at it. It just puts a cursor pointer on it, overflow hidden, rounded the corners, make the background white, adds a shadow, and then some padding, so I guess it's not too bad, But to copy that, this is what the repo is for.
[00:09:57]
It's in the new entry TSX file if you wanna copy that. You also don't need to make this look like exactly what I have. The style of this is not gonna affect the functionality, so. Okay, and then if you go check this out, just to verify it's there.
[00:10:17]
Now what's bothering me is that it's a white card on a white background and I can't stand it, so I'm gonna fix that. Inside of our page, I'm just going to give this a background of zinc dash Let's start with 500, and then add some opacity, modifier of 50 ,and let's just see what that looks like.
[00:10:45]
Nope, let's try 10. Absolutely not, let's lower that to 400. Much better, much better. Okay, and then we say give this a height of full. Nope, that still didn't work. It doesn't like that. And that's because this doesn't have a height of full on it. I'm not doing all that.
[00:11:16]
It's just gonna look like that for now. I gotta put a height full on this, and I gotta put a height full on this, and then it'll be good. That's just so much work. I guess I'll do it now that I mentioned it. [LAUGH] Let's just do it.
[00:11:30]
Height full on the thing in the template, and then We'll put one here too. We'll probably get some scroll too, I bet. A little bit of scroll, yeah. So to fix the scroll what you would have to do is just do some math, right? So you have to come here and say height is going to be calc 100 view height minus.
[00:12:04]
What did I put before the thing, 60. Or, I'm sorry, you want to do that here. You would still want a high fall on this and then you would say, this has a height of 100 View Height, or sorry, calc(100vh-60px). The reason we do that is because 100 View Height is the entire screen, but minus 60 pixels because we have a header up top that's 60 pixels.
[00:12:42]
And there's no margin between them, so we just calculate that. And that's why I chose to do things absolutely positioned, cuz I could just do math and do stuff. But if you were gonna make this relative or mobile responsive, you probably couldn't get away with this unless you had some crazy media queries.
[00:12:59]
So there we go, no more scroll. Everything's exactly the height and width that it needs to be. Okay, so we got this new entry. It literally does nothing when we click on it. Let's change that.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops