feat(App): 添加导航菜单折叠功能和样式优化
- 实现响应式导航菜单,根据屏幕尺寸自动调整显示项数量 - 添加移动端友好的折叠菜单和汉堡按钮 - 统一应用内所有按钮和容器的圆角样式为8px - 重构导航配置为数据驱动模式,便于后续扩展 - 优化小屏幕设备上的导航显示和交互体验 - 添加菜单展开收起的动画过渡效果 - 修复超小屏幕下的边框遮挡问题
This commit is contained in:
+86
-12
@@ -1,29 +1,103 @@
|
||||
import {HashRouter as Router, Routes, Route, NavLink} from 'react-router-dom';
|
||||
import {useState, useEffect} from 'react';
|
||||
import TimestampPage from './pages/TimestampPage';
|
||||
import ElectronicWoodenFishPage from "./pages/ElectronicWoodenFishPage";
|
||||
import TodoListPage from "./pages/TodoListPage";
|
||||
import './App.css';
|
||||
|
||||
// 导航项配置数组,便于后续添加
|
||||
// 为了测试折叠功能,我们添加更多导航项
|
||||
const navItems = [
|
||||
{path: '/', label: 'Timestamp', element: <TimestampPage/>},
|
||||
{path: '/dzmy', label: '电子木鱼', element: <ElectronicWoodenFishPage/>},
|
||||
{path: '/todo', label: '待办', element: <TodoListPage/>},
|
||||
];
|
||||
|
||||
function App() {
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
const [visibleItems, setVisibleItems] = useState(navItems.length);
|
||||
|
||||
// 检测屏幕尺寸变化
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
const width = window.innerWidth;
|
||||
setIsMobile(width < 768);
|
||||
|
||||
// 根据屏幕宽度决定显示多少个导航项
|
||||
if (width >= 768) {
|
||||
setVisibleItems(navItems.length); // 大屏幕显示所有
|
||||
} else if (width >= 480) {
|
||||
// 中等屏幕:如果导航项超过3个,显示3个,否则显示全部
|
||||
setVisibleItems(Math.min(3, navItems.length));
|
||||
} else {
|
||||
// 小屏幕:如果导航项超过2个,显示2个,否则显示全部
|
||||
setVisibleItems(Math.min(2, navItems.length));
|
||||
}
|
||||
};
|
||||
|
||||
handleResize(); // 初始调用
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
// 计算哪些导航项应该显示,哪些应该折叠
|
||||
const visibleNavItems = navItems.slice(0, visibleItems);
|
||||
const collapsedNavItems = navItems.slice(visibleItems);
|
||||
|
||||
return (<Router>
|
||||
|
||||
<div className="app">
|
||||
<nav className="nav">
|
||||
<ul className="nav-list">
|
||||
<li><NavLink to="/" className={({isActive}) => isActive ? "nav-link active" : "nav-link"}>Timestamp</NavLink>
|
||||
</li>
|
||||
<li><NavLink to="/dzmy"
|
||||
className={({isActive}) => isActive ? "nav-link active" : "nav-link"}>电子木鱼</NavLink></li>
|
||||
<li><NavLink to="/todo" className={({isActive}) => isActive ? "nav-link active" : "nav-link"}>待办</NavLink>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="nav-content">
|
||||
<ul className={`nav-list ${isMenuOpen ? 'open' : ''}`}>
|
||||
{visibleNavItems.map((item) => (
|
||||
<li key={item.path}>
|
||||
<NavLink
|
||||
to={item.path}
|
||||
className={({isActive}) => isActive ? "nav-link active" : "nav-link"}
|
||||
onClick={() => isMobile && setIsMenuOpen(false)}
|
||||
>
|
||||
{item.label}
|
||||
</NavLink>
|
||||
</li>
|
||||
))}
|
||||
|
||||
{/* 折叠的导航项 */}
|
||||
{collapsedNavItems.length > 0 && (
|
||||
<li className="nav-collapse-item">
|
||||
<div className={`nav-collapse-content ${isMenuOpen ? 'show' : ''}`}>
|
||||
{isMenuOpen && collapsedNavItems.map((item) => (
|
||||
<NavLink
|
||||
key={item.path}
|
||||
to={item.path}
|
||||
className={({isActive}) => isActive ? "nav-link active" : "nav-link"}
|
||||
onClick={() => setIsMenuOpen(false)}
|
||||
>
|
||||
{item.label}
|
||||
</NavLink>
|
||||
))}
|
||||
</div>
|
||||
<button
|
||||
className="nav-toggle"
|
||||
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||
aria-label={isMenuOpen ? "收起菜单" : "展开菜单"}
|
||||
>
|
||||
<span className="nav-toggle-icon">{isMenuOpen ? '×' : '☰'}</span>
|
||||
{collapsedNavItems.length > 0 && !isMenuOpen && (
|
||||
<span className="nav-collapse-count">+{collapsedNavItems.length}</span>
|
||||
)}
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<Routes>
|
||||
<Route path="/" element={<TimestampPage/>}/>
|
||||
<Route path="/timestamp" element={<TimestampPage/>}/>
|
||||
<Route path="/dzmy" element={<ElectronicWoodenFishPage/>}/>
|
||||
<Route path="/todo" element={<TodoListPage/>}/>
|
||||
{navItems.map((item) => (
|
||||
<Route key={item.path} path={item.path} element={item.element}/>
|
||||
))}
|
||||
</Routes>
|
||||
</div>
|
||||
</Router>);
|
||||
|
||||
Reference in New Issue
Block a user