|
| 1 | +import { memo } from 'react'; |
| 2 | +import { workbenchStore, type WorkbenchViewType } from '~/lib/stores/workbench'; |
| 3 | +import { IconButton } from '~/components/ui/IconButton'; |
| 4 | +import * as DropdownMenu from '@radix-ui/react-dropdown-menu'; |
| 5 | + |
| 6 | +interface CodeModeHeaderProps { |
| 7 | + onTerminalToggle: () => void; |
| 8 | + onDownloadZip: () => void; |
| 9 | + onSyncFiles: () => void; |
| 10 | + onPushToGitHub: () => void; |
| 11 | + isSyncing: boolean; |
| 12 | + setIsPushDialogOpen: (open: boolean) => void; |
| 13 | + showTerminal: boolean; |
| 14 | +} |
| 15 | + |
| 16 | +export const CodeModeHeader = memo( |
| 17 | + ({ |
| 18 | + onTerminalToggle, |
| 19 | + onDownloadZip, |
| 20 | + onSyncFiles, |
| 21 | + onPushToGitHub, |
| 22 | + isSyncing, |
| 23 | + setIsPushDialogOpen, |
| 24 | + showTerminal, |
| 25 | + }: CodeModeHeaderProps) => { |
| 26 | + const setSelectedView = (view: WorkbenchViewType) => { |
| 27 | + workbenchStore.currentView.set(view); |
| 28 | + }; |
| 29 | + |
| 30 | + return ( |
| 31 | + <div className="flex relative items-center gap-2 py-2 min-h-[var(--panel-header-height)] pl-0 bg-codinit-elements-background-depth-2"> |
| 32 | + {/* Toggle Buttons Section */} |
| 33 | + <div className="flex items-center gap-2"> |
| 34 | + <div className="flex items-center gap-1"> |
| 35 | + <button |
| 36 | + aria-label="Preview" |
| 37 | + aria-pressed="false" |
| 38 | + className="flex items-center justify-center w-8 h-8 rounded-md text-codinit-elements-icon-secondary hover:text-codinit-elements-item-contentActive hover:bg-codinit-elements-item-backgroundActive transition-colors" |
| 39 | + onClick={() => setSelectedView('preview')} |
| 40 | + > |
| 41 | + <span className="i-lucide:eye size-4"></span> |
| 42 | + </button> |
| 43 | + <button |
| 44 | + aria-label="Code" |
| 45 | + aria-pressed="true" |
| 46 | + className="flex items-center justify-center w-8 h-8 rounded-md text-codinit-elements-item-contentAccent bg-codinit-elements-item-backgroundAccent hover:bg-codinit-elements-item-backgroundActive transition-colors" |
| 47 | + onClick={() => setSelectedView('code')} |
| 48 | + > |
| 49 | + <span className="i-lucide:code size-4"></span> |
| 50 | + </button> |
| 51 | + <button |
| 52 | + aria-label="Database - Connected" |
| 53 | + aria-pressed="false" |
| 54 | + className="flex items-center justify-center w-8 h-8 rounded-md text-codinit-elements-icon-secondary hover:text-codinit-elements-item-contentActive hover:bg-codinit-elements-item-backgroundActive transition-colors" |
| 55 | + > |
| 56 | + <span className="i-lucide:database size-4"></span> |
| 57 | + </button> |
| 58 | + <button |
| 59 | + aria-label="Terminal" |
| 60 | + aria-pressed={showTerminal} |
| 61 | + className={`flex items-center justify-center w-8 h-8 rounded-md transition-colors ${ |
| 62 | + showTerminal |
| 63 | + ? 'text-codinit-elements-item-contentAccent bg-codinit-elements-item-backgroundAccent hover:bg-codinit-elements-item-backgroundActive' |
| 64 | + : 'text-codinit-elements-icon-secondary hover:text-codinit-elements-item-contentActive hover:bg-codinit-elements-item-backgroundActive' |
| 65 | + }`} |
| 66 | + onClick={onTerminalToggle} |
| 67 | + > |
| 68 | + <span className="i-lucide:terminal size-4"></span> |
| 69 | + </button> |
| 70 | + </div> |
| 71 | + <div className="flex items-center"> |
| 72 | + <DropdownMenu.Root> |
| 73 | + <DropdownMenu.Trigger asChild> |
| 74 | + <button |
| 75 | + type="button" |
| 76 | + aria-haspopup="menu" |
| 77 | + aria-expanded="false" |
| 78 | + className="bg-transparent p-0" |
| 79 | + aria-label="More Options" |
| 80 | + > |
| 81 | + <div className="flex items-center bg-transparent text-sm px-2 py-1 rounded-full relative text-codinit-elements-item-contentDefault hover:text-codinit-elements-item-contentActive pl-1 pr-1.5 h-5 opacity-90 hover:opacity-100"> |
| 82 | + <span className="i-lucide:settings text-current w-4 h-4"></span> |
| 83 | + </div> |
| 84 | + </button> |
| 85 | + </DropdownMenu.Trigger> |
| 86 | + <DropdownMenu.Content |
| 87 | + className="min-w-[240px] z-[250] bg-codinit-elements-background-depth-2 dark:bg-[#141414] rounded-lg shadow-xl border border-codinit-elements-borderColor animate-in fade-in-0 zoom" |
| 88 | + sideOffset={5} |
| 89 | + align="start" |
| 90 | + > |
| 91 | + <DropdownMenu.Item |
| 92 | + className="cursor-pointer flex items-center w-full px-4 py-2 text-sm text-codinit-elements-textPrimary hover:bg-codinit-elements-item-backgroundActive gap-2 rounded-md group relative" |
| 93 | + onClick={onDownloadZip} |
| 94 | + > |
| 95 | + <div className="flex items-center gap-2"> |
| 96 | + <span className="i-lucide:download text-current"></span> |
| 97 | + <span>Download Code</span> |
| 98 | + </div> |
| 99 | + </DropdownMenu.Item> |
| 100 | + <DropdownMenu.Item |
| 101 | + className="cursor-pointer flex items-center w-full px-4 py-2 text-sm text-codinit-elements-textPrimary hover:bg-codinit-elements-item-backgroundActive gap-2 rounded-md group relative" |
| 102 | + onClick={onSyncFiles} |
| 103 | + disabled={isSyncing} |
| 104 | + > |
| 105 | + <div className="flex items-center gap-2"> |
| 106 | + {isSyncing ? ( |
| 107 | + <span className="i-lucide:loader-2 text-current animate-spin" /> |
| 108 | + ) : ( |
| 109 | + <span className="i-lucide:cloud-download text-current" /> |
| 110 | + )} |
| 111 | + <span>{isSyncing ? 'Syncing...' : 'Sync Files'}</span> |
| 112 | + </div> |
| 113 | + </DropdownMenu.Item> |
| 114 | + <DropdownMenu.Item |
| 115 | + className="cursor-pointer flex items-center w-full px-4 py-2 text-sm text-codinit-elements-textPrimary hover:bg-codinit-elements-item-backgroundActive gap-2 rounded-md group relative" |
| 116 | + onClick={onPushToGitHub} |
| 117 | + > |
| 118 | + <div className="flex items-center gap-2"> |
| 119 | + <span className="i-lucide:git-branch text-current" /> |
| 120 | + <span>Push to GitHub</span> |
| 121 | + </div> |
| 122 | + </DropdownMenu.Item> |
| 123 | + </DropdownMenu.Content> |
| 124 | + </DropdownMenu.Root> |
| 125 | + </div> |
| 126 | + </div> |
| 127 | + |
| 128 | + {/* Right Action Buttons */} |
| 129 | + <div className="ml-auto"> |
| 130 | + <div className="flex gap-3"> |
| 131 | + <div className="flex gap-1 empty:hidden"></div> |
| 132 | + <div className="flex gap-1"> |
| 133 | + <IconButton |
| 134 | + icon="i-codinit:stars" |
| 135 | + className="text-codinit-elements-item-contentDefault bg-transparent rounded-md disabled:cursor-not-allowed enabled:hover:text-codinit-elements-item-contentActive enabled:hover:bg-codinit-elements-item-backgroundActive p-1 relative w-8 h-8" |
| 136 | + /> |
| 137 | + </div> |
| 138 | + <button |
| 139 | + className="items-center justify-center font-medium min-w-0 max-w-full rounded-md focus-visible:outline-2 disabled:opacity-50 relative disabled:cursor-not-allowed focus-visible:outline-codinit-ds-brandHighlight bg-codinit-elements-textPrimary text-codinit-elements-background-depth-1 flex gap-1.7 shrink-0 h-8 text-sm px-3" |
| 140 | + type="button" |
| 141 | + aria-controls="publish-menu" |
| 142 | + onClick={() => setIsPushDialogOpen(true)} |
| 143 | + > |
| 144 | + Publish |
| 145 | + </button> |
| 146 | + </div> |
| 147 | + </div> |
| 148 | + </div> |
| 149 | + ); |
| 150 | + }, |
| 151 | +); |
0 commit comments