/** * @fileoverview Application Header Component for Writenex Astro * * This component provides the main header bar with logo, branding, and * a unified toolbar for editor operations. * * @module @writenex/astro/client/components/Header */ import { Folder, History, Info, Keyboard, Monitor, Moon, Plus, Search, Settings, Sun, } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { type Theme, useTheme } from "../../context/ThemeContext"; import "./Header.css"; /** * Writenex Logo SVG component */ function LogoIcon(): React.ReactElement { return ( ); } /** * Props for the Header component */ interface HeaderProps { /** Whether the sidebar is open */ isSidebarOpen?: boolean; /** Callback to toggle sidebar */ onToggleSidebar?: () => void; /** Whether the frontmatter panel is open */ isFrontmatterOpen?: boolean; /** Callback to toggle frontmatter panel */ onToggleFrontmatter?: () => void; /** Whether the search panel is open */ isSearchOpen?: boolean; /** Callback to toggle search panel */ onToggleSearch?: () => void; /** Whether the version history panel is open */ isVersionHistoryOpen?: boolean; /** Callback to toggle version history panel */ onToggleVersionHistory?: () => void; /** Whether version history is available (content selected) */ versionHistoryEnabled?: boolean; /** Callback when keyboard shortcuts button is clicked */ onKeyboardShortcuts?: () => void; /** Callback when settings button is clicked */ onSettings?: () => void; /** Callback when new content button is clicked */ onNewContent?: () => void; } /** * Visual separator for grouping toolbar buttons. */ function ToolbarSeparator(): React.ReactElement { return
; } /** * Toolbar button component with icon */ function ToolbarButton({ icon, label, onClick, active = false, disabled = false, }: { icon: React.ReactNode; label: string; onClick?: () => void; active?: boolean; disabled?: boolean; }): React.ReactElement { const className = [ "wn-toolbar-btn", active ? "wn-toolbar-btn--active" : "", disabled ? "wn-toolbar-btn--disabled" : "", ] .filter(Boolean) .join(" "); return ( ); } /** * Theme option configuration */ const THEME_OPTIONS: { value: Theme; label: string; icon: typeof Sun }[] = [ { value: "light", label: "Light", icon: Sun }, { value: "dark", label: "Dark", icon: Moon }, { value: "system", label: "System", icon: Monitor }, ]; /** * Theme switcher dropdown component */ function ThemeSwitcher(): React.ReactElement { const { theme, resolvedTheme, setTheme } = useTheme(); const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); // Close dropdown when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { setIsOpen(false); } }; if (isOpen) { document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); } }, [isOpen]); // Close on escape key useEffect(() => { const handleEscape = (event: KeyboardEvent) => { if (event.key === "Escape") setIsOpen(false); }; if (isOpen) { document.addEventListener("keydown", handleEscape); return () => document.removeEventListener("keydown", handleEscape); } }, [isOpen]); const ThemeIcon = resolvedTheme === "dark" ? Moon : Sun; return (
{isOpen && (
{THEME_OPTIONS.map((option) => { const Icon = option.icon; const isSelected = theme === option.value; return ( ); })}
)}
); } /** * Main application header with logo and unified toolbar. * * @component */ export function Header({ isSidebarOpen = true, onToggleSidebar, isFrontmatterOpen = true, onToggleFrontmatter, isSearchOpen = false, onToggleSearch, isVersionHistoryOpen = false, onToggleVersionHistory, versionHistoryEnabled = false, onKeyboardShortcuts, onSettings, onNewContent, }: HeaderProps): React.ReactElement { return (
{/* Left side: Logo and branding */}
Writenex Astro
Edit your Astro content visually.
{/* Right side: Toolbar */}
{/* New Content Button */} } label="New Content (Alt+N)" onClick={onNewContent} /> {/* Group 1: Panels & Actions */} } label="Toggle Explorer" onClick={onToggleSidebar} active={isSidebarOpen} /> } label="Toggle Frontmatter" onClick={onToggleFrontmatter} active={isFrontmatterOpen} /> } label="Search & Replace (Ctrl+F)" onClick={onToggleSearch} active={isSearchOpen} /> } label="Version History" onClick={onToggleVersionHistory} active={isVersionHistoryOpen} disabled={!versionHistoryEnabled} /> {/* Group 2: Preferences */} } label="Keyboard Shortcuts (Ctrl+/)" onClick={onKeyboardShortcuts} /> } label="Settings" onClick={onSettings} />
); }