Workspaces in Workspaces all around

This commit is contained in:
2026-02-19 01:49:15 +00:00
parent 72bca6cd42
commit dd8ab84df5
84 changed files with 3047 additions and 749 deletions
@@ -186,7 +186,7 @@ export const InputArea = ({
};
return (
<div className="shrink-0 border-t border-duck-dark/10 bg-white/60 p-2 md:p-3">
<div className="shrink-0 border-t border-duck-dark/10 bg-background/60 p-2 md:p-3">
{commandFeedback && (
<div className="mb-2 px-3 py-1.5 text-xs text-duck-teal bg-duck-teal/10 rounded-md">{commandFeedback}</div>
)}
@@ -296,7 +296,7 @@ export const InputArea = ({
}}
placeholder="Type a message..."
rows={1}
className="min-w-0 flex-1 resize-none rounded-lg border border-duck-dark/20 bg-white/80 px-2 py-1.5 md:px-3 md:py-2 text-base md:text-sm text-duck-dark placeholder:text-duck-dark/30 focus:outline-none focus:ring-2 focus:ring-duck-teal/30 focus:border-duck-teal/50"
className="min-w-0 flex-1 resize-none rounded-lg border border-duck-dark/20 bg-background/80 px-2 py-1.5 md:px-3 md:py-2 text-base md:text-sm text-duck-dark placeholder:text-duck-dark/30 focus:outline-none focus:ring-2 focus:ring-duck-teal/30 focus:border-duck-teal/50"
/>
{isGenerating ? (
<Button onClick={onStop} variant="destructive" size="icon" className="shrink-0 h-7 w-7 md:h-9 md:w-9 cursor-pointer">
@@ -343,7 +343,7 @@ export const InputArea = ({
}
}}
placeholder="https://example.com"
className="flex-1 rounded-lg border border-duck-dark/20 bg-white px-3 py-2 text-sm text-duck-dark placeholder:text-duck-dark/30 focus:outline-none focus:ring-2 focus:ring-duck-teal/30 focus:border-duck-teal/50"
className="flex-1 rounded-lg border border-duck-dark/20 bg-background px-3 py-2 text-sm text-duck-dark placeholder:text-duck-dark/30 focus:outline-none focus:ring-2 focus:ring-duck-teal/30 focus:border-duck-teal/50"
autoFocus
/>
<Button
@@ -38,13 +38,13 @@ export const Settings = ({
{provider === 'claude' ? 'Claude' : 'OpenCode'}
</span>
) : (
<div className="flex items-center gap-1 rounded-lg bg-white/60 p-1">
<div className="flex items-center gap-1 rounded-lg bg-background/60 p-1">
{(['claude', 'opencode'] as const).map((value) => (
<button
key={value}
onClick={() => onProviderChange?.(value)}
className={`rounded-md px-3 py-1 text-xs font-medium transition-colors ${
provider === value ? 'bg-white text-duck-dark shadow-sm' : 'text-duck-dark/70 hover:text-duck-dark/90'
provider === value ? 'bg-background text-duck-dark shadow-sm' : 'text-duck-dark/70 hover:text-duck-dark/90'
} ${!onProviderChange ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}`}
>
{value === 'claude' ? 'Claude' : 'OpenCode'}
@@ -1,79 +1 @@
import { useState } from 'react';
import { useParams } from 'react-router';
import { useQueryClient } from '@tanstack/react-query';
import type { SessionEntry } from 'apps/Chat';
import { useClaude } from './useClaude';
import { useOpenCode } from './useOpenCode';
import { ChatPanel } from './ChatPanel';
import { useVisibleClaudeModels, useVisibleOpenCodeModels } from '@/state/useModels';
export const ClaudeChat = () => {
const { sessionId } = useParams<{ sessionId: string }>();
const queryClient = useQueryClient();
const sessions = queryClient.getQueryData<SessionEntry[]>(['SESSIONS']);
const sessionModel = sessions?.find((s) => s.id === sessionId)?.model;
const claude = useClaude(sessionId, sessionModel);
const claudeModels = useVisibleClaudeModels();
return (
<div className="flex items-center justify-center h-full md:p-4">
<div className="flex flex-col w-full h-full md:w-3/4 md:h-3/4 lg:w-1/2 lg:h-1/2">
<ChatPanel chat={claude} provider="claude" availableModels={claudeModels} />
</div>
</div>
);
};
export const OpenCodeChat = () => {
const { sessionId } = useParams<{ sessionId: string }>();
const queryClient = useQueryClient();
const sessions = queryClient.getQueryData<SessionEntry[]>(['OC_SESSIONS']);
const sessionModel = sessions?.find((s) => s.id === sessionId)?.model;
const opencode = useOpenCode(sessionId, sessionModel);
const openCodeModels = useVisibleOpenCodeModels();
return (
<div className="flex items-center justify-center h-full md:p-4">
<div className="flex flex-col w-full h-full md:w-3/4 md:h-3/4 lg:w-1/2 lg:h-1/2">
<ChatPanel chat={opencode} provider="opencode" availableModels={openCodeModels} />
</div>
</div>
);
};
const ClaudeNewChatInner = ({ onProviderChange }: { onProviderChange: (p: 'claude' | 'opencode') => void }) => {
const claude = useClaude();
const claudeModels = useVisibleClaudeModels();
return (
<ChatPanel chat={claude} provider="claude" availableModels={claudeModels} onProviderChange={onProviderChange} />
);
};
const OpenCodeNewChatInner = ({ onProviderChange }: { onProviderChange: (p: 'claude' | 'opencode') => void }) => {
const opencode = useOpenCode();
const openCodeModels = useVisibleOpenCodeModels();
return (
<ChatPanel
chat={opencode}
provider="opencode"
availableModels={openCodeModels}
onProviderChange={onProviderChange}
/>
);
};
export const NewChat = () => {
const [provider, setProvider] = useState<'claude' | 'opencode'>('claude');
return (
<div className="flex items-center justify-center h-full md:p-4">
<div className="flex flex-col w-full h-full md:w-3/4 md:h-3/4 lg:w-1/2 lg:h-1/2">
{provider === 'claude' ? (
<ClaudeNewChatInner key="claude" onProviderChange={setProvider} />
) : (
<OpenCodeNewChatInner key="opencode" onProviderChange={setProvider} />
)}
</div>
</div>
);
};
export {};