Files
accounted/components/dashboard/MainContainer.tsx
T
Jakob Wennberg 8aff6dc684 fix(dashboard): container leaks after extension workspace navigation (#414)
* fix(dashboard): keep container in sync with route after extension navigation

The shared (dashboard)/layout.tsx picked between the centered max-w-5xl
chrome and the full-width extension wrapper based on a server-side
pathname header. App Router caches shared layouts across sibling-route
navigations, so whichever branch was rendered on the first server pass
stuck on subsequent client navigations until a hard reload.

In practice this only mattered because /e/* is the first route family
that opts out of the centered card — visiting the invoice-inbox
workspace and then clicking back to /, /transactions, etc. left the
unconstrained h-full wrapper in place, and the dashboard rendered
edge-to-edge.

Move the conditional into a small client component that subscribes to
usePathname(). The hook re-runs on every navigation, so the wrapper
className always tracks the current route.

The layout still reads x-pathname for the isNoCompanyAllowed redirect
check; that path only fires on the initial server render and isn't
subject to the soft-navigation issue.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(dashboard): drop redundant nullish guards on usePathname

Per Greptile review on #414. usePathname() in App Router always returns
a string, so the optional chaining and ?? false were dead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 14:19:11 +02:00

38 lines
1.1 KiB
TypeScript

'use client'
import { usePathname } from 'next/navigation'
import type { ReactNode } from 'react'
/**
* Picks the dashboard chrome container based on route. Extension workspaces
* (/e/*) want the full viewport for file viewers and dashboards; everything
* else gets the centered max-w-5xl card.
*
* Lives in a client component because the parent (dashboard) layout is
* shared across all dashboard routes. Server-side pathname checks done in
* the layout don't re-evaluate reliably on soft navigation between sibling
* routes, so the wrapper class would otherwise stick on whichever branch
* the first render picked.
*/
export function MainContainer({
companyId,
children,
}: {
companyId: string | null
children: ReactNode
}) {
const pathname = usePathname()
const isExtensionWorkspace = pathname.startsWith('/e/')
return isExtensionWorkspace ? (
<div key={companyId ?? ''} className="h-full">{children}</div>
) : (
<div
key={companyId ?? ''}
className="max-w-5xl mx-auto px-5 py-8 md:px-8 md:py-10"
>
{children}
</div>
)
}