diff --git a/web/workspace/src/app.css b/web/workspace/src/app.css
index 48070aaa..8b5a1e6a 100644
--- a/web/workspace/src/app.css
+++ b/web/workspace/src/app.css
@@ -122,9 +122,8 @@
}
}
@layer layout {
- .workspace-layout {
+ .app-layout {
display: grid;
- grid-template-columns: minmax(220px, 280px) minmax(0, 1fr);
grid-template-rows: auto minmax(0, 1fr);
width: 100vw;
height: 100dvh;
@@ -133,12 +132,25 @@
overflow: hidden;
min-width: 0;
}
+ .app-shell {
+ min-width: 0;
+ min-height: 0;
+ overflow: auto;
+ }
+ .workspace-layout {
+ display: grid;
+ grid-template-columns: minmax(220px, 280px) minmax(0, 1fr);
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+ min-width: 0;
+ }
.workspace-layout.sidebar-collapsed {
grid-template-columns: max-content minmax(0, 1fr);
}
.workspace-topbar {
- grid-column: 2;
- grid-row: 1;
display: flex;
align-items: center;
justify-content: flex-end;
@@ -180,7 +192,6 @@
}
.shell {
grid-column: 2;
- grid-row: 2;
display: flex;
flex-direction: column;
gap: var(--space-6);
@@ -236,7 +247,7 @@
@layer components {
.workspace-sidebar {
grid-column: 1;
- grid-row: 1 / 3;
+ grid-row: 1;
align-self: stretch;
min-width: 0;
min-height: 0;
diff --git a/web/workspace/src/lib/workspace/console/worker-console.ui.test.ts b/web/workspace/src/lib/workspace/console/worker-console.ui.test.ts
index 3acf3cf7..c2ab4826 100644
--- a/web/workspace/src/lib/workspace/console/worker-console.ui.test.ts
+++ b/web/workspace/src/lib/workspace/console/worker-console.ui.test.ts
@@ -390,6 +390,12 @@ Deno.test("Account UI owns browser passkey session state without workspace autho
const rootLayoutLoad = await Deno.readTextFile(
new URL("./../../../routes/+layout.ts", import.meta.url),
);
+ const workspaceLayout = await Deno.readTextFile(
+ new URL("./../../../routes/w/[workspaceId]/+layout.svelte", import.meta.url),
+ );
+ const workspaceLayoutLoad = await Deno.readTextFile(
+ new URL("./../../../routes/w/[workspaceId]/+layout.ts", import.meta.url),
+ );
const sidebar = await Deno.readTextFile(
new URL("../sidebar/WorkspaceSidebar.svelte", import.meta.url),
);
@@ -422,10 +428,17 @@ Deno.test("Account UI owns browser passkey session state without workspace autho
rootLayout.includes("topbar-icon-button") &&
rootLayout.includes('href="/account"') &&
rootLayout.includes("Open Account") &&
+ !rootLayout.includes("WorkspaceSidebar") &&
!sidebar.includes("accountHref") &&
!sidebar.includes("Open Account"),
"Account navigation should live in the global layout header, not the workspace sidebar",
);
+ assert(
+ workspaceLayout.includes("WorkspaceSidebar") &&
+ workspaceLayout.includes("workspace={data.workspace}") &&
+ workspaceLayoutLoad.includes("workspaceApiPath(params.workspaceId"),
+ "Workspace sidebar and workspace-scoped data loading should live under /w/[workspaceId] layout",
+ );
assert(
rootLayoutLoad.includes('"/account"') && rootLayoutLoad.includes('"/login/device"'),
"Root layout should not redirect account and device-login public routes to a workspace",
diff --git a/web/workspace/src/routes/+layout.svelte b/web/workspace/src/routes/+layout.svelte
index cd5280bc..fc368d29 100644
--- a/web/workspace/src/routes/+layout.svelte
+++ b/web/workspace/src/routes/+layout.svelte
@@ -1,26 +1,14 @@