feat(frontend): M9 模态 UI(mode 系统+共享 store+WS 客户端 + chat(思维链/工具回显/情绪徽标)/code/Agent 监控/后台思考页 + Miuix 设计 token + PWA);tsc+vite build 通过
This commit is contained in:
1 parent
b3ffd51736
commit
4c48e94659
40 files changed
+5321
No files matched your search
@@ -0,0 +1,58 @@
|
||||
import { useState } from "react";
|
||||
import { useAppStore } from "../store/useAppStore";
|
||||
import { useModeStore } from "../store/useModeStore";
|
||||
import { applyTheme, readTheme, type ThemeMode } from "../lib/theme";
|
||||
import type { WsStatus } from "../lib/types";
|
||||
import { Tag } from "./primitives";
|
||||
|
||||
const wsMeta: Record<WsStatus, { label: string; tone: "ok" | "warn" | "neutral" | "err" }> = {
|
||||
idle: { label: "未连接", tone: "neutral" },
|
||||
connecting: { label: "连接中", tone: "warn" },
|
||||
connected: { label: "实时", tone: "ok" },
|
||||
reconnecting: { label: "重连中", tone: "warn" },
|
||||
disconnected: { label: "已断开", tone: "err" },
|
||||
};
|
||||
|
||||
export function TopBar(): React.ReactNode {
|
||||
const wsStatus = useAppStore((s) => s.wsStatus);
|
||||
const mood = useAppStore((s) => s.mood);
|
||||
const mode = useModeStore((s) => s.mode);
|
||||
const [theme, setTheme] = useState<ThemeMode>(readTheme);
|
||||
|
||||
const toggleTheme = () => {
|
||||
const next: ThemeMode = theme === "dark" ? "light" : "dark";
|
||||
applyTheme(next);
|
||||
setTheme(next);
|
||||
};
|
||||
|
||||
const meta = wsMeta[wsStatus];
|
||||
|
||||
return (
|
||||
<header className="glass sticky top-0 z-30 flex h-[var(--mu-topbar-h)] items-center gap-3 border-b border-[var(--mu-glass-border)] px-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<img src="/icon.svg" alt="Cyrene" className="h-7 w-7" />
|
||||
<div className="leading-tight">
|
||||
<div className="text-sm font-semibold">Cyrene · 昔涟</div>
|
||||
<div className="text-[11px] text-[var(--mu-text-lo)]">{mode} 模式</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1" />
|
||||
|
||||
{mood ? <Tag tone="accent">心情 · {mood}</Tag> : null}
|
||||
|
||||
<Tag tone={meta.tone}>
|
||||
<span className={`inline-block h-1.5 w-1.5 rounded-full ${wsStatus === "connected" ? "bg-[var(--mu-ok)]" : "mu-blink"}`} />
|
||||
{meta.label}
|
||||
</Tag>
|
||||
|
||||
<button
|
||||
onClick={toggleTheme}
|
||||
aria-label="切换主题"
|
||||
className="inline-flex h-8 w-8 items-center justify-center rounded-[var(--mu-radius)] bg-[var(--mu-surface-4)] text-sm transition-all duration-200 ease-[var(--mu-spring)] hover:bg-[var(--mu-surface-5)] active:scale-95"
|
||||
>
|
||||
{theme === "dark" ? "☀" : "☾"}
|
||||
</button>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user