Skip to content

Commit cf317c8

Browse files
committed
fix(desktop): cover the remaining traffic-light overlaps, and enumerate them in CI
Fixing signup by hand would have been the fourth time this bug was found by a person hitting it. The audit now enumerates instead of listing what to inspect: it walks every `.tsx` outside workspace chrome, flags each full-viewport root, and fails unless that root either composes `.desktop-title-bar-page` or appears in an allowlist with a written reason. A brand-new page that fills the viewport fails on arrival — verified by adding one, and by reverting each fix below. Running it found three more surfaces already overlapping: - `/oauth-error` is Better Auth's `onAPIError.errorURL`, which is precisely where desktop OAuth failures land, so the one page a user sees when sign-in breaks drew its content under the lights. - `/f/[token]` public file view, same shell family, same origin, reachable in the window. - The signup and reset-password Suspense fallbacks are viewport-tall *inside* the lane-reserving shell, so the page overflowed by the lane while the split chunk loaded. A placeholder needs no viewport height. Four surfaces are allowlisted with reasons: the two landing shells (the desktop shell boots to /login or a workspace and has no path to marketing routes), the dev-only playground, and the embedded resume interface. Measured over CDP: /oauth-error reserves 40px with zero overflow.
1 parent 8397dfa commit cf317c8

5 files changed

Lines changed: 51 additions & 5 deletions

File tree

apps/sim/app/(auth)/reset-password/reset-password-content.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ function ResetPasswordContent() {
8080

8181
export default function ResetPasswordPage() {
8282
return (
83-
<Suspense fallback={<div className='flex h-screen items-center justify-center'>Loading…</div>}>
83+
<Suspense
84+
fallback={<div className='flex min-h-[320px] items-center justify-center'>Loading…</div>}
85+
>
8486
<ResetPasswordContent />
8587
</Suspense>
8688
)

apps/sim/app/(auth)/signup/signup-form.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,9 @@ export default function SignupPage({
490490
emailSignupEnabled,
491491
}: SignupFormProps) {
492492
return (
493-
<Suspense fallback={<div className='flex h-screen items-center justify-center'>Loading…</div>}>
493+
<Suspense
494+
fallback={<div className='flex min-h-[320px] items-center justify-center'>Loading…</div>}
495+
>
494496
<SignupFormContent
495497
githubAvailable={githubAvailable}
496498
googleAvailable={googleAvailable}

apps/sim/app/_shell/desktop-title-bar-surfaces.test.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @vitest-environment node
33
*/
4-
import { readFileSync } from 'node:fs'
4+
import { readdirSync, readFileSync } from 'node:fs'
55
import { describe, expect, it } from 'vitest'
66

77
/** Anchored to this file, not `process.cwd()`, which only resolves from `apps/sim`. */
@@ -149,3 +149,45 @@ describe('desktop title-bar surface audit', () => {
149149
expect(resourceHeader).not.toMatch(/py-\[8\.5px\]/)
150150
})
151151
})
152+
153+
/**
154+
* Every full-viewport page root outside workspace chrome, and why it is safe.
155+
*
156+
* A root that fills the viewport and is NOT lane-aware draws its top chrome underneath
157+
* the macOS traffic lights, because the pre-paint script marks the lane on every desktop
158+
* route whether or not the page reserves it. That is one bug that has now surfaced four
159+
* separate times — workspace headers, signup, the CLI handoff, the OAuth error page —
160+
* each found by a person hitting it rather than by a check.
161+
*
162+
* So the check enumerates instead of listing what to look at: any new full-viewport root
163+
* fails here until it either composes `.desktop-title-bar-page` or is added below with a
164+
* reason. Reaching for this allowlist should feel like a claim you have to defend.
165+
*/
166+
const LANE_EXEMPT: Record<string, string> = {
167+
'app/(landing)/components/landing-shell/landing-shell.tsx':
168+
'Marketing chrome. The desktop shell boots straight to /login or a workspace and has no path to the landing routes.',
169+
'app/(landing)/components/logo-shell/logo-shell.tsx':
170+
'Marketing chrome, same reasoning as landing-shell.',
171+
'app/playground/page.tsx': 'Dev-only scratch route, not shipped in the desktop shell.',
172+
'app/(interfaces)/resume/[workflowId]/[executionId]/loading.tsx':
173+
'Embedded interface surface rendered inside a host page, never as the desktop window root.',
174+
}
175+
176+
describe('desktop traffic-light lane coverage', () => {
177+
it('leaves no full-viewport root outside workspace chrome unaccounted for', () => {
178+
const appDir = new URL('../', import.meta.url)
179+
const files = readdirSync(appDir, { recursive: true, encoding: 'utf8' })
180+
.filter((f) => f.endsWith('.tsx') && !f.startsWith('workspace/'))
181+
.map((f) => `app/${f}`)
182+
183+
const unaccounted = files.filter((file) => {
184+
const source = stripComments(read(`../${file.slice('app/'.length)}`))
185+
const fillsViewport = /\b(min-h-screen|h-screen)\b/.test(source)
186+
if (!fillsViewport) return false
187+
const laneAware = source.includes('desktop-title-bar-page') || source.includes('AuthShell')
188+
return !laneAware && !(file in LANE_EXEMPT)
189+
})
190+
191+
expect(unaccounted).toEqual([])
192+
})
193+
})

apps/sim/app/f/[token]/public-file-view.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export function PublicFileView({
6565
)
6666

6767
return (
68-
<div className='light flex min-h-screen flex-col bg-[var(--bg)]'>
68+
<div className='light desktop-title-bar-page flex flex-col bg-[var(--bg)]'>
6969
<header className='sticky top-0 z-10 flex items-center justify-between gap-4 border-[var(--border)] border-b bg-[var(--bg)] px-4 py-3'>
7070
<div className='flex min-w-0 items-center gap-3'>
7171
{!brand.logoUrl && (

apps/sim/app/oauth-error/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default async function OAuthErrorPage({ searchParams }: OAuthErrorPagePro
3636
const code = typeof params.error === 'string' ? params.error : undefined
3737

3838
return (
39-
<main className='flex min-h-screen items-center justify-center px-6'>
39+
<main className='desktop-title-bar-page flex items-center justify-center px-6'>
4040
<div className='max-w-sm text-center'>
4141
<h1 className='font-semibold text-foreground text-lg'>Couldn’t complete that</h1>
4242
<p className='mt-2 text-muted-foreground text-sm'>{messageForError(code)}</p>

0 commit comments

Comments
 (0)