In this task, we will add navigation functionality to the Posts app. We will add navigation links to view comments for a post and navigate back to the home page.
We will add a button to view comments for a post. When the button is clicked, the user will be navigated to the comments view for the post.
Open the web/src/components/post/post-actions.tsx
file and update the PostActions
component as follows:
import { Button } from "@/components/ui/button";
import { PostType } from "@/data/types";
import { Pencil2Icon, ChatBubbleIcon } from "@radix-ui/react-icons";
import DeletePostDialog from "./delete-post-dialog";
import { openPage } from "@nanostores/router"; // π Look here
import { $router } from "@/lib/router"; // π Look here
const PostActions = ({
post,
setIsEditing,
}: {
post: PostType;
setIsEditing: (flag: boolean) => void;
}) => {
// π Look here
const navigateToCommentsView = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
openPage($router, "post", { postId: post.id });
};
return (
<div className="flex justify-end">
<Button variant={"ghost"} size={"icon"} onClick={navigateToCommentsView}>
<ChatBubbleIcon className="w-4 h-4" />
</Button>
{/* π Look here */}
<Button
variant={"ghost"}
size={"icon"}
onClick={() => setIsEditing(true)}
>
<Pencil2Icon className="w-4 h-4" />
</Button>
<DeletePostDialog postId={post.id} />
</div>
);
};
export default PostActions;
Notice the navigateToCommentsView
function that uses the openPage
function to navigate to the comments view for the post. We pass the postId
as a parameter to the openPage
function to identify the post.
We will update the home button in the sidebar to navigate back to the home page when clicked. Open the web/src/components/layout/sidebar.tsx
file and update the Sidebar
component as follows:
import {
ChatBubbleIcon,
HomeIcon,
MagnifyingGlassIcon,
PlusCircledIcon,
} from "@radix-ui/react-icons";
import { Button } from "@/components/ui/button";
import { useStore } from "@nanostores/react";
import {
$showAddPost,
$showAddComment,
toggleAddPost,
toggleAddComment,
} from "@/lib/store";
import { $router } from "@/lib/router"; // π Look here
import { openPage } from "@nanostores/router"; // π Look here
const Sidebar = () => {
const page = useStore($router);
const showAddPost = useStore($showAddPost);
const showAddComment = useStore($showAddComment);
// Look here π
const navigateHome = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
openPage($router, "home");
};
if (!page) return null;
return (
<div className="flex flex-col items-end p-2 space-y-2">
<Button
aria-label={"Home"}
variant="ghost"
size="icon"
onClick={navigateHome} // π look here
>
<HomeIcon className="w-5 h-5" />
</Button>
<Button aria-label={"Search"} variant="ghost" size="icon">
<MagnifyingGlassIcon className="w-5 h-5" />
</Button>
{page.route === "home" && !showAddPost && (
<Button
aria-label={"Make a Post"}
variant="default"
size="icon"
onClick={() => {
toggleAddPost();
}}
>
<PlusCircledIcon className="w-5 h-5" />
</Button>
)}
{page.route === "post" && !showAddComment && (
<Button
aria-label={"Make a Comment"}
variant="default" // π look here
size="icon"
onClick={() => {
toggleAddComment();
}}
>
<ChatBubbleIcon className="w-5 h-5" /> {/* π look here */}
</Button>
)}
</div>
);
};
export default Sidebar;
Notice the navigateHome
function that uses the openPage
function to navigate back to the home page. We pass the "home"
route as a parameter to the openPage
function to navigate to the home page.
We also updated the βMake a Commentβ button to use the variant="default"
style to match the other buttons in the sidebar. The button now displays a chat bubble icon to indicate making a comment.
We will update the header component to display the appropriate title based on the current page. Open the web/src/components/layout/header.tsx
file and update the Header
component as follows:
import { Button } from "@/components/ui/button";
import { $router } from "@/lib/router"; // π Look here
import { useStore } from "@nanostores/react"; // π Look here
const Header = () => {
const page = useStore($router); // π Look here
if (!page) return null; // π Look here
if (page.route === "post") {
return (
<div className="flex justify-center gap-3 p-1 border-b">
<Button variant={"link"}>My Comments</Button>
<Button variant={"link"} disabled={true}>
All Comments
</Button>
</div>
);
}
// π Look here π
return (
<div className="flex justify-center gap-3 p-1 border-b">
<Button variant={"link"}>My Posts</Button>
<Button variant={"link"} disabled={true}>
All Posts
</Button>
</div>
);
};
export default Header;
Notice the page
store that we use to determine the current page. We display different titles based on the current page. If the current page is the βpostβ page, we display βMy Commentsβ and βAll Commentsβ buttons. If the current page is the βhomeβ page, we display βMy Postsβ and βAll Postsβ buttons.
You can now test the navigation functionality by clicking the buttons to view comments for a post and navigate back to the home page.
The navigation should work as expected, and you should see the appropriate title displayed in the header based on the current page.
In this task, we added navigation functionality to the Posts app. We added buttons to view comments for a post and navigate back to the home page. We updated the sidebar, header, and post actions components to enable navigation between different views in the app. You can now navigate between the home page and the comments view for a post.