摘要: 直版/窄螢幕時辦公室改為滿寬顯示並鎖定 1200:700 比例,側邊面板移到下方; 另新增面板收合按鈕,桌面版也能全畫面看辦公室。 根本原因: 原本任何螢幕都是「辦公室 + 300px 側欄」左右排,SVG 以 meet 等比縮放, 直版視窗寬度受限時上下大量留白,辦公室被壓得很小。 影響: 直版(手機/平板)辦公室寬度從約一半提升到 100%; 窄橫版維持左右排但側欄縮為 232px;桌面版行為不變,多一顆 ⊞ 收合鈕。 修法: - styles.css:orientation: portrait 時 main-row 改 column, floorplan-wrap 用 aspect-ratio 1200/7 00 撐滿寬度,不再靠 flex 留白; ≤900px 壓縮 header(隱藏圖例/副標、按鈕縮小、允許換行) - store 新增 panelOpen/togglePanel,App 據此條件渲染 SidePanel Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
import { STATUS_COLORS, STATUS_LABELS } from "@/lib/constants";
|
||
import { useOfficeStore } from "@/store/office-store";
|
||
import { getDirector, setMode } from "@/sim/runtime";
|
||
import type { AgentStatus } from "@/lib/types";
|
||
|
||
const LEGEND: AgentStatus[] = ["idle", "thinking", "tool_calling", "speaking", "spawning", "error"];
|
||
|
||
export function HeaderBar() {
|
||
const paused = useOfficeStore((s) => s.paused);
|
||
const setPaused = useOfficeStore((s) => s.setPaused);
|
||
const speed = useOfficeStore((s) => s.speed);
|
||
const setSpeed = useOfficeStore((s) => s.setSpeed);
|
||
const theme = useOfficeStore((s) => s.theme);
|
||
const setTheme = useOfficeStore((s) => s.setTheme);
|
||
const mode = useOfficeStore((s) => s.mode);
|
||
const agentCount = useOfficeStore((s) => s.agents.size);
|
||
const panelOpen = useOfficeStore((s) => s.panelOpen);
|
||
|
||
const isLive = mode === "live";
|
||
|
||
return (
|
||
<header className="header">
|
||
<div className="header-brand">
|
||
<span className="header-mark">✳</span>
|
||
<div>
|
||
<h1>Claude Office</h1>
|
||
<p>multi-agent 虛擬辦公室 · {isLive ? "實況模式" : "模擬模式"}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="header-legend">
|
||
{LEGEND.map((s) => (
|
||
<span key={s} className="legend-chip">
|
||
<span className="legend-dot" style={{ backgroundColor: STATUS_COLORS[s] }} />
|
||
{STATUS_LABELS[s]}
|
||
</span>
|
||
))}
|
||
</div>
|
||
|
||
<div className="header-controls">
|
||
<span className="agent-count">{agentCount} agents</span>
|
||
<button
|
||
className={`btn mode-btn ${isLive ? "live-on" : ""}`}
|
||
onClick={() => setMode(isLive ? "sim" : "live")}
|
||
title={isLive ? "切回劇本模擬" : "連上真實 Claude Code 活動 (需 npm run watch)"}
|
||
>
|
||
{isLive ? "● LIVE" : "▶ 模擬"}
|
||
</button>
|
||
{!isLive && (
|
||
<>
|
||
<button className="btn" onClick={() => getDirector().hireAgent()} title="招募一位 agent">
|
||
+ Agent
|
||
</button>
|
||
<button
|
||
className="btn"
|
||
onClick={() => setSpeed(speed >= 4 ? 1 : speed * 2)}
|
||
title="模擬速度"
|
||
>
|
||
{speed}×
|
||
</button>
|
||
</>
|
||
)}
|
||
<button className="btn" onClick={() => setPaused(!paused)} title={paused ? "繼續" : "暫停"}>
|
||
{paused ? "▶" : "⏸"}
|
||
</button>
|
||
<button className="btn" onClick={() => setTheme(theme === "light" ? "dark" : "light")} title="切換主題">
|
||
{theme === "light" ? "🌙" : "☀️"}
|
||
</button>
|
||
<button
|
||
className="btn"
|
||
onClick={() => useOfficeStore.getState().togglePanel()}
|
||
title={panelOpen ? "收合面板,放大辦公室" : "展開面板"}
|
||
>
|
||
{panelOpen ? "⊞" : "⊟"}
|
||
</button>
|
||
</div>
|
||
</header>
|
||
);
|
||
}
|