我們繼續完成側邊欄,談到側邊欄就是一些icon加文字。
在layout資料夾下,新增SidebarItem.tsx,這是用來統一設定側邊欄的icon呈現的方式。
import { IconType } from "react-icons";
interface SidebarItemProps {
label: string;
href?: string;
icon: IconType;
onClick?: () => void;
}
const SidebarItem: React.FC<SidebarItemProps> = ({
label,
href,
icon: Icon,
onClick,
}) => {
return (
<div className="flex flex-row items-center">
<div className="relative rounded-full h-14 w-14 flex items-center justify-center p-4 hover:bg-slate-300 cursor-pointer lg:hidden">
<Icon size={28} color="white" />
</div>
<div className="relative hidden lg:flex items-center gap-4 p-4 rounded-full hover:bg-slate-300 hover:bg-opacity-10 cursor-pointer">
<Icon size={24} color="white" />
<p className="hidden lg:block text-white text-xl">{label}</p>
</div>
</div>
);
};
export default SidebarItem;
回到Sidebar.tsx,讓icon用SidebarItem裏面的方式顯示。
import { BsHouseFill, BsBellFill } from "react-icons/bs";
import { FaUser } from "react-icons/fa";
import SidebarLogo from "./SidebarLogo";
import SidebarItem from "./SidebarItem";
const Sidebar = () => {
const items = [
{
label: "Home",
href: "/",
icon: BsHouseFill,
},
{
label: "Notifications",
href: "/notifications",
icon: BsBellFill,
},
{
label: "Profile",
href: "/users/1",
icon: FaUser,
},
];
return (
<div className="col-span-1 h-full pr-4 md:pr-6">
<div className="flex flex-col items-start">
<div className="space-y-2 lg:w-[230px]">
<SidebarLogo />
{items.map((item) => (
<SidebarItem key={item.href} href={item.href} label={item.label} icon={item.icon} />
))}
</div>
</div>
</div>
);
};
export default Sidebar;
現在我們的畫面上多出了幾個按鈕和文字。
增加登出按鈕,修改Sidebar.tsx。
import { BsHouseFill, BsBellFill } from "react-icons/bs";
import { FaUser } from "react-icons/fa";
import { BiLogOut } from 'react-icons/bi';
import SidebarLogo from "./SidebarLogo";
import SidebarItem from "./SidebarItem";
const Sidebar = () => {
const items = [
{
label: "Home",
href: "/",
icon: BsHouseFill,
},
{
label: "Notifications",
href: "/notifications",
icon: BsBellFill,
},
{
label: "Profile",
href: "/users/1",
icon: FaUser,
},
];
return (
<div className="col-span-1 h-full pr-4 md:pr-6">
<div className="flex flex-col items-start">
<div className="space-y-2 lg:w-[230px]">
<SidebarLogo />
{items.map((item) => (
<SidebarItem key={item.href} href={item.href} label={item.label} icon={item.icon} />
))}
<SidebarItem onClick={() => {}} icon={BiLogOut} label="Logout" />
</div>
</div>
</div>
);
};
export default Sidebar;
接下來,我們要增加一個發佈推文的按鈕。
在layout資料夾下,新增SidebarTweetButton.tsx。
'use client'
import { useRouter } from "next/navigation"
import { FaFeather } from "react-icons/fa"
const SidebarTweetButton = () => {
const router = useRouter();
return (
<div onClick={() => router.push('/')}>
<div className="mt-6 lg:hidden rounded-full h-14 w-14 p-4 flex items-center justify-center bg-sky-500 hover:bg-opacity-80 transition cursor-pointer">
<FaFeather size={24} color="white" />
</div>
<div className="mt-6 hidden lg:block px-4 py-2 rounded-full bg-sky-500 hover:bg-opacity-90 cursor-pointer transition">
<p className="hidden lg:block text-center font-semibold text-white text-[20px]">
Tweet
</p>
</div>
</div>
)
}
export default SidebarTweetButton
修改Sidebar.tsx顯示Tweet按鈕。
import { BsHouseFill, BsBellFill } from "react-icons/bs";
import { FaUser } from "react-icons/fa";
import { BiLogOut } from 'react-icons/bi';
import SidebarLogo from "./SidebarLogo";
import SidebarItem from "./SidebarItem";
import SidebarTweetButton from "./SidebarTweetButton";
const Sidebar = () => {
const items = [
{
label: "Home",
href: "/",
icon: BsHouseFill,
},
{
label: "Notifications",
href: "/notifications",
icon: BsBellFill,
},
{
label: "Profile",
href: "/users/1",
icon: FaUser,
},
];
return (
<div className="col-span-1 h-full pr-4 md:pr-6">
<div className="flex flex-col items-start">
<div className="space-y-2 lg:w-[230px]">
<SidebarLogo />
{items.map((item) => (
<SidebarItem key={item.href} href={item.href} label={item.label} icon={item.icon} />
))}
<SidebarItem onClick={() => {}} icon={BiLogOut} label="Logout" />
<SidebarTweetButton />
</div>
</div>
</div>
);
};
export default Sidebar;
啟動專案就能看到藍色的Tweet按鈕。
如果的視窗縮小的話,可以看到不同的按鈕,但功能是一樣的。
X首頁的右方會出現一些推薦的內容,我們即將把這個打造出來。
在layout資料夾下,新增FollowBar.tsx,目前只會顯示Who to follow,未來連接資料庫後會顯示用戶名稱。
const FollowBar = () => {
return (
<div className="px-6 py-4 hidden lg:block">
<div className="bg-neutral-800 rounded-xl p-4">
<h2 className="text-white text-xl font-semibold">Who to follow</h2>
<div className="flex flex-col gap-6 mt-4">
</div>
</div>
</div>
)
}
export default FollowBar
修改Layout.tsx,顯示FollowBar。
import FollowBar from "./layout/FollowBar";
import Sidebar from "./layout/Sidebar";
interface LayoutProps {
children: React.ReactNode;
}
const Layout: React.FC<LayoutProps> = ({ children }) => {
return (
<div className="h-screen bg-black">
<div className="container h-full mx-auto xl:px-30 max-w-6xl">
<div className="grid grid-cols-4 h-full">
<div className="col-span-3 lg:col-span-2 border-x-[1px] border-neutral-800">
<Sidebar />
{children}
</div>
<FollowBar />
</div>
</div>
</div>
);
};
export default Layout;
目前的首頁長這樣。
X的首頁中間部分可以滾動,不論什麼時候點擊中上方的首頁(非側邊欄)就能立刻回到頂部,接下來我們要開始做這個。
在layout資料夾下,新增Header.tsx,點擊Home即可回到頂端。
'use client'
import { useRouter } from "next/navigation";
import { useCallback } from "react";
import { BiArrowBack } from "react-icons/bi";
interface HeaderProps{
label: string;
showBackArrow?: boolean;
}
const Header: React.FC<HeaderProps> = ({ label, showBackArrow}) => {
const router = useRouter();
const handleBack = useCallback(() => {
router.back();
}, [router]);
return (
<div className="border-b-[1px] border-neutral-800 p-5">
<div className="flex flex-row items-center gap-2">
{
showBackArrow && (
<BiArrowBack
onClick={handleBack}
color="white"
size={20}
className="cursor-pointer hover:opacity-70 transition"
/>
)
}
<h1 className="text-white text-xl font-semibold">{label}</h1>
</div>
</div>
)
}
export default Header
修改index.tsx,傳入參數給Header。
import Header from "../Components/layout/Header";
export default function Home() {
return (
<Header label="Home" />
)
}
修改Sidebar.tsx,顯示Header的內容。
import { BsHouseFill, BsBellFill } from "react-icons/bs";
import { FaUser } from "react-icons/fa";
import { BiLogOut } from 'react-icons/bi';
import SidebarLogo from "./SidebarLogo";
import SidebarItem from "./SidebarItem";
import SidebarTweetButton from "./SidebarTweetButton";
import Home from "@/pages/index";
const Sidebar = () => {
const items = [
{
label: "Home",
href: "/",
icon: BsHouseFill,
},
{
label: "Notifications",
href: "/notifications",
icon: BsBellFill,
},
{
label: "Profile",
href: "/users/1",
icon: FaUser,
},
];
return (
<div className="col-span-1 h-full pr-4 md:pr-6 flex">
<div className="flex flex-col items-start">
<div className="space-y-2 lg:w-[230px]">
<SidebarLogo />
{items.map((item) => (
<SidebarItem key={item.href} href={item.href} label={item.label} icon={item.icon} />
))}
<SidebarItem onClick={() => {}} icon={BiLogOut} label="Logout" />
<SidebarTweetButton />
</div>
</div>
<Home />
</div>
);
};
export default Sidebar;
專案目前的外觀。
目前首頁的外觀大致完成了,可以看到側邊欄有登出的按鈕,接下來我們要開始編寫註冊以及登入的表單了。