diff --git a/src/client/components/Sidebar.tsx b/src/client/components/Sidebar.tsx index 9e0213b..453d6fa 100644 --- a/src/client/components/Sidebar.tsx +++ b/src/client/components/Sidebar.tsx @@ -9,8 +9,13 @@ import { User, X, } from "lucide-react"; -import { aiNavItem, getProjectNavGroups } from "@/client/navigation/items"; +import { + connectNavGroup, + getProjectNavGroups, +} from "@/client/navigation/items"; import { ProjectSwitcher } from "@/client/features/projects/ProjectSwitcher"; +import { ThemePreferenceMenuItems } from "@/client/components/ThemePreferenceMenuItems"; +import { closeDropdown } from "@/client/lib/dropdown"; import { signOutAndRedirect, useSession } from "@/lib/auth-client"; import { isHostedClientAuthMode } from "@/lib/auth-mode"; import { BILLING_ROUTE } from "@/shared/billing"; @@ -63,7 +68,10 @@ function SidebarNavLink({ } export function Sidebar({ projectId, onNavigate, onClose }: SidebarProps) { - const navGroups = projectId ? getProjectNavGroups(projectId) : []; + const navGroups = [ + ...(projectId ? getProjectNavGroups(projectId) : []), + connectNavGroup, + ]; return (
@@ -125,76 +133,81 @@ function SidebarFooter({ onNavigate }: { onNavigate?: () => void }) { const { data: session } = useSession(); const isHostedMode = isHostedClientAuthMode(); const email = session?.user?.email; - const { icon: aiIcon, label: aiLabel, ...aiLinkProps } = aiNavItem; + + const closeMenu = () => { + closeDropdown(); + onNavigate?.(); + }; return (
- - {isHostedMode ? ( - - ) : null} - {email ? ( - isHostedMode ? ( -
- -
    -
  • - -
  • -
-
- ) : ( -
+
+
- ) - ) : null} + +
    +
  • + + + Settings + +
  • + {isHostedMode ? ( +
  • + + + Billing + +
  • + ) : null} + + {isHostedMode ? ( + <> +
  • +
  • + +
  • + + ) : null} +
+
+ ) : ( + + )}
); } diff --git a/src/client/features/projects/ProjectSwitcher.tsx b/src/client/features/projects/ProjectSwitcher.tsx index 5412f5e..1da25d2 100644 --- a/src/client/features/projects/ProjectSwitcher.tsx +++ b/src/client/features/projects/ProjectSwitcher.tsx @@ -3,14 +3,9 @@ import { useQuery } from "@tanstack/react-query"; import { Check, ChevronsUpDown, FolderCog } from "lucide-react"; import { getProjects } from "@/serverFunctions/projects"; import { setLastProjectId } from "@/client/lib/active-project"; +import { closeDropdown } from "@/client/lib/dropdown"; import type { ProjectSummary } from "./types"; -function closeDropdown() { - if (document.activeElement instanceof HTMLElement) { - document.activeElement.blur(); - } -} - export function ProjectSwitcher({ activeProjectId, onCloseDrawer, diff --git a/src/client/lib/dropdown.ts b/src/client/lib/dropdown.ts new file mode 100644 index 0000000..0265f2e --- /dev/null +++ b/src/client/lib/dropdown.ts @@ -0,0 +1,7 @@ +// daisyUI dropdowns stay open until focus leaves, so blur the trigger to +// close the menu before navigating or acting on a selection. +export function closeDropdown() { + if (document.activeElement instanceof HTMLElement) { + document.activeElement.blur(); + } +} diff --git a/src/client/navigation/items.ts b/src/client/navigation/items.ts index b2ef682..8964635 100644 --- a/src/client/navigation/items.ts +++ b/src/client/navigation/items.ts @@ -60,12 +60,18 @@ const projectNavItems = [ }, ] as const; -export const aiNavItem = linkOptions({ +const aiNavItem = linkOptions({ to: "/ai" as const, label: "AI & MCP", icon: Bot, }); +// Always-visible sidebar group (not project-scoped, unlike the groups below). +export const connectNavGroup = { + label: "Connect", + items: [aiNavItem], +}; + function getProjectNavItems(projectId: string) { return linkOptions( projectNavItems.map((item) => ({