NextJs - Sidebar
In the previous tutorial, you learnt to create and run nextjs-app app. In this tutorial, you will be able to add sidebar menu to the app, use bootstrap to style the app., and use icons from react-icons library.
In real project, sidebar menu is an important component. You see most of the websites have sidebar menu. It allows visitors to navigate easily in the applications. Before adding sidebar menu to the app, you have to add bootstrap and react-icons libraries to the app by executing the command below from nextjs-app folder (root folder of the app created in the previous tutorial).
npm install bootstrap react-icons
In the nextjs-app folder, create components folder. In the components folder, create sidebar folder. In the sidebar folder, create three files: SideBar.js, SideBarData.js, and SubMenu.js,
SideBar.js
import React, {useState } from "react"; import Link from 'next/link'; import {FaBars} from "react-icons/fa"; import {AiOutlineClose} from "react-icons/ai"; import { SideBarData } from "./SideBarData"; import SubMenu from "./SubMenu"; import { IconContext } from "react-icons/lib"; import { FaSignInAlt,FaSignOutAlt } from "react-icons/fa" const nav_style = { background: "#0d6efd", height: "80px", display: "flex", justifyCcontent: "flex-start", alignItems: "center" }; const navitem_style = { color:"#ffffff", marginLeft: "auto", marginRight: "20px" }; const navicon_style = { marginLeft: "0.5rem", fontSize: "1.8rem", height: "70px", display: "flex", justifyContent: "flex-start", alignItems: "center", cursor: "pointer", }; const sidebarwrap_style = { width: "100%", }; const Sidebar = (props) => { const [sidebaropen, setSidebarOpen] = useState(false); const showSidebar = () => setSidebarOpen(!sidebaropen); const {token} = props; const sidebarnav_style = { background: "#0d6efd", width: "250px", height: "100vh", display: "flex", justifyContent: "center", position: "fixed", top: 0, left: (sidebaropen ? "0" : "-100%"), transition: "350ms", zIndex: 10, }; function isLoggedIn () { if(token!==null && token!==''){ return true; } else{ return false; } } const logged=isLoggedIn(); const links = [ { id: 2, path: logged? "/user/logout":"/user/login", text: logged?"Logout":"Login", icon: logged?<FaSignInAlt/> : <FaSignOutAlt/> }, ]; return ( <> <IconContext.Provider value={{ color: "#fff" }}> <div style={nav_style}> <div to="#" style={navicon_style}> <FaBars onClick={showSidebar} /> </div> <h3 style={{ textAlign: "center", marginLeft: "50px", color: "white" }} > Admin </h3> <div style={navitem_style}> <ul className="navbar-nav mr-auto list-group-horizontal"> {links.map(link => { return ( <li key={link.id} className="nav-item"> <Link href={{pathname: link.path}}> <a className="nav-link">{link.icon}{link.text}</a> </Link> </li> ) })} </ul> </div> </div> <div className="nav" style={sidebarnav_style}> <div style={sidebarwrap_style}> <div to="#" style={navicon_style}> <AiOutlineClose onClick={showSidebar} /> </div> {SideBarData.map((item, index) => { return <SubMenu item={item} key={index} />; })} </div> </div> </IconContext.Provider> </> ); }; export default Sidebar;
SideBarData.js
import React from "react"; import {FaPhone,FaEnvelopeOpenText,FaProductHunt,FaServicestack} from "react-icons/fa"; import {AiFillHome} from "react-icons/ai"; import {IoIosPaper,IoMdHelpCircle} from "react-icons/io"; import {RiArrowUpSFill,RiArrowDownSFill} from "react-icons/ri"; export const SideBarData = [ { title: "Users", path: "", icon: <FaServicestack />, iconClosed: <RiArrowDownSFill />, iconOpened: <RiArrowUpSFill />, subNav: [ { title: "User List", path: "/user/list", icon: <IoIosPaper />, cName: "sub-nav", }, { title: "User Roles", path: "/user/list", icon: <IoIosPaper />, cName: "sub-nav", }, ], }, { title: "Products", path: "/products", icon: <FaProductHunt />, }, { title: "Events", path: "", icon: <FaEnvelopeOpenText />, iconClosed: <RiArrowDownSFill />, iconOpened: <RiArrowUpSFill />, subNav: [ { title: "Event 1", path: "/events/events1", icon: <IoIosPaper />, }, { title: "Event 2", path: "/events/events2", icon: <IoIosPaper />, }, ], }, { title: "About Us", path: "/about-us", icon: <AiFillHome />, }, { title: "Contact", path: "/contact", icon: <FaPhone />, }, { title: "Support", path: "/support", icon: <IoMdHelpCircle />, }, ];
SubMenu.js
import React, { useState } from "react"; import Link from 'next/link'; const sidelink = { display: "flex", color: "#e1e9fc", justifyContent: "space-between", alignItems: "center", padding: "20px", listStyle: "none", height: "60px", textDecoration: "none", fontSize: "18px", hover :{ background: "#252831", borderLeft: "4px solid green", cursor: "pointer", } } const SidebarLabel = { marginLeft: "16px", } const DropdownLink = { background: "#252831", height: "60px", paddingLeft: "3rem", display: "flex", alignItems: "center", textDecoration: "none", color: "#f5f5f5", fontSize: "18px", hover: { background: "green", cursor: "pointer" } } const SubMenu = ({ item }) => { const [subnav, setSubnav] = useState(false); const showSubnav = () => setSubnav(!subnav); return ( <> <Link href={{pathname:item.path}}> <a style={sidelink} onClick={item.subNav && showSubnav}> <div> {item.icon} <span style={{marginLeft: "10px"}}>{item.title}</span> </div> <div> {item.subNav && subnav ? item.iconOpened : item.subNav ? item.iconClosed : null} </div> </a> </Link> {subnav && item.subNav.map((item, index) => { return ( <Link href={{pathname: item.path}}> <a key={index} style={DropdownLink} > {item.icon} <span style={SidebarLabel}>{item.title}</span> </a> </Link> ); })} </> ); }; export default SubMenu;
In the components folder, create layout.js and layout.module.css files.
layout.js
import Head from 'next/head'; import styles from './layout.module.css'; import Sidebar from './sidebar/SideBar'; export const siteTitle = 'Next.js Sample Website'; export default function Layout( { children, title = 'Next.js sample', description = 'Next.js sample project with sequelize & mysql database', keywords = 'Next.js, Sequelize, JWT, Json Web Tokens, Authentication, Application', token = '', }) { return ( <div className={styles.container}> <Head> <link rel="icon" href="/favicon.ico" /> <meta charSet="utf-8" /> <title>{title}</title> <link rel="icon" href="/favicon.ico" /> <meta name="robots" content="index, follow" /> <meta name="description" content={description} /> <meta name="keywords" content={keywords} /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> </Head> <Sidebar token={token}/> <header className={styles.header}> Welcome! </header> <main>{children}</main> </div> ); }
layout.module.css
.container { width: 100%; padding: 0 0rem; margin: 0rem auto 3rem; } .header { display: flex; flex-direction: column; align-items: center; }
Modify the index.js file in pages folder to add Layout component:
import Layout from '../components/layout'; export default function Home() { return ( <Layout title='Home Page' /> ) }
Then executing the following command to run the app.
npm run dev
Comments
Post a Comment