feat: add github and slack community buttons

This commit is contained in:
Abhishek Kumar 2026-04-11 15:32:16 +05:30
parent 51fde746ba
commit 73e5ca87e4
5 changed files with 95 additions and 28 deletions

View file

@ -297,7 +297,7 @@ function RenderWorkflow({ initialWorkflowName, workflowId, initialFlow, initialT
return (
<WorkflowProvider value={workflowContextValue}>
<div className="flex flex-col h-screen">
<div className="flex flex-col h-screen min-w-fit">
{/* New Workflow Editor Header */}
<WorkflowEditorHeader
workflowName={workflowName}

View file

@ -1,7 +1,7 @@
"use client";
import { ReactFlowInstance } from "@xyflow/react";
import { AlertCircle, ArrowLeft, ChevronDown, Copy, Download, Eye, History, LoaderCircle, MoreVertical, Phone, Rocket } from "lucide-react";
import { AlertCircle, ArrowLeft, ChevronDown, Copy, Download, Eye, History, LoaderCircle, Menu, MoreVertical, Phone, Rocket } from "lucide-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { toast } from "sonner";
@ -12,6 +12,7 @@ import {
} from "@/client/sdk.gen";
import { WorkflowError } from "@/client/types.gen";
import { FlowEdge, FlowNode } from "@/components/flow/types";
import { GitHubStarBadge } from "@/components/layout/GitHubStarBadge";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
@ -24,6 +25,7 @@ import {
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { useSidebar } from "@/components/ui/sidebar";
import { WORKFLOW_RUN_MODES } from "@/constants/workflowRunModes";
interface WorkflowEditorHeaderProps {
@ -61,6 +63,7 @@ export const WorkflowEditorHeader = ({
workflowId,
}: WorkflowEditorHeaderProps) => {
const router = useRouter();
const { toggleSidebar } = useSidebar();
const [savingWorkflow, setSavingWorkflow] = useState(false);
const [duplicating, setDuplicating] = useState(false);
const [publishing, setPublishing] = useState(false);
@ -140,8 +143,15 @@ export const WorkflowEditorHeader = ({
return (
<div className="flex items-center justify-between w-full h-14 px-4 bg-[#1a1a1a] border-b border-[#2a2a2a]">
{/* Left section: Back button + Workflow name */}
<div className="flex items-center gap-3">
{/* Left section: Mobile menu + Back button + Workflow name */}
<div className="flex items-center gap-3 mr-4">
<button
onClick={toggleSidebar}
className="flex items-center justify-center w-8 h-8 rounded-lg hover:bg-[#2a2a2a] transition-colors md:hidden"
aria-label="Open menu"
>
<Menu className="w-5 h-5 text-gray-400" />
</button>
<button
onClick={handleBack}
className="flex items-center justify-center w-8 h-8 rounded-lg hover:bg-[#2a2a2a] transition-colors"
@ -150,8 +160,11 @@ export const WorkflowEditorHeader = ({
</button>
<div className="flex items-center gap-2">
<h1 className="text-base font-medium text-white">
{workflowName}
<h1 className="text-base font-medium text-white whitespace-nowrap">
<span className="md:hidden">
{workflowName.length > 8 ? `${workflowName.slice(0, 8)}` : workflowName}
</span>
<span className="hidden md:inline">{workflowName}</span>
</h1>
</div>
</div>
@ -361,6 +374,11 @@ export const WorkflowEditorHeader = ({
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
{/* GitHub star badge - desktop only */}
<div className="hidden md:block">
<GitHubStarBadge className="border-[#3a3a3a] text-white" />
</div>
</div>
</div>
);

View file

@ -1,6 +1,7 @@
"use client";
import { Menu } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import React, { ReactNode } from "react";
@ -8,16 +9,35 @@ import { Button } from "@/components/ui/button";
import { SidebarInset, SidebarProvider, useSidebar } from "@/components/ui/sidebar";
import { AppSidebar } from "./AppSidebar";
import { GitHubStarBadge } from "./GitHubStarBadge";
function MobileHeader() {
function AppHeader() {
const { toggleSidebar } = useSidebar();
return (
<header className="sticky top-0 z-50 flex items-center gap-3 border-b bg-background px-4 py-2 md:hidden">
<Button variant="ghost" size="icon" onClick={toggleSidebar} aria-label="Open menu">
<Menu className="h-5 w-5" />
</Button>
<span className="text-lg font-bold">Dograh</span>
<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
href="https://join.slack.com/t/dograh-community/shared_invite/zt-2z2i1p37n-CkHFbPWDCQ~hNqmKeFGJiQ"
target="_blank"
rel="noopener noreferrer"
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>
<GitHubStarBadge />
</div>
</header>
);
}
@ -40,7 +60,8 @@ const AppLayout: React.FC<AppLayoutProps> = ({
const shouldShowSidebar = pathname !== "/" && !pathname.startsWith("/handler") && !pathname.startsWith("/auth");
// Check if we're in workflow editor mode or superadmin runs - collapse sidebar by default
const isWorkflowEditor = /^\/workflow\/\d+/.test(pathname);
// Only match the exact editor page /workflow/<id>, not sub-routes like /workflow/<id>/runs
const isWorkflowEditor = /^\/workflow\/\d+$/.test(pathname);
const isSuperadmin = pathname.startsWith("/superadmin");
// Always render SidebarProvider to keep the component tree shape consistent
@ -51,7 +72,7 @@ const AppLayout: React.FC<AppLayoutProps> = ({
<div className="flex min-h-screen w-full">
<AppSidebar />
<SidebarInset className="flex-1">
<MobileHeader />
{!isWorkflowEditor && <AppHeader />}
{/* Optional header area for specific pages */}
{headerActions && (
<header className="sticky top-0 z-50 w-full border-b bg-background">

View file

@ -73,6 +73,10 @@ export function AppSidebar() {
const { provider, getSelectedTeam, logout, user } = useAuth();
const { config } = useAppConfig();
// On mobile the sidebar renders as a full-width sheet overlay, so treat it
// as always "expanded" regardless of the desktop collapsed/expanded state.
const effectiveState = isMobile ? "expanded" : state;
// Get selected team for Stack auth (cast to Team type from Stack)
// Stabilize the reference so SelectedTeamSwitcher only sees a change when the team ID changes,
// preventing unnecessary PATCH calls to Stack Auth on every route navigation.
@ -181,7 +185,7 @@ export function AppSidebar() {
const isItemActive = isActive(item.url);
const Icon = item.icon;
if (state === "collapsed") {
if (effectiveState === "collapsed") {
return (
<TooltipProvider delayDuration={0}>
<Tooltip>
@ -228,7 +232,7 @@ export function AppSidebar() {
<SidebarHeader className="border-b px-2 py-3">
<div className="flex items-center justify-between">
{/* Logo - only show when expanded */}
{state === "expanded" && (
{effectiveState === "expanded" && (
<Link
href="/"
className="flex items-center gap-2 px-2 text-xl font-bold"
@ -244,9 +248,9 @@ export function AppSidebar() {
{/* Toggle button - center it when collapsed */}
<SidebarTrigger className={cn(
"hover:bg-accent",
state === "collapsed" && "mx-auto"
effectiveState === "collapsed" && "mx-auto"
)}>
{state === "expanded" ? (
{effectiveState === "expanded" ? (
<ChevronLeft className="h-4 w-4" />
) : (
<ChevronRight className="h-4 w-4" />
@ -255,7 +259,7 @@ export function AppSidebar() {
</div>
{/* Team Switcher for Stack Auth - at the top */}
{provider === "stack" && state === "expanded" && (
{provider === "stack" && effectiveState === "expanded" && (
<div className="mt-3">
<React.Suspense
fallback={
@ -275,7 +279,7 @@ export function AppSidebar() {
{/* Star us on GitHub for OSS mode - at the top */}
{provider !== "stack" && (
<div className="mt-3 px-2">
{state === "collapsed" ? (
{effectiveState === "collapsed" ? (
<TooltipProvider delayDuration={0}>
<Tooltip>
<TooltipTrigger asChild>
@ -321,7 +325,7 @@ export function AppSidebar() {
</SidebarHeader>
<SidebarContent className={cn(
state === "collapsed" && "px-0"
effectiveState === "collapsed" && "px-0"
)}>
{/* Overview Section */}
<SidebarGroup className="mt-2">
@ -337,7 +341,7 @@ export function AppSidebar() {
{/* BUILD Section */}
{buildSection.length > 0 && (
<SidebarGroup className="mt-6">
{state === "expanded" && (
{effectiveState === "expanded" && (
<SidebarGroupLabel className="text-xs font-semibold text-muted-foreground uppercase tracking-wider">
BUILD
</SidebarGroupLabel>
@ -354,7 +358,7 @@ export function AppSidebar() {
{/* OBSERVE Section */}
<SidebarGroup className="mt-6">
{state === "expanded" && (
{effectiveState === "expanded" && (
<SidebarGroupLabel className="text-xs font-semibold text-muted-foreground uppercase tracking-wider">
OBSERVE
</SidebarGroupLabel>
@ -371,7 +375,7 @@ export function AppSidebar() {
<SidebarFooter className={cn(
"border-t p-4",
state === "collapsed" && "p-2"
effectiveState === "collapsed" && "p-2"
)}>
{/* Bottom Actions */}
<div className="space-y-2">
@ -379,7 +383,7 @@ export function AppSidebar() {
{provider !== "stack" && (
<div className={cn(
"flex",
state === "collapsed" ? "justify-center" : "justify-start"
effectiveState === "collapsed" ? "justify-center" : "justify-start"
)}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
@ -421,7 +425,7 @@ export function AppSidebar() {
{provider === "stack" && (
<div className={cn(
"flex",
state === "collapsed" ? "justify-center" : "justify-start"
effectiveState === "collapsed" ? "justify-center" : "justify-start"
)}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
@ -473,9 +477,9 @@ export function AppSidebar() {
{/* Theme Toggle - at the very bottom */}
<div className={cn(
"mt-2 pt-2 border-t",
state === "collapsed" ? "flex justify-center" : ""
effectiveState === "collapsed" ? "flex justify-center" : ""
)}>
{state === "collapsed" ? (
{effectiveState === "collapsed" ? (
<TooltipProvider delayDuration={0}>
<Tooltip>
<TooltipTrigger asChild>

View file

@ -0,0 +1,24 @@
"use client";
import { cn } from "@/lib/utils";
export function GitHubStarBadge({ className }: { className?: string }) {
return (
<a
href="https://github.com/dograh-hq/dograh"
target="_blank"
rel="noopener noreferrer"
className={cn(
"inline-flex items-center rounded-md border text-sm leading-none hover:opacity-80 transition-opacity",
className
)}
>
<span className="inline-flex items-center gap-1.5 bg-muted px-2.5 py-1.5 rounded-md">
<svg className="h-4 w-4" viewBox="0 0 16 16" fill="currentColor">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" />
</svg>
<span className="font-medium">Star</span>
</span>
</a>
);
}