fix(ui): dark-theme colors in discussion session — replace light-mode Tailwind classes
ChatMessage, DiscussionPanel, ReasoningPanel, ModeSwitchMarker: swap all hard-coded light-mode colors (bg-slate-*, text-slate-7xx, bg-amber-50, bg-gray-*, border-gray-200, bg-white) for dark-theme tokens (text-foreground, text-muted-foreground, border-border, bg-card, bg-white/5, bg-amber-500/10) that match the existing dark glass-panel design system. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e156ef897e
commit
f626d2534b
4 changed files with 76 additions and 80 deletions
|
|
@ -79,7 +79,7 @@ const ChatMessage = ({ message, persona, toggleHighlight, participants = [], foc
|
|||
id={`message-${message.id}`}
|
||||
className={cn(
|
||||
"flex items-start p-3 rounded-lg transition-colors",
|
||||
message.highlighted ? "bg-amber-50 border border-amber-200" : "hover:bg-slate-50",
|
||||
message.highlighted ? "bg-amber-500/10 border border-amber-500/30" : "hover:bg-white/5",
|
||||
isModerator ? "border-l-4 border-l-primary pl-4" : "",
|
||||
isFacilitator ? "border-l-4 border-l-green-500 pl-4" : ""
|
||||
)}
|
||||
|
|
@ -93,20 +93,20 @@ const ChatMessage = ({ message, persona, toggleHighlight, participants = [], foc
|
|||
<Bot className="h-6 w-6 text-primary" />
|
||||
</div>
|
||||
) : isFacilitator ? (
|
||||
<div className="bg-green-100 p-2 rounded-full">
|
||||
<User className="h-6 w-6 text-green-600" />
|
||||
<div className="bg-green-500/15 p-2 rounded-full">
|
||||
<User className="h-6 w-6 text-green-400" />
|
||||
</div>
|
||||
) : persona ? (
|
||||
<div className="bg-slate-100 p-2 rounded-full">
|
||||
<img
|
||||
src={getPersonaAvatarSrc(persona)}
|
||||
alt={`${persona.name} avatar`}
|
||||
className="h-6 w-6 rounded-full object-cover"
|
||||
<div className="bg-white/10 p-2 rounded-full">
|
||||
<img
|
||||
src={getPersonaAvatarSrc(persona)}
|
||||
alt={`${persona.name} avatar`}
|
||||
className="h-6 w-6 rounded-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-slate-100 p-2 rounded-full">
|
||||
<UserCircle className="h-6 w-6 text-slate-600" />
|
||||
<div className="bg-white/10 p-2 rounded-full">
|
||||
<UserCircle className="h-6 w-6 text-muted-foreground" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -123,12 +123,12 @@ const ChatMessage = ({ message, persona, toggleHighlight, participants = [], foc
|
|||
</Badge>
|
||||
)}
|
||||
|
||||
<span className="text-xs text-slate-500 ml-auto">
|
||||
<span className="text-xs text-muted-foreground ml-auto">
|
||||
{message.timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<p className="text-slate-700">
|
||||
<p className="text-foreground">
|
||||
{!message.text || message.text.trim() === '' || message.text === '...' ? (
|
||||
<span className="text-red-500 italic">
|
||||
[No response content - AI generation may have failed]
|
||||
|
|
@ -140,12 +140,12 @@ const ChatMessage = ({ message, persona, toggleHighlight, participants = [], foc
|
|||
|
||||
{/* Display creative asset if this is a moderator/facilitator message with an asset */}
|
||||
{hasCreativeAsset && assetInfo && (
|
||||
<div className="mt-3 p-3 border rounded-lg bg-slate-50">
|
||||
<div className="mt-3 p-3 border border-border rounded-lg bg-white/5">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<ImageIcon className="h-4 w-4 text-slate-600" />
|
||||
<span className="text-sm font-medium text-slate-700">Creative Asset</span>
|
||||
<ImageIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium text-foreground">Creative Asset</span>
|
||||
{assetInfo.displayReference !== assetInfo.filename && (
|
||||
<span className="text-xs text-slate-500">({assetInfo.displayReference})</span>
|
||||
<span className="text-xs text-muted-foreground">({assetInfo.displayReference})</span>
|
||||
)}
|
||||
</div>
|
||||
<img
|
||||
|
|
|
|||
|
|
@ -1185,7 +1185,7 @@ const DiscussionPanel = ({
|
|||
)
|
||||
))}
|
||||
{(isTyping || effectiveAiModeActive) && (
|
||||
<div className="flex items-center space-x-2 text-sm text-slate-500 animate-pulse">
|
||||
<div className="flex items-center space-x-2 text-sm text-muted-foreground animate-pulse">
|
||||
<div className="bg-primary/10 p-2 rounded-full">
|
||||
{effectiveAiModeActive ? (
|
||||
<Bot className="h-4 w-4 text-primary animate-spin" />
|
||||
|
|
@ -1229,21 +1229,21 @@ const DiscussionPanel = ({
|
|||
/>
|
||||
|
||||
{/* Control panel - pinned to bottom */}
|
||||
<div className="pt-4 border-t border-slate-200 w-full">
|
||||
<div className="pt-4 border-t border-border w-full">
|
||||
{/* Show selected file indicator */}
|
||||
{selectedFile && (
|
||||
<div className="mb-2 p-2 bg-blue-50 border border-blue-200 rounded-md flex items-center justify-between">
|
||||
<div className="mb-2 p-2 bg-blue-500/10 border border-blue-500/30 rounded-md flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Paperclip className="h-4 w-4 text-blue-600" />
|
||||
<span className="text-sm text-blue-700">{selectedFile.name}</span>
|
||||
<span className="text-xs text-blue-500">({(selectedFile.size / 1024 / 1024).toFixed(1)} MB)</span>
|
||||
<Paperclip className="h-4 w-4 text-blue-400" />
|
||||
<span className="text-sm text-blue-300">{selectedFile.name}</span>
|
||||
<span className="text-xs text-blue-400/70">({(selectedFile.size / 1024 / 1024).toFixed(1)} MB)</span>
|
||||
</div>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={clearSelectedFile}
|
||||
className="h-6 w-6 p-0 text-blue-600 hover:text-blue-800"
|
||||
className="h-6 w-6 p-0 text-blue-400 hover:text-blue-200"
|
||||
>
|
||||
×
|
||||
</Button>
|
||||
|
|
@ -1298,7 +1298,7 @@ const DiscussionPanel = ({
|
|||
|
||||
<div className="flex justify-between items-center mt-3">
|
||||
<div className="flex items-center space-x-2">
|
||||
<p className="text-sm text-slate-500">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{isSpeaking ? 'Speaking...' :
|
||||
effectiveAiModeActive ? 'AI mode active' :
|
||||
'Manual moderation mode'}
|
||||
|
|
@ -1313,7 +1313,7 @@ const DiscussionPanel = ({
|
|||
className={`hover-transition ${
|
||||
effectiveAiModeActive
|
||||
? 'bg-red-50 text-red-600 hover:bg-red-100'
|
||||
: 'bg-blue-50 text-blue-600 hover:bg-blue-100'
|
||||
: 'bg-blue-500/10 text-blue-400 hover:bg-blue-500/20'
|
||||
}`}
|
||||
title={effectiveAiModeActive ? "Stop AI mode and return to manual" : "Start autonomous AI conversation"}
|
||||
>
|
||||
|
|
@ -1346,7 +1346,7 @@ const DiscussionPanel = ({
|
|||
scrollToBottom();
|
||||
}
|
||||
}}
|
||||
className={`hover-transition ${autoScroll ? 'bg-blue-50 text-blue-600 hover:bg-blue-100' : ''}`}
|
||||
className={`hover-transition ${autoScroll ? 'bg-blue-500/10 text-blue-400 hover:bg-blue-500/20' : ''}`}
|
||||
title={autoScroll ? 'Disable auto-scroll' : 'Enable auto-scroll'}
|
||||
>
|
||||
<ArrowDown className="h-3 w-3 mr-1" />
|
||||
|
|
@ -1386,7 +1386,7 @@ const DiscussionPanel = ({
|
|||
{/* Show AI mode status and controls */}
|
||||
{effectiveAiModeActive && (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-1 text-sm text-slate-600">
|
||||
<div className="flex items-center gap-1 text-sm text-muted-foreground">
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
|
||||
<span>AI Active</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -25,29 +25,29 @@ const ModeSwitchMarker = ({ modeEvent }: ModeSwitchMarkerProps) => {
|
|||
const getEventColor = (eventType: string) => {
|
||||
switch (eventType) {
|
||||
case 'ai_mode_started':
|
||||
return 'text-blue-600';
|
||||
return 'text-blue-400';
|
||||
case 'manual_mode_started':
|
||||
return 'text-slate-600';
|
||||
return 'text-muted-foreground';
|
||||
case 'ai_session_concluded':
|
||||
return 'text-green-600';
|
||||
return 'text-green-400';
|
||||
default:
|
||||
return 'text-gray-600';
|
||||
return 'text-muted-foreground';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center my-6 px-4">
|
||||
<div className="flex-1 border-t border-gray-200"></div>
|
||||
<div className={`mx-4 px-3 py-1 bg-white border border-gray-200 rounded-full ${getEventColor(modeEvent.event_type)}`}>
|
||||
<div className="flex-1 border-t border-border"></div>
|
||||
<div className={`mx-4 px-3 py-1 bg-card border border-border rounded-full ${getEventColor(modeEvent.event_type)}`}>
|
||||
<div className="flex items-center space-x-2 text-xs font-medium">
|
||||
<span>{getEventText(modeEvent.event_type)}</span>
|
||||
<span className="text-gray-400">at</span>
|
||||
<span className="text-muted-foreground">at</span>
|
||||
<span>{formatTime(modeEvent.timestamp)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 border-t border-gray-200"></div>
|
||||
<div className="flex-1 border-t border-border"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModeSwitchMarker;
|
||||
export default ModeSwitchMarker;
|
||||
|
|
|
|||
|
|
@ -18,34 +18,34 @@ interface ReasoningPanelProps {
|
|||
reasoningHistory: ReasoningEntry[];
|
||||
isVisible: boolean;
|
||||
onToggle: () => void;
|
||||
isAiMode?: boolean; // Whether the focus group is in AI mode
|
||||
isAiMode?: boolean;
|
||||
}
|
||||
|
||||
const ActionIcon = ({ action }: { action: string }) => {
|
||||
switch (action) {
|
||||
case 'moderator_speak':
|
||||
return <MessageSquare className="h-4 w-4 text-blue-500" />;
|
||||
return <MessageSquare className="h-4 w-4 text-blue-400" />;
|
||||
case 'participant_respond':
|
||||
return <Users className="h-4 w-4 text-green-500" />;
|
||||
return <Users className="h-4 w-4 text-green-400" />;
|
||||
case 'participant_interaction':
|
||||
return <Users className="h-4 w-4 text-primary" />;
|
||||
case 'probe_trigger':
|
||||
return <Zap className="h-4 w-4 text-orange-500" />;
|
||||
return <Zap className="h-4 w-4 text-orange-400" />;
|
||||
case 'end_session':
|
||||
return <AlertTriangle className="h-4 w-4 text-red-500" />;
|
||||
return <AlertTriangle className="h-4 w-4 text-red-400" />;
|
||||
default:
|
||||
return <Brain className="h-4 w-4 text-gray-500" />;
|
||||
return <Brain className="h-4 w-4 text-muted-foreground" />;
|
||||
}
|
||||
};
|
||||
|
||||
const StatusIcon = ({ status }: { status: string }) => {
|
||||
switch (status) {
|
||||
case 'success':
|
||||
return <CheckCircle className="h-3 w-3 text-green-500" />;
|
||||
return <CheckCircle className="h-3 w-3 text-green-400" />;
|
||||
case 'error':
|
||||
return <XCircle className="h-3 w-3 text-red-500" />;
|
||||
return <XCircle className="h-3 w-3 text-red-400" />;
|
||||
case 'pending':
|
||||
return <Clock className="h-3 w-3 text-yellow-500 animate-pulse" />;
|
||||
return <Clock className="h-3 w-3 text-yellow-400 animate-pulse" />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
@ -75,10 +75,10 @@ const ReasoningEntry = ({ entry, isLatest }: { entry: ReasoningEntry; isLatest:
|
|||
const [isExpanded, setIsExpanded] = useState(isLatest);
|
||||
|
||||
return (
|
||||
<Card className={`mb-2 ${isLatest ? 'ring-2 ring-blue-200 bg-blue-50/50' : ''}`}>
|
||||
<Card className={`mb-2 ${isLatest ? 'ring-2 ring-blue-500/30 bg-blue-500/10' : ''}`}>
|
||||
<Collapsible open={isExpanded} onOpenChange={setIsExpanded}>
|
||||
<CollapsibleTrigger asChild>
|
||||
<CardHeader className="pb-2 cursor-pointer hover:bg-gray-50/50 transition-colors">
|
||||
<CardHeader className="pb-2 cursor-pointer hover:bg-white/5 transition-colors">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<ActionIcon action={entry.action} />
|
||||
|
|
@ -89,7 +89,7 @@ const ReasoningEntry = ({ entry, isLatest }: { entry: ReasoningEntry; isLatest:
|
|||
</span>
|
||||
<StatusIcon status={entry.execution_status} />
|
||||
</div>
|
||||
<span className="text-xs text-gray-500">
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{formatTimestamp(entry.timestamp)}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -101,9 +101,9 @@ const ReasoningEntry = ({ entry, isLatest }: { entry: ReasoningEntry; isLatest:
|
|||
</Badge>
|
||||
)}
|
||||
{isExpanded ? (
|
||||
<ChevronUp className="h-4 w-4 text-gray-400" />
|
||||
<ChevronUp className="h-4 w-4 text-muted-foreground" />
|
||||
) : (
|
||||
<ChevronDown className="h-4 w-4 text-gray-400" />
|
||||
<ChevronDown className="h-4 w-4 text-muted-foreground" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -113,31 +113,31 @@ const ReasoningEntry = ({ entry, isLatest }: { entry: ReasoningEntry; isLatest:
|
|||
<CardContent className="pt-0">
|
||||
<div className="space-y-2">
|
||||
<div>
|
||||
<h4 className="text-sm font-medium text-gray-700 mb-1">AI Reasoning:</h4>
|
||||
<p className="text-sm text-gray-600 bg-gray-50 p-2 rounded italic">
|
||||
<h4 className="text-sm font-medium text-foreground mb-1">AI Reasoning:</h4>
|
||||
<p className="text-sm text-muted-foreground bg-white/5 p-2 rounded italic">
|
||||
"{entry.reasoning}"
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
{entry.details && Object.keys(entry.details).length > 0 && (
|
||||
<div>
|
||||
<h4 className="text-sm font-medium text-gray-700 mb-1">Details:</h4>
|
||||
<div className="text-xs text-gray-600 bg-gray-50 p-2 rounded font-mono">
|
||||
<h4 className="text-sm font-medium text-foreground mb-1">Details:</h4>
|
||||
<div className="text-xs text-muted-foreground bg-white/5 p-2 rounded font-mono">
|
||||
{JSON.stringify(entry.details, null, 2)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{entry.execution_result && (
|
||||
<div>
|
||||
<h4 className="text-sm font-medium text-gray-700 mb-1">
|
||||
<h4 className="text-sm font-medium text-foreground mb-1">
|
||||
Execution Result:
|
||||
</h4>
|
||||
<div className="text-xs text-gray-600 bg-gray-50 p-2 rounded">
|
||||
<div className="text-xs text-muted-foreground bg-white/5 p-2 rounded">
|
||||
{entry.execution_result.error ? (
|
||||
<span className="text-red-600">Error: {entry.execution_result.error}</span>
|
||||
<span className="text-red-400">Error: {entry.execution_result.error}</span>
|
||||
) : (
|
||||
<span className="text-green-600">
|
||||
<span className="text-green-400">
|
||||
{entry.execution_result.message || 'Success'}
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -155,10 +155,8 @@ const ReasoningEntry = ({ entry, isLatest }: { entry: ReasoningEntry; isLatest:
|
|||
const ReasoningPanel = ({ reasoningHistory, isVisible, onToggle, isAiMode = false }: ReasoningPanelProps) => {
|
||||
const [autoScroll, setAutoScroll] = useState(true);
|
||||
|
||||
// Auto-expand latest entry when new reasoning arrives
|
||||
useEffect(() => {
|
||||
if (autoScroll && reasoningHistory.length > 0) {
|
||||
// Scroll to top of reasoning panel when new entry arrives
|
||||
const reasoningPanel = document.getElementById('reasoning-panel-content');
|
||||
if (reasoningPanel) {
|
||||
reasoningPanel.scrollTop = 0;
|
||||
|
|
@ -167,10 +165,10 @@ const ReasoningPanel = ({ reasoningHistory, isVisible, onToggle, isAiMode = fals
|
|||
}, [reasoningHistory.length, autoScroll]);
|
||||
|
||||
return (
|
||||
<div className="border-t border-gray-200 bg-white">
|
||||
<div className="border-t border-border bg-card">
|
||||
<Collapsible open={isVisible} onOpenChange={onToggle}>
|
||||
<CollapsibleTrigger asChild>
|
||||
<div className="flex items-center justify-between p-3 cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="flex items-center justify-between p-3 cursor-pointer hover:bg-white/5 transition-colors">
|
||||
<div className="flex items-center gap-2">
|
||||
<Brain className="h-4 w-4 text-primary" />
|
||||
<span className="font-medium text-sm">
|
||||
|
|
@ -188,27 +186,26 @@ const ReasoningPanel = ({ reasoningHistory, isVisible, onToggle, isAiMode = fals
|
|||
)}
|
||||
</div>
|
||||
{isVisible ? (
|
||||
<ChevronUp className="h-4 w-4 text-gray-400" />
|
||||
<ChevronUp className="h-4 w-4 text-muted-foreground" />
|
||||
) : (
|
||||
<ChevronDown className="h-4 w-4 text-gray-400" />
|
||||
<ChevronDown className="h-4 w-4 text-muted-foreground" />
|
||||
)}
|
||||
</div>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<div className="border-t border-gray-100">
|
||||
<div className="border-t border-border">
|
||||
{isAiMode ? (
|
||||
// AI Mode: Show reasoning history
|
||||
reasoningHistory.length === 0 ? (
|
||||
<div className="p-4 text-center text-gray-500">
|
||||
<Brain className="h-8 w-8 mx-auto mb-2 text-gray-300" />
|
||||
<div className="p-4 text-center text-muted-foreground">
|
||||
<Brain className="h-8 w-8 mx-auto mb-2 text-muted-foreground/40" />
|
||||
<p className="text-sm">No AI decisions yet</p>
|
||||
<p className="text-xs text-gray-400">
|
||||
<p className="text-xs text-muted-foreground/70">
|
||||
Reasoning will appear here when the AI makes decisions
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<ScrollArea
|
||||
id="reasoning-panel-content"
|
||||
<ScrollArea
|
||||
id="reasoning-panel-content"
|
||||
className="h-[25vh] p-3"
|
||||
>
|
||||
<div className="space-y-2">
|
||||
|
|
@ -223,14 +220,13 @@ const ReasoningPanel = ({ reasoningHistory, isVisible, onToggle, isAiMode = fals
|
|||
</ScrollArea>
|
||||
)
|
||||
) : (
|
||||
// Manual Mode: Show status and guidance
|
||||
<div className="p-4 text-center text-gray-500">
|
||||
<Settings className="h-8 w-8 mx-auto mb-2 text-gray-400" />
|
||||
<p className="text-sm font-medium text-gray-700">Manual Moderation Mode</p>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
<div className="p-4 text-center text-muted-foreground">
|
||||
<Settings className="h-8 w-8 mx-auto mb-2 text-muted-foreground/60" />
|
||||
<p className="text-sm font-medium text-foreground">Manual Moderation Mode</p>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
You are currently moderating the discussion manually.
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 mt-2">
|
||||
<p className="text-xs text-muted-foreground mt-2">
|
||||
Switch to AI Mode to see automated reasoning and decisions.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -242,4 +238,4 @@ const ReasoningPanel = ({ reasoningHistory, isVisible, onToggle, isAiMode = fals
|
|||
);
|
||||
};
|
||||
|
||||
export default ReasoningPanel;
|
||||
export default ReasoningPanel;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue