import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import {
Clock,
Hammer,
KeyRound,
LayoutPanelLeft,
Network,
Play,
Plug,
Server,
Settings,
User,
Zap,
} from "lucide-react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/dropdown-menu";
import type { SplitMode, TabType, ToolsTab } from "@/types/ui-types";
export type RailView =
| "hosts"
| "credentials"
| "quick-connect"
| ToolsTab
| "connections"
| "user-profile"
| "admin-settings";
type RailItem =
| {
kind?: undefined;
view: RailView;
icon: React.ReactNode;
title: string;
dot?: boolean;
}
| { kind: "tab"; tabType: TabType; icon: React.ReactNode; title: string }
| { kind: "separator" };
function buildRailButtons(
splitMode: SplitMode,
t: (key: string) => string,
connectionCount: number,
): RailItem[] {
return [
{ view: "hosts", icon: , title: t("nav.hosts") },
{
view: "credentials",
icon: ,
title: t("nav.credentials"),
},
{ kind: "separator" },
{
view: "connections",
icon: ,
title: t("nav.connections"),
},
{ kind: "separator" },
{
view: "quick-connect",
icon: ,
title: t("nav.quickConnect"),
},
{ kind: "separator" },
{ view: "ssh-tools", icon: , title: t("nav.sshTools") },
{ kind: "separator" },
{ view: "snippets", icon: , title: t("nav.snippets") },
{ kind: "separator" },
{ view: "history", icon: , title: t("nav.history") },
{ kind: "separator" },
{
view: "split-screen",
icon: ,
title: t("nav.splitScreen"),
dot: splitMode !== "none",
},
{ kind: "separator" },
{
kind: "tab",
tabType: "network_graph" as TabType,
icon: ,
title: t("nav.networkGraph"),
},
{ kind: "separator" },
];
}
const btnBase =
"relative flex items-center gap-2.5 h-7 rounded shrink-0 transition-colors";
const btnStyle = { margin: "0 4px", padding: "0 6px" };
export function AppRail({
railView,
sidebarOpen,
splitMode,
connectionCount,
username,
isAdmin,
profileDropdownOpen,
onProfileDropdownChange,
onRailClick,
onOpenTab,
onLogout,
}: {
railView: RailView;
sidebarOpen: boolean;
splitMode: SplitMode;
connectionCount: number;
username: string;
isAdmin: boolean;
profileDropdownOpen: boolean;
onProfileDropdownChange: (open: boolean) => void;
onRailClick: (view: RailView) => void;
onOpenTab?: (type: TabType) => void;
onLogout: () => void;
}) {
const { t } = useTranslation();
const [hovered, setHovered] = useState(false);
const [pinned, setPinned] = useState(
() => localStorage.getItem("pinAppRail") === "true",
);
useEffect(() => {
const handler = () =>
setPinned(localStorage.getItem("pinAppRail") === "true");
window.addEventListener("pinAppRailChanged", handler);
return () => window.removeEventListener("pinAppRailChanged", handler);
}, []);
const railExpanded = pinned || hovered || profileDropdownOpen;
const railButtons = buildRailButtons(splitMode, t, connectionCount);
return (
setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
{railButtons.map((item, i) =>
item.kind === "separator" ? (
) : item.kind === "tab" ? (
) : (
),
)}
{[
{
view: "user-profile" as RailView,
icon: ,
title: t("nav.userProfile"),
},
...(isAdmin
? [
{
view: "admin-settings" as RailView,
icon: ,
title: t("nav.admin"),
},
]
: []),
].map((item) => (
))}
Logout
);
}