wip: pane/session + tab-bar checkpoint
Second checkpoint of in-flight work (sessions route, api types, ChatTabBar, PaneHeaderActions, Workspace, useWorkspacePanes) so the Orchestrator branch can rebase onto current main before merge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,14 +12,9 @@ import { cn } from '@/lib/utils';
|
||||
// desktop coder + terminal pane headers (Workspace) so all pane kinds share one
|
||||
// control set. Extracted to avoid a divergent copy per header.
|
||||
interface Props {
|
||||
// When provided, the "+" menu item matching `tabKind` opens an in-pane tab
|
||||
// (e.g. chat panes: New BooChat → tab; coder panes: New BooCode → tab). Every
|
||||
// OTHER kind splits into a new pane. When onNewTab is omitted (terminal
|
||||
// panes, which can't host tabs) all three items split.
|
||||
onNewTab?: () => void;
|
||||
// The host pane's own kind — the "+" item of this kind becomes "new tab".
|
||||
// Defaults to 'chat' for back-compat with the chat tab bar.
|
||||
tabKind?: 'chat' | 'terminal' | 'coder';
|
||||
// Mixed tabs: the "+" menu adds a tab of the chosen kind to THIS pane. Split
|
||||
// (the second control) adds a new pane.
|
||||
onNewTab: (kind: 'chat' | 'terminal' | 'coder') => void;
|
||||
onSplitPane: (kind: 'chat' | 'terminal' | 'coder') => void;
|
||||
onReopenPane?: () => void;
|
||||
onShowHistory: () => void;
|
||||
@@ -35,7 +30,6 @@ const BTN =
|
||||
|
||||
export function PaneHeaderActions({
|
||||
onNewTab,
|
||||
tabKind = 'chat',
|
||||
onSplitPane,
|
||||
onReopenPane,
|
||||
onShowHistory,
|
||||
@@ -43,10 +37,6 @@ export function PaneHeaderActions({
|
||||
historyActive,
|
||||
className,
|
||||
}: Props) {
|
||||
// The "+" item of the host pane's own kind adds a tab; every other kind
|
||||
// splits into a new pane. Falls back to split when onNewTab is absent.
|
||||
const newOrSplit = (kind: 'chat' | 'terminal' | 'coder') =>
|
||||
onNewTab && tabKind === kind ? onNewTab : () => onSplitPane(kind);
|
||||
return (
|
||||
<div className={cn('flex items-center gap-0.5 shrink-0', className)}>
|
||||
<DropdownMenu>
|
||||
@@ -55,22 +45,21 @@ export function PaneHeaderActions({
|
||||
type="button"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className={BTN}
|
||||
aria-label="New chat, terminal, or coder"
|
||||
title="New chat / terminal / coder"
|
||||
aria-label="New tab"
|
||||
title="New tab (chat / terminal / coder)"
|
||||
>
|
||||
<Plus size={12} />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-fit">
|
||||
{/* The item matching the host pane's kind opens an in-pane tab; the
|
||||
others split into a new pane. (tabKind defaults to 'chat'.) */}
|
||||
<DropdownMenuItem onSelect={newOrSplit('chat')}>
|
||||
{/* Mixed tabs: every item adds a tab of that kind to THIS pane. */}
|
||||
<DropdownMenuItem onSelect={() => onNewTab('chat')}>
|
||||
<MessageSquare size={14} /> New BooChat
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onSelect={newOrSplit('terminal')}>
|
||||
<DropdownMenuItem onSelect={() => onNewTab('terminal')}>
|
||||
<Terminal size={14} /> New BooTerm
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onSelect={newOrSplit('coder')}>
|
||||
<DropdownMenuItem onSelect={() => onNewTab('coder')}>
|
||||
<Code size={14} /> New BooCode
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
|
||||
Reference in New Issue
Block a user