Delete the src/app tree, next.config.ts, next-env.d.ts, and the Next-only guard/header components. Port AppShell/Sidebar/Topbar to react-router and mount them as a DashboardLayout route over all authenticated routes. Strip 'use client' directives, move globals.css up from the deleted app/ tree, rewrite tsconfig for Vite/Bundler resolution, drop the next dependency. Test fixes the port surfaced: jsdom v29 has no window.matchMedia (sidebar breakpoint) so setup.ts stubs it; the router-boundary specs render inside ThemeProvider because the chrome's ThemeToggle requires the context.
31 lines
820 B
TypeScript
31 lines
820 B
TypeScript
import type { ReactNode } from 'react';
|
|
import { SidebarProvider, useSidebar } from './sidebar-context';
|
|
import { Sidebar } from './sidebar';
|
|
import { Topbar } from './topbar';
|
|
|
|
interface AppShellProps {
|
|
children: ReactNode;
|
|
}
|
|
|
|
function AppShellFrame({ children }: AppShellProps): React.ReactElement {
|
|
const { collapsed, isMobile } = useSidebar();
|
|
|
|
return (
|
|
<div className="app-shell" data-sidebar-hidden={!isMobile && collapsed ? 'true' : undefined}>
|
|
<Topbar />
|
|
<Sidebar />
|
|
<div className="app-main">
|
|
<main className="h-full overflow-y-auto p-6">{children}</main>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function AppShell({ children }: AppShellProps): React.ReactElement {
|
|
return (
|
|
<SidebarProvider>
|
|
<AppShellFrame>{children}</AppShellFrame>
|
|
</SidebarProvider>
|
|
);
|
|
}
|