first commit
This commit is contained in:
94
components/Sidebar.tsx
Normal file
94
components/Sidebar.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { ThemeToggle } from './ThemeToggle';
|
||||
|
||||
interface SidebarItem {
|
||||
title: string;
|
||||
slug: string;
|
||||
children?: SidebarItem[];
|
||||
}
|
||||
|
||||
interface SidebarProps {
|
||||
sidebarData: SidebarItem[];
|
||||
currentSlug?: string;
|
||||
}
|
||||
|
||||
export function Sidebar({ sidebarData, currentSlug }: SidebarProps) {
|
||||
// Use a map to track open state of each section (by slug)
|
||||
const [openSections, setOpenSections] = useState<Record<string, boolean>>({});
|
||||
|
||||
useEffect(() => {
|
||||
// Automatically open the section that contains the current slug
|
||||
if (currentSlug) {
|
||||
const parentSection = sidebarData.find(item =>
|
||||
item.children?.some(child => child.slug === currentSlug)
|
||||
);
|
||||
if (parentSection) {
|
||||
setOpenSections(prev => ({ ...prev, [parentSection.slug]: true }));
|
||||
}
|
||||
}
|
||||
}, [currentSlug, sidebarData]);
|
||||
|
||||
const toggleSection = (slug: string) => {
|
||||
setOpenSections(prev => ({ ...prev, [slug]: !prev[slug] }));
|
||||
};
|
||||
|
||||
return (
|
||||
<aside className="sidebar">
|
||||
<div className="sidebar-header">
|
||||
<Link href="/" className="sidebar-logo">
|
||||
<div className="sidebar-logo-icon">🦞</div>
|
||||
<div className="sidebar-logo-text">
|
||||
<span className="sidebar-logo-title">OpenClaw</span>
|
||||
<span className="sidebar-logo-subtitle">中文文档</span>
|
||||
</div>
|
||||
</Link>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
<nav className="sidebar-nav">
|
||||
{sidebarData.map(item => {
|
||||
if (item.children && item.children.length > 0) {
|
||||
const isOpen = !!openSections[item.slug];
|
||||
const hasActiveChild = item.children.some(c => c.slug === currentSlug);
|
||||
|
||||
return (
|
||||
<div key={item.slug} className="sidebar-section">
|
||||
<div
|
||||
className={`sidebar-section-title ${hasActiveChild ? 'active' : ''}`}
|
||||
onClick={() => toggleSection(item.slug)}
|
||||
>
|
||||
{item.title}
|
||||
<span className={`sidebar-section-arrow ${isOpen ? 'open' : ''}`}>▶</span>
|
||||
</div>
|
||||
{isOpen && (
|
||||
<div className="sidebar-section-children">
|
||||
{item.children.map(child => (
|
||||
<Link
|
||||
key={child.slug}
|
||||
href={child.slug}
|
||||
className={`sidebar-link ${child.slug === currentSlug ? 'active' : ''}`}
|
||||
>
|
||||
{child.title}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Link
|
||||
key={item.slug}
|
||||
href={item.slug}
|
||||
className={`sidebar-root-link ${item.slug === currentSlug ? 'active' : ''}`}
|
||||
>
|
||||
{item.title}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user