fix(ui): show workspace readiness dot and bounded session accordions
This commit is contained in:
@@ -193,6 +193,10 @@ export function AppShell({ canLogout }: AppShellProps) {
|
||||
&& preprocessingQuery.data
|
||||
&& preprocessingQuery.data.state !== "ready",
|
||||
);
|
||||
const workspaceReady = Boolean(selectedWorkspaceId && !preprocessingQuery.isError && preprocessingQuery.data?.state === "ready");
|
||||
const workspaceReadinessLabel = t("Workspace readiness: {state}", {
|
||||
state: t(preprocessingQuery.isError ? "unavailable" : preprocessingQuery.data?.state ?? "checking"),
|
||||
});
|
||||
const { data: sessions = [], isSuccess: sessionsLoaded } = useQuery<SessionSummary[]>({
|
||||
queryKey: ["sessions", sessionScope],
|
||||
queryFn: async () => {
|
||||
@@ -951,7 +955,7 @@ export function AppShell({ canLogout }: AppShellProps) {
|
||||
{/* Right session rail */}
|
||||
{(
|
||||
<ArchiveNavigation surface={activeSurface} forceDrawer={activeSurface === "core" && showActivity}>
|
||||
<aside aria-label={t("Session navigation")} className="flex w-64 shrink-0 flex-col bg-sidebar">
|
||||
<aside aria-label={t("Session navigation")} className="flex min-h-0 w-64 shrink-0 flex-col bg-sidebar">
|
||||
<div className="thot-session-navigation__header relative text-center">
|
||||
<h1 className="thot-wordmark--sidebar font-heading text-[2rem] font-semibold leading-none tracking-tight text-foreground">
|
||||
Thoth<span className="text-primary">II</span>
|
||||
@@ -1046,12 +1050,16 @@ export function AppShell({ canLogout }: AppShellProps) {
|
||||
size="sm"
|
||||
className="w-full min-w-0 max-w-full gap-[0.25rem] px-[0.75rem]"
|
||||
aria-current={currentNavigation === "workspace" ? "page" : undefined}
|
||||
aria-label={t("Workspace")}
|
||||
aria-describedby="workspace-readiness-indicator"
|
||||
title={workspaceReadinessLabel}
|
||||
data-navigation-state={currentNavigation === "workspace" ? "current" : "available"}
|
||||
onClick={() => {
|
||||
if (!canLeaveDatabaseManagement()) return;
|
||||
navigate({ surface: "workspace-management" }, true);
|
||||
}}
|
||||
>{t("Workspace")}</Button>
|
||||
>{t("Workspace")}<span id="workspace-readiness-indicator" role="img" aria-label={workspaceReadinessLabel}
|
||||
data-ready={workspaceReady} className={`ml-1 size-2 shrink-0 rounded-full ${workspaceReady ? "bg-[oklch(var(--success))]" : "bg-destructive"}`} /></Button>
|
||||
<Button
|
||||
variant={currentNavigation === "pi" ? "navigationActive" : "outline"}
|
||||
size="sm"
|
||||
@@ -1065,8 +1073,6 @@ export function AppShell({ canLogout }: AppShellProps) {
|
||||
navigate({ surface: "pi-management" }, true);
|
||||
}}
|
||||
>{t("Pi configuration")}</Button>
|
||||
<Button variant="ghost" size="sm" className="w-full min-w-0 whitespace-normal" onClick={() => navigate({ surface: "workspace-management", workspace: selectedWorkspaceId })}>{t("Workspace readiness: {state}", { state: t(preprocessingQuery.isError ? "unavailable" : preprocessingQuery.data?.state ?? "checking") })}
|
||||
</Button>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion.Root>
|
||||
@@ -1154,18 +1160,18 @@ export function AppShell({ canLogout }: AppShellProps) {
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex-1 overflow-y-auto px-2 pb-4">
|
||||
{/* L2 — section toggle */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActiveOpen((v) => !v)}
|
||||
aria-expanded={activeOpen}
|
||||
className="thot-label flex w-full items-center gap-1 px-1 pb-1 pt-1 text-left text-foreground/65 hover:text-foreground"
|
||||
>
|
||||
<span className="select-none">{activeOpen ? "▾" : "▸"}</span>
|
||||
<span>{t("Active sessions")}</span>
|
||||
</button>
|
||||
{activeOpen && (
|
||||
<Accordion.Root multiple
|
||||
value={[...(activeOpen ? ["active"] : []), ...(archiveOpen ? ["archive"] : [])]}
|
||||
onValueChange={value => { setActiveOpen(value.includes("active")); setArchiveOpen(value.includes("archive")); }}
|
||||
className="thot-session-accordion min-h-0 flex-1 overflow-y-auto px-2 pb-4">
|
||||
<Accordion.Item value="active" className="thot-session-accordion__item">
|
||||
<Accordion.Header className="m-0">
|
||||
<Accordion.Trigger className="thot-session-accordion__trigger">
|
||||
<span>{t("Active sessions")}</span>
|
||||
<ChevronDown aria-hidden="true" className={`size-4 shrink-0 ${activeOpen ? "rotate-180" : ""}`} />
|
||||
</Accordion.Trigger>
|
||||
</Accordion.Header>
|
||||
<Accordion.Panel className="thot-session-accordion__panel" tabIndex={0}>
|
||||
<div className="flex flex-col gap-3 pb-2">
|
||||
{groups.map((g) => (
|
||||
<div key={g}>
|
||||
@@ -1217,19 +1223,16 @@ export function AppShell({ canLogout }: AppShellProps) {
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* L2 — section toggle */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setArchiveOpen((v) => !v)}
|
||||
aria-expanded={archiveOpen}
|
||||
className="thot-label mt-2 flex w-full items-center gap-1 px-1 pb-1 pt-1 text-left text-foreground/65 hover:text-foreground"
|
||||
>
|
||||
<span className="select-none">{archiveOpen ? "▾" : "▸"}</span>
|
||||
<span className="tabular-nums">{t("Archive ({count})", { count: archivedList.length })}</span>
|
||||
</button>
|
||||
{archiveOpen && (
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
<Accordion.Item value="archive" className="thot-session-accordion__item">
|
||||
<Accordion.Header className="m-0">
|
||||
<Accordion.Trigger className="thot-session-accordion__trigger">
|
||||
<span className="tabular-nums">{t("Archive ({count})", { count: archivedList.length })}</span>
|
||||
<ChevronDown aria-hidden="true" className={`size-4 shrink-0 ${archiveOpen ? "rotate-180" : ""}`} />
|
||||
</Accordion.Trigger>
|
||||
</Accordion.Header>
|
||||
<Accordion.Panel className="thot-session-accordion__panel" tabIndex={0}>
|
||||
<NavSessions
|
||||
sessions={archivedList}
|
||||
activeSessionId={activeSessionId}
|
||||
@@ -1239,8 +1242,9 @@ export function AppShell({ canLogout }: AppShellProps) {
|
||||
onSelectionChange={setSessionSelected}
|
||||
showOwner={showingAllSessions}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion.Root>
|
||||
</div>
|
||||
</aside>
|
||||
</ArchiveNavigation>
|
||||
|
||||
Reference in New Issue
Block a user