e8d5b16acc
- Add mobile viewport detection to ToolWorkshopPage - Implement mobile list view with MobileListView component - Implement mobile detail view with MobileDetailView component - Implement mobile edit view with MobileEditView component - Add MobileFAB for creating new tool types - Fix IconName type issues in mobile components - TypeScript check passes, build succeeds
88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import { useState } from "react";
|
|
import { NavLink, useLocation } from "react-router-dom";
|
|
import { Icon } from "./icon";
|
|
import { ToolsBottomSheet } from "./tools-bottom-sheet";
|
|
import type { IconName } from "../utils/icons";
|
|
|
|
interface MobileNavProps {
|
|
sessionCount?: number;
|
|
}
|
|
|
|
interface NavItem {
|
|
to: string;
|
|
label: string;
|
|
icon: IconName;
|
|
isGroup?: boolean;
|
|
}
|
|
|
|
const MOBILE_NAV_ITEMS: NavItem[] = [
|
|
{ to: "/", label: "Home", icon: "dashboard" },
|
|
{ to: "/projects", label: "Projects", icon: "projects" },
|
|
{ to: "/sessions", label: "Sessions", icon: "terminal" },
|
|
{ to: "/tools", label: "Tools", icon: "settings", isGroup: true },
|
|
{ to: "/settings", label: "Settings", icon: "settings" },
|
|
];
|
|
|
|
export const MobileNav: React.FC<MobileNavProps> = ({ sessionCount }) => {
|
|
const location = useLocation();
|
|
const [toolsSheetOpen, setToolsSheetOpen] = useState(false);
|
|
|
|
const isToolsActive =
|
|
location.pathname === "/tool-workshop" ||
|
|
location.pathname === "/config-profiles";
|
|
|
|
const handleNavClick = (item: NavItem) => {
|
|
if (item.isGroup) {
|
|
setToolsSheetOpen(true);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<nav className="mobile-nav" role="navigation" aria-label="Mobile navigation">
|
|
{MOBILE_NAV_ITEMS.map((item) => {
|
|
if (item.isGroup) {
|
|
return (
|
|
<button
|
|
key={item.to}
|
|
className={`mobile-nav-item ${isToolsActive ? "active" : ""}`}
|
|
onClick={() => handleNavClick(item)}
|
|
type="button"
|
|
>
|
|
<div className="mobile-nav-icon-wrapper">
|
|
<Icon name={item.icon} size="md" />
|
|
</div>
|
|
<span className="mobile-nav-label">{item.label}</span>
|
|
</button>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`mobile-nav-item ${isActive ? "active" : ""}`
|
|
}
|
|
end={item.to === "/"}
|
|
>
|
|
<div className="mobile-nav-icon-wrapper">
|
|
<Icon name={item.icon} size="md" />
|
|
{item.to === "/sessions" && sessionCount ? (
|
|
<span className="mobile-nav-badge">{sessionCount}</span>
|
|
) : null}
|
|
</div>
|
|
<span className="mobile-nav-label">{item.label}</span>
|
|
</NavLink>
|
|
);
|
|
})}
|
|
</nav>
|
|
|
|
<ToolsBottomSheet
|
|
isOpen={toolsSheetOpen}
|
|
onClose={() => setToolsSheetOpen(false)}
|
|
/>
|
|
</>
|
|
);
|
|
};
|