| import { |
| FileText, |
| LogIn, |
| Monitor, |
| Moon, |
| MoreHorizontal, |
| PanelLeft, |
| Pencil, |
| Share2, |
| SquarePen, |
| Sun, |
| Trash2, |
| } from 'lucide-react' |
| import Button from './Button' |
| import Dropdown from './Dropdown' |
|
|
| function themeOptionItems(themePreference, onThemePreferenceChange) { |
| return [ |
| { |
| key: 'system', |
| label: 'System', |
| icon: Monitor, |
| onSelect: () => onThemePreferenceChange('system'), |
| }, |
| { |
| key: 'light', |
| label: 'Light', |
| icon: Sun, |
| onSelect: () => onThemePreferenceChange('light'), |
| }, |
| { |
| key: 'dark', |
| label: 'Dark', |
| icon: Moon, |
| onSelect: () => onThemePreferenceChange('dark'), |
| }, |
| ] |
| } |
|
|
| export default function AppHeader({ |
| title, |
| theme, |
| themePreference, |
| currentSessionId, |
| canRenameSession, |
| hasMessages, |
| onToggleSidebar, |
| onThemePreferenceChange, |
| onNewChat, |
| onRenameSession, |
| onDeleteSession, |
| onShare, |
| onExportMarkdown, |
| onExportPdf, |
| onFeedback, |
| user, |
| onLogin, |
| onLogout, |
| }) { |
| const accountName = user?.name || user?.username || '' |
| const actions = [ |
| { |
| key: 'new', |
| label: 'New chat', |
| icon: SquarePen, |
| onSelect: onNewChat, |
| }, |
| ...(canRenameSession |
| ? [ |
| { |
| key: 'rename', |
| label: 'Rename', |
| icon: Pencil, |
| onSelect: onRenameSession, |
| }, |
| ] |
| : []), |
| ...(currentSessionId |
| ? [ |
| { |
| key: 'delete', |
| label: 'Delete', |
| icon: Trash2, |
| onSelect: onDeleteSession, |
| destructive: true, |
| }, |
| ] |
| : []), |
| { |
| key: 'share', |
| label: 'Share', |
| icon: Share2, |
| onSelect: onShare, |
| disabled: !hasMessages, |
| }, |
| { |
| key: 'export-md', |
| label: 'Export Markdown', |
| icon: FileText, |
| onSelect: onExportMarkdown, |
| disabled: !hasMessages, |
| }, |
| { |
| key: 'export-pdf', |
| label: 'Export PDF', |
| icon: FileText, |
| onSelect: onExportPdf, |
| disabled: !hasMessages, |
| }, |
| ] |
|
|
| const userItems = user |
| ? [ |
| { |
| key: 'feedback', |
| label: 'Send feedback', |
| onSelect: onFeedback, |
| }, |
| { |
| key: 'separator', |
| type: 'separator', |
| }, |
| { |
| key: 'logout', |
| label: 'Sign out', |
| onSelect: onLogout, |
| }, |
| ] |
| : [] |
|
|
| const ThemeIcon = |
| themePreference === 'system' ? Monitor : theme === 'dark' ? Moon : Sun |
|
|
| return ( |
| <header className="h-14 border-b border-border bg-background/95 px-3 backdrop-blur-xl sm:px-4"> |
| <div className="flex h-full items-center justify-between gap-3"> |
| <div className="flex min-w-0 items-center gap-2"> |
| <Button size="icon" onClick={onToggleSidebar} variant="secondary" className="shrink-0"> |
| <PanelLeft className="h-4 w-4" /> |
| </Button> |
| |
| <h1 className="max-w-[52vw] truncate text-sm font-medium text-foreground sm:max-w-[22rem]"> |
| {title} |
| </h1> |
| </div> |
| |
| <div className="flex shrink-0 items-center gap-1.5"> |
| <Button variant="ghost" size="sm" onClick={onNewChat} className="hidden sm:inline-flex"> |
| <SquarePen className="h-4 w-4" /> |
| <span>New chat</span> |
| </Button> |
| <Dropdown |
| trigger={ |
| <Button variant="ghost" size="icon" aria-label="Theme options"> |
| <ThemeIcon className="h-4 w-4" /> |
| </Button> |
| } |
| items={themeOptionItems(themePreference, onThemePreferenceChange)} |
| /> |
| <Dropdown |
| trigger={ |
| <Button variant="ghost" size="icon" aria-label="Workspace actions"> |
| <MoreHorizontal className="h-4 w-4" /> |
| </Button> |
| } |
| items={actions} |
| /> |
| {user ? ( |
| <Dropdown |
| trigger={ |
| <button |
| type="button" |
| className="flex h-11 min-w-11 items-center justify-center rounded-full border border-border/70 bg-card/95 px-3 text-sm font-semibold text-foreground shadow-soft transition hover:border-accent/25" |
| aria-label="Open account menu" |
| > |
| {user.avatar_url ? ( |
| <img |
| src={user.avatar_url} |
| alt={accountName} |
| className="h-8 w-8 rounded-full object-cover" |
| /> |
| ) : ( |
| accountName.slice(0, 1).toUpperCase() |
| )} |
| </button> |
| } |
| items={userItems} |
| /> |
| ) : ( |
| <Button variant="primary" onClick={onLogin}> |
| <LogIn className="h-4 w-4" /> |
| Sign in |
| </Button> |
| )} |
| </div> |
| </div> |
| </header> |
| ) |
| } |
|
|