我們上一次完成了Story區塊,但是只能透過網址進入,這一次我們要設定能從首頁上進入Story。
修改StoryCircle.jsx,增加點擊跳到Story的功能。
import React from "react";
import { useNavigate } from "react-router-dom";
const StoryCircle = () => {
const navigate = useNavigate();
const handleNavigate = () => {
navigate("/story");
};
return (
<div
onClick={handleNavigate}
className="cursor-pointer flex flex-col items-center"
>
<img
className="w-16 h-16 rounded-full"
src="https://images.pexels.com/photos/7106845/pexels-photo-7106845.jpeg?auto=compress"
alt=""
/>
<p>username</p>
</div>
);
};
export default StoryCircle;
接著,我們要完成搜尋區塊。
在Components資料夾底下,新增SearchComponents資料夾。
在SearchComponents資料夾下,新增SearchComponents.jsx、SearchComponents.css。
SearchComponents.jsx的內容如下:
import React from "react";
import "./SearchComponents.css";
const SearchComponents = () => {
return (
<div className="searchContainer">
<div>
<h1>Search</h1>
<input className="searchInput" type="text" placeholder="Search" />
</div>
</div>
);
};
export default SearchComponents;
有一個大標題和一個輸入區塊。
SearchComponents.css
.searchContainer{
padding: 1rem 0rem;
border: 1px solid rgb(222, 222, 222);
box-shadow: 0 1px 2px rgb(2, 2, 2);
width: 300px;
height: 100vh;
z-index: 10;
}
.searchInput{
border: none;
border-radius: 4px;
background-color: rgb(242, 242, 242);
padding: 5px 10px;
font-size: 12px;
width: 100%;
outline: none;
margin-left: 10px;
}
來到Sidebar.jsx,設定按下Search後顯示搜尋區塊。
import React, { useState } from "react";
import { IoReorderThreeOutline } from "react-icons/io5";
import { menu } from "./SidebarMenu";
import { useNavigate } from "react-router-dom";
import { useDisclosure } from "@chakra-ui/react";
import CreatePostModal from "../Post/CreatePostModal";
import SearchComponents from "../SearchComponents/SearchComponents";
const Sidebar = () => {
const [activeTab, setActiveTab] = useState([]);
const navigate = useNavigate();
const { isOpen, onOpen, onClose } = useDisclosure();
const [isSearchVisible, setIsSearchVisible] = useState(false);
const handleTabClick = (title) => {
setActiveTab(title);
//點擊Profile按鈕時,跳到/username
if (title === "Profile") {
navigate("/username");
}
//點擊Home按鈕時,跳到/
else if (title === "Home") {
navigate("/");
}
//點擊Create按鈕時,跳出CreateModal視窗
else if (title === "Create") {
onOpen();
}
if(title === "Search"){
setIsSearchVisible(true)
}
else{
setIsSearchVisible(false)
}
};
return (
<div className="sticky top-0 h-[100vh] flex">
<div className="flex flex-col justify-between h-full px-10">
<div>
<div className="pt-10">
<img className="w-40" src="Instagram_logo.svg.png" alt="" />
</div>
<div className="mt-10">
{menu.map((item) => (
<div
onClick={() => handleTabClick(item.title)}
className="flex items-center cursor-pointer mb-5 text-lg"
>
{activeTab === item.title ? item.activeIcon : item.icon}
<p
className={`${
activeTab === item.title ? "font-bold" : "font-semibold"
}`}
>
{item.title}
</p>
</div>
))}
</div>
</div>
<div className="flex items-center cursor-pointer pb-10">
<IoReorderThreeOutline />
<p className="ml-5">More</p>
</div>
</div>
<CreatePostModal onClose={onClose} isOpen={isOpen} />
{isSearchVisible && <SearchComponents />}
</div>
);
};
export default Sidebar;
被兩條黑色的邊界線包圍的就是我們的搜尋區塊。
當搜尋區塊顯示時,左側的導航列的文字應該會消失,修改Sidebar.jsx符合這個規則。
import React, { useState } from "react";
import { IoReorderThreeOutline } from "react-icons/io5";
import { menu } from "./SidebarMenu";
import { useNavigate } from "react-router-dom";
import { useDisclosure } from "@chakra-ui/react";
import CreatePostModal from "../Post/CreatePostModal";
import SearchComponents from "../SearchComponents/SearchComponents";
const Sidebar = () => {
const [activeTab, setActiveTab] = useState([]);
const navigate = useNavigate();
const { isOpen, onOpen, onClose } = useDisclosure();
const [isSearchVisible, setIsSearchVisible] = useState(false);
const handleTabClick = (title) => {
setActiveTab(title);
//點擊Profile按鈕時,跳到/username
if (title === "Profile") {
navigate("/username");
}
//點擊Home按鈕時,跳到/
else if (title === "Home") {
navigate("/");
}
//點擊Create按鈕時,跳出CreateModal視窗
else if (title === "Create") {
onOpen();
}
if (title === "Search") {
setIsSearchVisible(true);
} else {
setIsSearchVisible(false);
}
};
return (
<div className="sticky top-0 h-[100vh] flex">
<div className="flex flex-col justify-between h-full px-10">
<div>
<div className="pt-10">
<img className="w-40" src="Instagram_logo.svg.png" alt="" />
</div>
<div className="mt-10">
{menu.map((item) => (
<div
onClick={() => handleTabClick(item.title)}
className="flex items-center cursor-pointer mb-5 text-lg"
>
{activeTab === item.title ? item.activeIcon : item.icon}
{!(activeTab === "Search") && (
<p
className={`${
activeTab === item.title ? "font-bold" : "font-semibold"
}`}
>
{item.title}
</p>
)}
</div>
))}
</div>
</div>
<div className="flex items-center cursor-pointer pb-10">
<IoReorderThreeOutline />
{!(activeTab === "Search") && <p className="ml-5">More</p>}
</div>
</div>
<CreatePostModal onClose={onClose} isOpen={isOpen} />
{isSearchVisible && <SearchComponents />}
</div>
);
};
export default Sidebar;
修改排版和當搜尋欄開啟時Instagram logo應該要消失。
import React, { useState } from "react";
import { IoReorderThreeOutline } from "react-icons/io5";
import { menu } from "./SidebarMenu";
import { useNavigate } from "react-router-dom";
import { useDisclosure } from "@chakra-ui/react";
import CreatePostModal from "../Post/CreatePostModal";
import SearchComponents from "../SearchComponents/SearchComponents";
const Sidebar = () => {
const [activeTab, setActiveTab] = useState([]);
const navigate = useNavigate();
const { isOpen, onOpen, onClose } = useDisclosure();
const [isSearchVisible, setIsSearchVisible] = useState(false);
const handleTabClick = (title) => {
setActiveTab(title);
//點擊Profile按鈕時,跳到/username
if (title === "Profile") {
navigate("/username");
}
//點擊Home按鈕時,跳到/
else if (title === "Home") {
navigate("/");
}
//點擊Create按鈕時,跳出CreateModal視窗
else if (title === "Create") {
onOpen();
}
if (title === "Search") {
setIsSearchVisible(true);
} else {
setIsSearchVisible(false);
}
};
return (
<div className="sticky top-0 h-[100vh] flex">
<div
className={`flex flex-col justify-between h-full ${
activeTab === "Search" ? "px-2" : "px-10"
}`}
>
<div>
{!(activeTab === "Search") && (
<div className="pt-10">
<img className="w-40" src="Instagram_logo.svg.png" alt="" />
</div>
)}
<div className="mt-10">
{menu.map((item) => (
<div
onClick={() => handleTabClick(item.title)}
className="flex items-center cursor-pointer mb-5 text-lg"
>
{activeTab === item.title ? item.activeIcon : item.icon}
{!(activeTab === "Search") && (
<p
className={`${
activeTab === item.title ? "font-bold" : "font-semibold"
}`}
>
{item.title}
</p>
)}
</div>
))}
</div>
</div>
<div className="flex items-center cursor-pointer pb-10">
<IoReorderThreeOutline />
{!(activeTab === "Search") && <p className="ml-5">More</p>}
</div>
</div>
<CreatePostModal onClose={onClose} isOpen={isOpen} />
{isSearchVisible && <SearchComponents />}
</div>
);
};
export default Sidebar;
修改SearchComponents.css,讓搜尋輸入的區塊不要超出搜尋欄。
.searchContainer{
padding: 1rem 0rem;
border: 1px solid rgb(222, 222, 222);
box-shadow: 0 1px 2px rgb(2, 2, 2);
width: 300px;
height: 100vh;
z-index: 10;
}
.searchInput{
border: none;
border-radius: 4px;
background-color: rgb(242, 242, 242);
padding: 5px 10px;
font-size: 12px;
width: 90%;
outline: none;
margin-left: 10px;
}
調整一下排版,SearchComponents.jsx。
import React from "react";
import "./SearchComponents.css";
const SearchComponents = () => {
return (
<div className="searchContainer">
<div className="px-3 pb-5">
<h1 className="text-xl pb-5">Search</h1>
<input className="searchInput" type="text" placeholder="Search" />
</div>
<hr />
<div>
</div>
</div>
);
};
export default SearchComponents;
我們的搜尋欄還缺了一些東西,就是搜尋結果。
在SearchComponents資料夾下,新增SearchCard.jsx。
import React from "react";
const SearchCard = () => {
return (
<div className="py-2 cursor-pointer">
<div className="flex items-center">
<img
className="w-10 h-10 rounded-full"
src="https://images.pexels.com/photos/15784572/pexels-photo-15784572.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
alt=""
/>
<div className="ml-3">
<p>FullName</p>
<p className="opacity-70">username</p>
</div>
</div>
</div>
);
};
export default SearchCard;
在SearchComponents.jsx,顯示SearchCard的內容。
import React from "react";
import "./SearchComponents.css";
import SearchCard from "./SearchCard";
const SearchComponents = () => {
return (
<div className="searchContainer">
<div className="px-3 pb-5">
<h1 className="text-xl pb-5">Search</h1>
<input className="searchInput" type="text" placeholder="Search" />
</div>
<hr />
<div className="px-3 pt-5">
{[1, 1, 1, 1, 1, 1].map((item) => <SearchCard />)}
</div>
</div>
);
};
export default SearchComponents;
我們模仿Instagram的部分就到此結束了,雖然還有Explore、Reels、Message、Notification沒完成,不過需要的技術我們已經使用過了,Explore使用Profile區塊的Post程式碼再加上一些CSS就能完成了。Reels使用HomeRight的SuggestionCard的程式碼在加上一些排版就能做出雛形。Message、Notification這種會出現側邊欄的東西,我們已經在做SearchComponents時用過了。
下回我們會模擬另外一個知名的網站。