feat(app): UI parity with Pencil mockup — top bar, panel cards, sidebar/event-center polish
Top bar (breadcrumb + actions + account), rounded panel cards with active accent + rich headers, sidebar count pills/collapsible groups/daemon footer, preset chips + scrollback pill, Event Center tabs + external-notify footer, JetBrains Mono + Inter via @fontsource, shared theme tokens. Backend-absent pieces are mocked (search, zoom, uptime, channels) pending SP1–SP5. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import { FolderGit2, PanelRight, Search, Bell, Settings, ChevronDown } from "lucide-react";
|
||||
import { COLORS, FONT } from "./theme";
|
||||
import type { WorkspaceView } from "./layoutTypes";
|
||||
import { leafIds } from "./layoutTypes";
|
||||
|
||||
/** Human-readable descriptor of the active workspace layout (mock until a real preset id is tracked). */
|
||||
function describeLayout(w: WorkspaceView | null): string {
|
||||
if (!w || !w.layout) return "no layout";
|
||||
const n = leafIds(w.layout).length;
|
||||
return n === 1 ? "1 pane" : `${n} panes`;
|
||||
}
|
||||
|
||||
function IconBtn({ icon, onClick, active, title }: { icon: React.ReactNode; onClick?: () => void; active?: boolean; title?: string }) {
|
||||
return (
|
||||
<button
|
||||
title={title}
|
||||
onClick={onClick}
|
||||
style={{
|
||||
display: "flex", alignItems: "center", justifyContent: "center",
|
||||
width: 26, height: 26, borderRadius: 6,
|
||||
background: active ? COLORS.bgElevated : "transparent",
|
||||
border: active ? `1px solid ${COLORS.borderSubtle}` : "1px solid transparent",
|
||||
color: active ? COLORS.textPrimary : COLORS.textSecondary,
|
||||
}}
|
||||
>
|
||||
{icon}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export function TopBar({
|
||||
active, eventsOpen, onToggleEvents,
|
||||
}: {
|
||||
active: WorkspaceView | null;
|
||||
eventsOpen: boolean;
|
||||
onToggleEvents: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "flex", alignItems: "center", height: 40, flex: "0 0 40px",
|
||||
padding: "0 14px", gap: 12, background: COLORS.bgApp,
|
||||
borderBottom: `1px solid ${COLORS.borderSubtle}`,
|
||||
}}
|
||||
>
|
||||
{/* macOS traffic-light spacer — real lights are drawn by the window chrome. */}
|
||||
<div style={{ width: 60, flex: "0 0 60px" }} />
|
||||
|
||||
{/* Workspace breadcrumb */}
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 8, minWidth: 0 }}>
|
||||
<FolderGit2 size={15} color={COLORS.textSecondary} />
|
||||
<span style={{ fontFamily: FONT.ui, fontSize: 13, fontWeight: 600, color: COLORS.textPrimary, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
|
||||
{active?.name ?? "spacesh"}
|
||||
</span>
|
||||
{active && (
|
||||
<>
|
||||
<span style={{ fontFamily: FONT.ui, fontSize: 13, color: COLORS.textMuted }}>/</span>
|
||||
<span style={{ fontFamily: FONT.ui, fontSize: 13, color: COLORS.textSecondary, whiteSpace: "nowrap" }}>
|
||||
{describeLayout(active)}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div style={{ flex: 1 }} />
|
||||
|
||||
{/* Right cluster */}
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 6 }}>
|
||||
<IconBtn icon={<PanelRight size={15} />} onClick={onToggleEvents} active={eventsOpen} title="Toggle Event Center" />
|
||||
<IconBtn icon={<Search size={16} />} title="Search (mock)" />
|
||||
<IconBtn icon={<Bell size={16} />} title="Notifications (mock)" />
|
||||
<IconBtn icon={<Settings size={16} />} title="Settings (mock)" />
|
||||
<span style={{ width: 1, height: 18, background: COLORS.borderStrong, margin: "0 2px" }} />
|
||||
<button
|
||||
title="Account (mock)"
|
||||
style={{
|
||||
display: "flex", alignItems: "center", gap: 6, height: 26, padding: "0 4px 0 4px",
|
||||
background: "transparent", border: "1px solid transparent", borderRadius: 6, color: COLORS.textSecondary,
|
||||
}}
|
||||
>
|
||||
<span style={{ width: 20, height: 20, borderRadius: "50%", background: COLORS.accent, display: "flex", alignItems: "center", justifyContent: "center", fontFamily: FONT.ui, fontSize: 11, fontWeight: 700, color: "#fff" }}>
|
||||
V
|
||||
</span>
|
||||
<ChevronDown size={13} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user