diff --git a/ui/src/pages/accounts.tsx b/ui/src/pages/accounts.tsx index 877b04b4..71de35b2 100644 --- a/ui/src/pages/accounts.tsx +++ b/ui/src/pages/accounts.tsx @@ -55,7 +55,7 @@ export function AccountsPage() { return ( <> -
+
{/* Left action column */}
diff --git a/ui/src/pages/api.tsx b/ui/src/pages/api.tsx index b1474d57..028121c3 100644 --- a/ui/src/pages/api.tsx +++ b/ui/src/pages/api.tsx @@ -206,7 +206,7 @@ export function ApiPage() { }; return ( -
+
setCreateDialogOpen(true)} />
diff --git a/ui/src/pages/claude-extension.tsx b/ui/src/pages/claude-extension.tsx index 00bed2c0..c17057ac 100644 --- a/ui/src/pages/claude-extension.tsx +++ b/ui/src/pages/claude-extension.tsx @@ -405,7 +405,7 @@ export function ClaudeExtensionPage() { } return ( -
+
diff --git a/ui/src/pages/cliproxy-ai-providers.tsx b/ui/src/pages/cliproxy-ai-providers.tsx index 78deca16..37998ca0 100644 --- a/ui/src/pages/cliproxy-ai-providers.tsx +++ b/ui/src/pages/cliproxy-ai-providers.tsx @@ -1462,7 +1462,7 @@ export function CliproxyAiProvidersPage() { if (isLoading) { return ( -
+
@@ -1476,7 +1476,7 @@ export function CliproxyAiProvidersPage() { : 'Failed to load CLIProxy AI providers. Check the local server and try again.'; return ( -
+
@@ -1549,7 +1549,7 @@ export function CliproxyAiProvidersPage() {
); return ( -
+
diff --git a/ui/src/pages/cliproxy-control-panel.tsx b/ui/src/pages/cliproxy-control-panel.tsx index 80cfa80e..776c33ca 100644 --- a/ui/src/pages/cliproxy-control-panel.tsx +++ b/ui/src/pages/cliproxy-control-panel.tsx @@ -8,7 +8,7 @@ import { ControlPanelEmbed } from '@/components/cliproxy/control-panel-embed'; export function CliproxyControlPanelPage() { return ( -
+
); diff --git a/ui/src/pages/cliproxy.tsx b/ui/src/pages/cliproxy.tsx index f1d8c557..ce4e2a05 100644 --- a/ui/src/pages/cliproxy.tsx +++ b/ui/src/pages/cliproxy.tsx @@ -338,7 +338,7 @@ export function CliproxyPage() { }; return ( -
+
{/* Left Sidebar */}
{/* Header */} diff --git a/ui/src/pages/copilot.tsx b/ui/src/pages/copilot.tsx index 211a240b..23a58578 100644 --- a/ui/src/pages/copilot.tsx +++ b/ui/src/pages/copilot.tsx @@ -116,7 +116,7 @@ export function CopilotPage() { } = useCopilot(); return ( -
+
{/* Left Sidebar - Status Overview */}
{/* Header */} diff --git a/ui/src/pages/cursor.tsx b/ui/src/pages/cursor.tsx index 2c4b7679..e788ecb0 100644 --- a/ui/src/pages/cursor.tsx +++ b/ui/src/pages/cursor.tsx @@ -633,7 +633,7 @@ export function CursorPage() { return ( <> -
+
diff --git a/ui/src/pages/droid.tsx b/ui/src/pages/droid.tsx index 382791c3..0166ab23 100644 --- a/ui/src/pages/droid.tsx +++ b/ui/src/pages/droid.tsx @@ -694,7 +694,7 @@ export function DroidPage() { }; return ( -
+
{renderOverview()}
diff --git a/ui/src/pages/settings/index.tsx b/ui/src/pages/settings/index.tsx index 57da2d80..bb317ff9 100644 --- a/ui/src/pages/settings/index.tsx +++ b/ui/src/pages/settings/index.tsx @@ -121,7 +121,7 @@ function SettingsPageInner() { }; return ( -
+
{/* Mobile View - Stacked vertically */}
diff --git a/ui/src/pages/updates.tsx b/ui/src/pages/updates.tsx index 770c3d61..1a4048db 100644 --- a/ui/src/pages/updates.tsx +++ b/ui/src/pages/updates.tsx @@ -102,7 +102,7 @@ export function UpdatesPage() { ); return ( -
+
diff --git a/ui/tests/unit/ui/pages/dashboard-page-height-contract.test.ts b/ui/tests/unit/ui/pages/dashboard-page-height-contract.test.ts new file mode 100644 index 00000000..170f3890 --- /dev/null +++ b/ui/tests/unit/ui/pages/dashboard-page-height-contract.test.ts @@ -0,0 +1,38 @@ +import { readFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; + +const testDir = path.dirname(fileURLToPath(import.meta.url)); +const projectRoot = path.resolve(testDir, '../../../../'); + +const layoutManagedRouteFiles = [ + 'src/pages/index.tsx', + 'src/pages/analytics/index.tsx', + 'src/pages/updates.tsx', + 'src/pages/api.tsx', + 'src/pages/cliproxy.tsx', + 'src/pages/cliproxy-ai-providers.tsx', + 'src/pages/cliproxy-control-panel.tsx', + 'src/pages/copilot.tsx', + 'src/pages/cursor.tsx', + 'src/pages/claude-extension.tsx', + 'src/pages/droid.tsx', + 'src/pages/accounts.tsx', + 'src/pages/settings/index.tsx', + 'src/pages/health.tsx', + 'src/pages/shared.tsx', +] as const; + +const forbiddenViewportHeightPattern = /\b(?:h-screen|min-h-screen)\b|calc\(100(?:d|l|s)?vh/i; + +describe('dashboard route height contract', () => { + it.each(layoutManagedRouteFiles)( + '%s relies on the shared layout for viewport height', + (relativePath) => { + const source = readFileSync(path.join(projectRoot, relativePath), 'utf8'); + + expect(source).not.toMatch(forbiddenViewportHeightPattern); + } + ); +});