import { memo } from "react"; import { useStyletron } from "baseui"; import { LabelXSmall } from "baseui/typography"; import { FileCode, Plus, X } from "lucide-react"; import { ContextMenuOverlay, TabAvatar, useContextMenu } from "./ui"; import { diffTabId, fileName, type Handoff } from "./view-model"; export const TabStrip = memo(function TabStrip({ handoff, activeTabId, openDiffs, editingSessionTabId, editingSessionName, onEditingSessionNameChange, onSwitchTab, onStartRenamingTab, onCommitSessionRename, onCancelSessionRename, onSetTabUnread, onCloseTab, onCloseDiffTab, onAddTab, }: { handoff: Handoff; activeTabId: string | null; openDiffs: string[]; editingSessionTabId: string | null; editingSessionName: string; onEditingSessionNameChange: (value: string) => void; onSwitchTab: (tabId: string) => void; onStartRenamingTab: (tabId: string) => void; onCommitSessionRename: () => void; onCancelSessionRename: () => void; onSetTabUnread: (tabId: string, unread: boolean) => void; onCloseTab: (tabId: string) => void; onCloseDiffTab: (path: string) => void; onAddTab: () => void; }) { const [css, theme] = useStyletron(); const contextMenu = useContextMenu(); return ( <>
{handoff.tabs.map((tab) => { const isActive = tab.id === activeTabId; return (
onSwitchTab(tab.id)} onDoubleClick={() => onStartRenamingTab(tab.id)} onMouseDown={(event) => { if (event.button === 1 && handoff.tabs.length > 1) { event.preventDefault(); onCloseTab(tab.id); } }} onContextMenu={(event) => contextMenu.open(event, [ { label: "Rename session", onClick: () => onStartRenamingTab(tab.id) }, { label: tab.unread ? "Mark as read" : "Mark as unread", onClick: () => onSetTabUnread(tab.id, !tab.unread), }, ...(handoff.tabs.length > 1 ? [{ label: "Close tab", onClick: () => onCloseTab(tab.id) }] : []), ]) } data-tab className={css({ display: "flex", alignItems: "center", gap: "6px", padding: "4px 12px", marginTop: "6px", marginBottom: "6px", borderRadius: "8px", backgroundColor: isActive ? "rgba(255, 255, 255, 0.06)" : "transparent", cursor: "pointer", transition: "color 200ms ease, background-color 200ms ease", flexShrink: 0, ":hover": { color: "#e4e4e7", backgroundColor: isActive ? "rgba(255, 255, 255, 0.06)" : "rgba(255, 255, 255, 0.04)" }, })} >
{editingSessionTabId === tab.id ? ( onEditingSessionNameChange(event.target.value)} onBlur={onCommitSessionRename} onClick={(event) => event.stopPropagation()} onDoubleClick={(event) => event.stopPropagation()} onKeyDown={(event) => { if (event.key === "Enter") { onCommitSessionRename(); } else if (event.key === "Escape") { onCancelSessionRename(); } }} className={css({ appearance: "none", WebkitAppearance: "none", background: "none", border: "none", padding: "0", margin: "0", outline: "none", minWidth: "72px", maxWidth: "180px", fontSize: "11px", fontWeight: 600, color: theme.colors.contentPrimary, borderBottom: "1px solid rgba(255, 255, 255, 0.3)", })} /> ) : ( {tab.sessionName} )} {handoff.tabs.length > 1 ? ( { event.stopPropagation(); onCloseTab(tab.id); }} /> ) : null}
); })} {openDiffs.map((path) => { const tabId = diffTabId(path); const isActive = tabId === activeTabId; return (
onSwitchTab(tabId)} onMouseDown={(event) => { if (event.button === 1) { event.preventDefault(); onCloseDiffTab(path); } }} data-tab className={css({ display: "flex", alignItems: "center", gap: "6px", padding: "4px 12px", marginTop: "6px", marginBottom: "6px", borderRadius: "8px", backgroundColor: isActive ? "rgba(255, 255, 255, 0.06)" : "transparent", cursor: "pointer", transition: "color 200ms ease, background-color 200ms ease", flexShrink: 0, ":hover": { color: "#e4e4e7", backgroundColor: isActive ? "rgba(255, 255, 255, 0.06)" : "rgba(255, 255, 255, 0.04)" }, })} > {fileName(path)} { event.stopPropagation(); onCloseDiffTab(path); }} />
); })}
{contextMenu.menu ? : null} ); });