// Sticky top navigation bar. Adapts based on whether we're on the repo picker
// page (root) or inside a specific repo:
// - Root: shows logo only, no Code/Issues links
// - Repo: shows Code + Issues nav links scoped to the current repo slug
//
// In external mode, shows a "Sign in" button when logged out and a sign-out
// action when logged in.
import { Link, useMatch, NavLink } from 'react-router-dom'
import { Bug, Plus, Sun, Moon, LogIn, LogOut } from 'lucide-react'
import { cn } from '@/lib/utils'
import { useAuth } from '@/lib/auth'
import { useTheme } from '@/lib/theme'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Button } from '@/components/ui/button'
// SignOutButton sends a POST to /auth/logout and reloads the page.
// A full reload is the simplest way to reset all Apollo cache + React state.
function SignOutButton() {
function handleSignOut() {
fetch('/auth/logout', { method: 'POST', credentials: 'include' }).finally(
() => window.location.assign('/'),
)
}
return (
)
}
export function Header() {
const { user, mode, loginProviders } = useAuth()
const { theme, toggle } = useTheme()
// Detect if we're inside a /:repo route and grab the slug.
// useMatch works from any component in the tree, unlike useParams which is
// scoped to the nearest Route element.
const repoMatch = useMatch({ path: '/:repo/*', end: false })
const repo = repoMatch?.params.repo ?? null
// Don't show repo nav on the /auth/* pages.
const effectiveRepo = repo === 'auth' ? null : repo
return (
{/* Logo always goes to the repo picker root */}
git-bug
{/* Repo-scoped nav links — only shown when inside a repo */}
{effectiveRepo && (
)}
{mode === 'readonly' && (
Read only
)}
{/* External mode: show sign-in buttons when logged out */}
{mode === 'external' && !user && loginProviders.map((p) => (
))}
{user && effectiveRepo && (
<>
{user.displayName.slice(0, 2).toUpperCase()}
>
)}
{/* Sign out only shown in external mode when logged in */}
{mode === 'external' && user && }
)
}
function providerLabel(name: string): string {
const labels: Record = { github: 'GitHub', gitlab: 'GitLab', gitea: 'Gitea' }
return labels[name] ?? name
}