Sidebar - Copy this React, Tailwind Component to your project
'use client' import { useState } from "react"; import { IoBusinessOutline, IoCodeSlashOutline, IoPersonOutline, IoLayersOutline, IoChevronDownOutline, IoChevronUpOutline, IoSettingsOutline, IoAnalyticsOutline, IoDocumentTextOutline, IoBuildOutline, IoExtensionPuzzleOutline, IoTerminalOutline, IoNotificationsOutline, IoKeyOutline } from "react-icons/io5"; interface Subcategory { name: string; icon: JSX.Element; } interface Category { name: string; icon: JSX.Element; subcategories: Subcategory[]; } const Index: React.FC = () => { const [isSidebarOpen, setIsSidebarOpen] = useState(true); const [expandedCategories, setExpandedCategories] = useState<string[]>([]); const [activeItem, setActiveItem] = useState<string>(""); const categories: Category[] = [ { name: "Government Bonds", icon: <IoBusinessOutline className="w-5 h-5" />, subcategories: [ { name: "buy", icon: <IoAnalyticsOutline className="w-4 h-4" /> }, { name: "sell", icon: <IoSettingsOutline className="w-4 h-4" /> }, ] }, { name: "Government Securities", icon: <IoCodeSlashOutline className="w-5 h-5" />, subcategories: [ { name: "buy", icon: <IoBuildOutline className="w-4 h-4" /> }, { name: "sell", icon: <IoExtensionPuzzleOutline className="w-4 h-4" /> }, ] }, { name: "Others", icon: <IoPersonOutline className="w-5 h-5" />, subcategories: [ { name: "Auction timelines", icon: <IoNotificationsOutline className="w-4 h-4" /> }, { name: "Security", icon: <IoKeyOutline className="w-4 h-4" /> } ] }, ]; const toggleSidebar = () => setIsSidebarOpen(!isSidebarOpen); const toggleCategory = (categoryName: string) => { setExpandedCategories(prev => prev.includes(categoryName) ? prev.filter(name => name !== categoryName) : [...prev, categoryName] ); }; const handleItemClick = (itemName: string) => { setActiveItem(itemName); }; return ( <div className="relative"> <button onClick={toggleSidebar} className="lg:hidden fixed top-4 left-4 z-50 p-2 bg-gray-800 text-white rounded-md" aria-label="Toggle sidebar" > ☰ </button> <aside className={`${isSidebarOpen ? "translate-x-0" : "-translate-x-full"} fixed top-0 left-0 h-full w-64 bg-white dark:bg-gray-800 shadow-lg transform transition-transform duration-300 ease-in-out z-40 lg:translate-x-0`} aria-label="Sidebar navigation" > <div className="p-4"> <div className="flex items-center justify-center mb-8"> <h1 className="text-xl font-bold text-gray-800 dark:text-white">Dashboard</h1> </div> <nav> <ul className="space-y-2"> {categories.map((category) => ( <li key={category.name}> <button onClick={() => toggleCategory(category.name)} className={`w-full flex items-center justify-between p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors ${expandedCategories.includes(category.name) ? "bg-gray-100 dark:bg-gray-700" : ""}`} aria-expanded={expandedCategories.includes(category.name)} > <div className="flex items-center space-x-3"> {category.icon} <span>{category.name}</span> </div> {category.subcategories.length > 0 && ( expandedCategories.includes(category.name) ? <IoChevronUpOutline className="w-4 h-4" /> : <IoChevronDownOutline className="w-4 h-4" /> )} </button> {expandedCategories.includes(category.name) && category.subcategories.length > 0 && ( <ul className="mt-2 ml-6 space-y-2"> {category.subcategories.map((subcategory) => ( <li key={subcategory.name}> <button onClick={() => handleItemClick(subcategory.name)} className={`w-full flex items-center space-x-2 p-2 text-sm text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors ${activeItem === subcategory.name ? "bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300" : ""}`} aria-current={activeItem === subcategory.name ? "page" : undefined} > {subcategory.icon} <span>{subcategory.name}</span> </button> </li> ))} </ul> )} </li> ))} </ul> </nav> </div> </aside> </div> ); }; export default Index;
