feat(frontend): minimal central area; WIP icon above composer toggles model-activity panel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { useSessionStream } from "../stream/useSessionStream";
|
||||
import { useSessionStore } from "../store/sessionStore";
|
||||
import { WidgetHost } from "./WidgetHost";
|
||||
import { Transcript } from "./Transcript";
|
||||
import { CentralStatus } from "./CentralStatus";
|
||||
import { ModelActivityPanel } from "./ModelActivityPanel";
|
||||
import { NavSessions } from "./NavSessions";
|
||||
import { SessionMenu } from "./SessionMenu";
|
||||
import { SessionDocumentsPanel } from "./SessionDocumentsPanel";
|
||||
@@ -36,6 +37,7 @@ export function AppShell() {
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const [panelSession, setPanelSession] = useState<SessionSummary | null>(null);
|
||||
const [showActivity, setShowActivity] = useState(false);
|
||||
const [activeOpen, setActiveOpen] = useState(true);
|
||||
const [archiveOpen, setArchiveOpen] = useState(false);
|
||||
const [renameTarget, setRenameTarget] = useState<SessionSummary | null>(null);
|
||||
@@ -53,7 +55,14 @@ export function AppShell() {
|
||||
|
||||
function openPanel(id: string) {
|
||||
const s = sessions.find((x) => x.id === id);
|
||||
if (s) setPanelSession(s);
|
||||
if (s) { setPanelSession(s); setShowActivity(false); }
|
||||
}
|
||||
function toggleActivity() {
|
||||
setShowActivity((v) => {
|
||||
const next = !v;
|
||||
if (next) setPanelSession(null);
|
||||
return next;
|
||||
});
|
||||
}
|
||||
async function doResume(id: string) {
|
||||
try {
|
||||
@@ -151,6 +160,7 @@ export function AppShell() {
|
||||
onResume={doResume}
|
||||
/>
|
||||
)}
|
||||
{showActivity && <ModelActivityPanel onClose={() => setShowActivity(false)} />}
|
||||
|
||||
{/* Conversation column */}
|
||||
<div className="flex min-w-0 flex-1 flex-col">
|
||||
@@ -166,7 +176,7 @@ export function AppShell() {
|
||||
<div className="mx-auto flex max-w-3xl flex-col gap-6">
|
||||
{activeSessionId ? (
|
||||
<>
|
||||
<Transcript />
|
||||
<CentralStatus />
|
||||
<WidgetHost sessionId={activeSessionId} />
|
||||
</>
|
||||
) : (
|
||||
@@ -178,6 +188,20 @@ export function AppShell() {
|
||||
{/* Sticky composer: the box stays pinned while the conversation scrolls above. */}
|
||||
<div className="shrink-0 px-6 pb-6 pt-2">
|
||||
<div className="mx-auto max-w-3xl">
|
||||
{activeSessionId && (
|
||||
<div className="mb-1.5 flex justify-start">
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleActivity}
|
||||
aria-label="Model activity"
|
||||
aria-pressed={showActivity}
|
||||
title="Model activity"
|
||||
className="grid size-7 place-items-center rounded-md border border-border text-primary transition-colors hover:bg-muted"
|
||||
>
|
||||
<WorkingSpinner spinning={working} />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div className="rounded-2xl border border-input bg-card shadow-sm transition-colors focus-within:border-primary/40 focus-within:ring-3 focus-within:ring-ring/15">
|
||||
<div className="px-2.5 py-2">
|
||||
<SteerInput
|
||||
@@ -196,9 +220,6 @@ export function AppShell() {
|
||||
{/* Right session rail — symmetric to the portal's left sidebar */}
|
||||
<aside className="flex w-[280px] shrink-0 flex-col border-l border-border bg-sidebar">
|
||||
<div className="relative px-4 pb-3 pt-5 text-center">
|
||||
{working && (
|
||||
<WorkingSpinner className="absolute left-4 top-[1.35rem]" />
|
||||
)}
|
||||
<h1 className="font-heading text-xl font-semibold leading-none tracking-tight text-foreground">
|
||||
Thoth<span className="text-primary">II</span>
|
||||
</h1>
|
||||
@@ -347,14 +368,14 @@ export function AppShell() {
|
||||
}
|
||||
|
||||
/** Brand-tinted spinner shown while the assistant/harness is working. */
|
||||
function WorkingSpinner({ className }: { className?: string }) {
|
||||
function WorkingSpinner({ className, spinning = true }: { className?: string; spinning?: boolean }) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
role="status"
|
||||
aria-label="Assistant is working"
|
||||
className={["size-4 animate-spin text-primary", className].filter(Boolean).join(" ")}
|
||||
className={["size-4 text-primary", spinning ? "animate-spin" : "", className].filter(Boolean).join(" ")}
|
||||
>
|
||||
<circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="3" opacity="0.2" />
|
||||
<path d="M21 12a9 9 0 0 0-9-9" stroke="currentColor" strokeWidth="3" strokeLinecap="round" />
|
||||
|
||||
Reference in New Issue
Block a user