PicoBot/web/src/components/ConnectionStatus.tsx
oudecheng eaee29841d feat(web): 对齐 deepseek-harness 设计语言,重构前端视觉与三栏布局
- 设计 token 重映射为 DeepSeek 调色板(深浅双主题),正文改无衬线字体栈,全面去霓虹化
- 移除顶部 Header,控件迁入左栏(Logo/连接/通道/会话/tabs/底部操作区),左右栏支持拖拽调宽并持久化,折叠为图标 rail
- 对话区对齐 DeepSeek 聊天风:hero/docked 状态机、736px 居中列、用户右对齐柔和气泡、助手无气泡平铺、composer 卡片与反差发送键;子智能体点击导航完整保留
- 全功能区同步换肤:侧栏列表、右栏面板、ConfigPage、弹窗、选择器等
- fix: 修复 virtual-core 3.17.x 陈旧行高导致消息行重叠(宽度变化/滚动停止后强制 resizeItem 重测)
- fix: 修复 ConfigPage/Modal 引用不存在的 fadeIn/scaleIn keyframes 致入场动画失效
2026-08-14 19:15:45 +08:00

69 lines
2.0 KiB
TypeScript

import { Wifi, WifiOff, Loader2 } from 'lucide-react';
import type { ConnectionStatus } from '../types/protocol';
interface ConnectionStatusProps {
status: ConnectionStatus;
/** rail 紧凑模式:仅显示图标 */
compact?: boolean;
}
export function ConnectionStatus({ status, compact = false }: ConnectionStatusProps) {
const getStatusConfig = () => {
switch (status) {
case 'connecting':
return {
icon: <Loader2 className={`animate-spin ${compact ? 'h-4 w-4' : 'h-3 w-3'}`} />,
text: '连接中',
className:
'text-[var(--accent-amber)] bg-[var(--accent-amber)]/10 border-[var(--accent-amber)]/30',
};
case 'connected':
return {
icon: <Wifi className={compact ? 'h-4 w-4' : 'h-3 w-3'} />,
text: '已连接',
className:
'text-[var(--accent-green)] bg-[var(--accent-green)]/10 border-[var(--accent-green)]/30',
};
case 'disconnected':
return {
icon: <WifiOff className={compact ? 'h-4 w-4' : 'h-3 w-3'} />,
text: '已断开',
className:
'text-[var(--text-muted)] bg-[var(--overlay-dim)] border-[var(--border-color)]',
};
case 'error':
return {
icon: <WifiOff className={compact ? 'h-4 w-4' : 'h-3 w-3'} />,
text: '连接错误',
className:
'text-[rgb(242,90,90)] bg-[rgb(242,90,90)]/10 border-[rgb(242,90,90)]/30',
};
}
};
const config = getStatusConfig();
if (!config) return null;
if (compact) {
return (
<div
className={`flex h-8 w-8 items-center justify-center rounded-lg border ${config.className}`}
title={config.text}
aria-label={config.text}
>
{config.icon}
</div>
);
}
return (
<div
className={`inline-flex w-fit items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs ${config.className}`}
>
{config.icon}
<span>{config.text}</span>
</div>
);
}