2025-11-29 15:39:57 +05:30
|
|
|
"use client";
|
|
|
|
|
|
2026-03-03 16:32:33 +05:30
|
|
|
import { Menu } from "lucide-react";
|
2026-04-11 15:32:16 +05:30
|
|
|
import Link from "next/link";
|
2025-11-29 15:39:57 +05:30
|
|
|
import { usePathname } from "next/navigation";
|
2026-04-11 16:29:19 +05:30
|
|
|
import posthog from "posthog-js";
|
2025-11-29 15:39:57 +05:30
|
|
|
import React, { ReactNode } from "react";
|
|
|
|
|
|
2026-03-03 16:32:33 +05:30
|
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
|
import { SidebarInset, SidebarProvider, useSidebar } from "@/components/ui/sidebar";
|
2026-04-11 21:10:54 +05:30
|
|
|
import { PostHogEvent } from "@/constants/posthog-events";
|
2025-11-29 15:39:57 +05:30
|
|
|
|
|
|
|
|
import { AppSidebar } from "./AppSidebar";
|
2026-04-11 15:32:16 +05:30
|
|
|
import { GitHubStarBadge } from "./GitHubStarBadge";
|
2025-11-29 15:39:57 +05:30
|
|
|
|
2026-04-11 15:32:16 +05:30
|
|
|
function AppHeader() {
|
2026-03-03 16:32:33 +05:30
|
|
|
const { toggleSidebar } = useSidebar();
|
|
|
|
|
|
|
|
|
|
return (
|
2026-04-11 15:32:16 +05:30
|
|
|
<header className="sticky top-0 z-50 flex items-center justify-between border-b bg-background px-4 py-2">
|
|
|
|
|
<div className="flex items-center gap-3">
|
|
|
|
|
<Button variant="ghost" size="icon" onClick={toggleSidebar} aria-label="Open menu" className="md:hidden">
|
|
|
|
|
<Menu className="h-5 w-5" />
|
|
|
|
|
</Button>
|
|
|
|
|
<Link href="/" className="text-lg font-bold md:hidden">Dograh</Link>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex items-center gap-3">
|
|
|
|
|
<Button variant="ghost" size="sm" asChild>
|
|
|
|
|
<a
|
2026-04-19 15:19:01 +05:30
|
|
|
href="https://join.slack.com/t/dograh-community/shared_invite/zt-3czr47sw5-MSg1J0kJ7IMPOCHF~03auQ"
|
2026-04-11 15:32:16 +05:30
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
2026-04-11 16:29:19 +05:30
|
|
|
onClick={() => posthog.capture(PostHogEvent.SLACK_COMMUNITY_CLICKED, { source: "app_header" })}
|
2026-04-11 15:32:16 +05:30
|
|
|
className="flex items-center gap-2"
|
|
|
|
|
>
|
|
|
|
|
<svg className="h-4 w-4" viewBox="0 0 24 24" fill="currentColor">
|
|
|
|
|
<path d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zm0-1.268a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z" />
|
|
|
|
|
</svg>
|
|
|
|
|
<span className="hidden sm:inline">Join Slack</span>
|
|
|
|
|
</a>
|
|
|
|
|
</Button>
|
2026-04-11 16:29:19 +05:30
|
|
|
<GitHubStarBadge source="app_header" />
|
2026-04-11 15:32:16 +05:30
|
|
|
</div>
|
2026-03-03 16:32:33 +05:30
|
|
|
</header>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-29 15:39:57 +05:30
|
|
|
interface AppLayoutProps {
|
|
|
|
|
children: ReactNode;
|
|
|
|
|
headerActions?: ReactNode;
|
|
|
|
|
stickyTabs?: ReactNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const AppLayout: React.FC<AppLayoutProps> = ({
|
|
|
|
|
children,
|
|
|
|
|
headerActions,
|
|
|
|
|
stickyTabs,
|
|
|
|
|
}) => {
|
|
|
|
|
const pathname = usePathname();
|
|
|
|
|
|
|
|
|
|
// Check if current route should have sidebar
|
2026-02-20 18:21:24 +05:30
|
|
|
// Hide sidebar for root (/), /handler routes (Stack Auth routes), and /auth routes
|
|
|
|
|
const shouldShowSidebar = pathname !== "/" && !pathname.startsWith("/handler") && !pathname.startsWith("/auth");
|
2025-11-29 15:39:57 +05:30
|
|
|
|
2026-04-11 15:32:16 +05:30
|
|
|
// Only match the exact editor page /workflow/<id>, not sub-routes like /workflow/<id>/runs
|
|
|
|
|
const isWorkflowEditor = /^\/workflow\/\d+$/.test(pathname);
|
2025-11-29 15:39:57 +05:30
|
|
|
|
2026-02-18 13:16:49 +05:30
|
|
|
// Always render SidebarProvider to keep the component tree shape consistent
|
|
|
|
|
// across route changes (avoids React hooks ordering violations during navigation).
|
2025-11-29 15:39:57 +05:30
|
|
|
return (
|
2026-05-14 14:45:34 +05:30
|
|
|
<SidebarProvider defaultOpen>
|
2026-02-18 13:16:49 +05:30
|
|
|
{shouldShowSidebar ? (
|
|
|
|
|
<div className="flex min-h-screen w-full">
|
|
|
|
|
<AppSidebar />
|
|
|
|
|
<SidebarInset className="flex-1">
|
2026-04-11 15:32:16 +05:30
|
|
|
{!isWorkflowEditor && <AppHeader />}
|
2026-02-18 13:16:49 +05:30
|
|
|
{/* Optional header area for specific pages */}
|
|
|
|
|
{headerActions && (
|
|
|
|
|
<header className="sticky top-0 z-50 w-full border-b bg-background">
|
|
|
|
|
<div className="container mx-auto px-4 py-4">
|
|
|
|
|
<div className="flex items-center justify-center">
|
|
|
|
|
{headerActions}
|
|
|
|
|
</div>
|
2025-11-29 15:39:57 +05:30
|
|
|
</div>
|
2026-02-18 13:16:49 +05:30
|
|
|
</header>
|
|
|
|
|
)}
|
2025-11-29 15:39:57 +05:30
|
|
|
|
2026-02-18 13:16:49 +05:30
|
|
|
{/* Optional sticky tabs */}
|
|
|
|
|
{stickyTabs && (
|
|
|
|
|
<div className="sticky top-0 z-40 bg-[#2a2e39] border-b border-gray-700">
|
|
|
|
|
<div className="container mx-auto px-4">
|
|
|
|
|
<div className="flex items-center justify-center py-2">
|
|
|
|
|
{stickyTabs}
|
|
|
|
|
</div>
|
2025-11-29 15:39:57 +05:30
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-02-18 13:16:49 +05:30
|
|
|
)}
|
2025-11-29 15:39:57 +05:30
|
|
|
|
2026-02-18 13:16:49 +05:30
|
|
|
{/* Main content area */}
|
|
|
|
|
<main className="flex-1">
|
|
|
|
|
{children}
|
|
|
|
|
</main>
|
|
|
|
|
</SidebarInset>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
<div className="flex-1 w-full">
|
|
|
|
|
{children}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2025-11-29 15:39:57 +05:30
|
|
|
</SidebarProvider>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default AppLayout;
|