iT邦幫忙

2023 iThome 鐵人賽

DAY 16
0
自我挑戰組

模仿知名網站的外觀系列 第 16

【Day16】模仿知名網站的外觀 X(3) 完成首頁的外觀

  • 分享至 

  • xImage
  •  

我們繼續完成側邊欄,談到側邊欄就是一些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;

現在我們的畫面上多出了幾個按鈕和文字。

Untitled

增加登出按鈕,修改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按鈕。

Untitled

如果的視窗縮小的話,可以看到不同的按鈕,但功能是一樣的。

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;

目前的首頁長這樣。

Untitled

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;

專案目前的外觀。

Untitled

目前首頁的外觀大致完成了,可以看到側邊欄有登出的按鈕,接下來我們要開始編寫註冊以及登入的表單了。


上一篇
【Day15】模仿知名網站的外觀 X(2) 在側邊欄顯示logo
下一篇
【Day17】模仿知名網站的外觀 X(4) 登入表單
系列文
模仿知名網站的外觀30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言