fix(website): expand Founder Portal layout width to fill available canvas (#11)

* fix(website): expand Founder Portal layout width to fill available canvas

* fix(website): restore mobile padding, preserve public main landmark, and harden width test

Apply responsive mobile padding to .site-page-frame under 760px. Render semantic <main> for public routes and <div> for portal routes with internal <main> via SitePageFrame. Assert max-w-[1536px] exclusively and reject old max-w-[1440px] cap in founder-portal.test.cjs.

---------

Co-authored-by: Developer <dev@example.com>
This commit is contained in:
Billie Ponder 2026-09-20 08:59:43 -04:00 committed by GitHub
parent 59900f46f2
commit 1a2ac12893
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 35 additions and 10 deletions

View File

@ -331,9 +331,9 @@ a { color: inherit; text-decoration: none; }
.button { background: var(--blue); border: 0; border-radius: 6px; color: white; cursor: pointer; display: inline-flex; font-size: 15px; font-weight: 700; justify-content: center; padding: 13px 18px; } .button { background: var(--blue); border: 0; border-radius: 6px; color: white; cursor: pointer; display: inline-flex; font-size: 15px; font-weight: 700; justify-content: center; padding: 13px 18px; }
.button:hover { filter: brightness(1.12); } .button:hover { filter: brightness(1.12); }
.button:disabled { cursor: wait; opacity: .6; } .button:disabled { cursor: wait; opacity: .6; }
.button-small { font-size: 13px; padding: 9px 13px; } .site-page-frame { margin: 0 auto; max-width: 1240px; padding: 6rem 28px 100px; }
main { margin: 0 auto; max-width: 1240px; padding: 6rem 28px 100px; } .site-page-frame:has(.flagship-landing), .site-page-frame:has(.flagship-page), .site-page-frame:has(.ops-shell-root), .site-page-frame:has(.ops-error-root), .site-page-frame:has(.founder-portal-root),
main:has(.flagship-landing), main:has(.flagship-page), main:has(.ops-shell-root), main:has(.ops-error-root) { max-width: 100%; padding: 0; margin: 0; } main:has(.flagship-landing), main:has(.flagship-page), main:has(.ops-shell-root), main:has(.ops-error-root), main:has(.founder-portal-root) { max-width: 100%; padding: 0; margin: 0; }
.ops-shell-root, .ops-shell-root main { max-width: 100% !important; margin: 0 !important; } .ops-shell-root, .ops-shell-root main { max-width: 100% !important; margin: 0 !important; }
.ops-shell-root h1 { max-width: none !important; } .ops-shell-root h1 { max-width: none !important; }
.flagship-landing, .flagship-landing,
@ -445,7 +445,7 @@ input:focus { border-color: var(--blue); outline: 2px solid color-mix(in srgb, v
.session-heading h2 { margin: 0; } .session-heading h2 { margin: 0; }
.session-row { align-items: center; border-top: 1px solid var(--line); display: flex; justify-content: space-between; margin-top: 16px; padding-top: 16px; } .session-row { align-items: center; border-top: 1px solid var(--line); display: flex; justify-content: space-between; margin-top: 16px; padding-top: 16px; }
.session-row p { font-size: 13px; margin: 5px 0 0; } .session-row p { font-size: 13px; margin: 5px 0 0; }
@media (max-width: 760px) { .site-header { flex-wrap: wrap; padding: 16px 18px; } nav { order: 3; width: 100%; } main { padding: 48px 18px 72px; } .section-grid, .section-grid-two, .account-grid, .auth-page, .admin-kpis { grid-template-columns: 1fr; margin-top: 56px; } .admin-title-row { align-items: flex-start; flex-direction: column; } .admin-toolbar { align-items: flex-start; flex-direction: column; } .admin-tabs { width: 100%; } .admin-tab { flex: 1; justify-content: center; } h1 { font-size: 48px; } .site-footer { padding-left: 18px; padding-right: 18px; } } @media (max-width: 760px) { .site-header { flex-wrap: wrap; padding: 16px 18px; } nav { order: 3; width: 100%; } .site-page-frame, main { padding: 48px 18px 72px; } .section-grid, .section-grid-two, .account-grid, .auth-page, .admin-kpis { grid-template-columns: 1fr; margin-top: 56px; } .admin-title-row { align-items: flex-start; flex-direction: column; } .admin-toolbar { align-items: flex-start; flex-direction: column; } .admin-tabs { width: 100%; } .admin-tab { flex: 1; justify-content: center; } h1 { font-size: 48px; } .site-footer { padding-left: 18px; padding-right: 18px; } }
@media (max-width: 760px) { .flagship-hero, .ride-hero-panel, .public-split { grid-template-columns: 1fr; padding: 28px; }.flagship-hero { min-height: 0; padding: 36px 24px; }.metric-ribbon { grid-template-columns: repeat(2, 1fr); gap: 22px; margin-bottom: 56px; }.metric-ribbon div:nth-child(3) { border-left: 0; }.feature-grid, .club-pillars, .architecture-grid { grid-template-columns: 1fr; }.conversion-band { align-items: flex-start; flex-direction: column; gap: 20px; }.radar { max-width: 270px; }.public-intro h1 { font-size: 48px; } } @media (max-width: 760px) { .flagship-hero, .ride-hero-panel, .public-split { grid-template-columns: 1fr; padding: 28px; }.flagship-hero { min-height: 0; padding: 36px 24px; }.metric-ribbon { grid-template-columns: repeat(2, 1fr); gap: 22px; margin-bottom: 56px; }.metric-ribbon div:nth-child(3) { border-left: 0; }.feature-grid, .club-pillars, .architecture-grid { grid-template-columns: 1fr; }.conversion-band { align-items: flex-start; flex-direction: column; gap: 20px; }.radar { max-width: 270px; }.public-intro h1 { font-size: 48px; } }
.flagship-section-heading { margin-top: 90px; } .flagship-section-heading { margin-top: 90px; }
.flagship-feature-grid { grid-template-columns: repeat(2, 1fr); } .flagship-feature-grid { grid-template-columns: repeat(2, 1fr); }

View File

@ -2,6 +2,7 @@ import type { Metadata, Viewport } from 'next';
import './globals.css'; import './globals.css';
import { SiteHeader } from '../components/site-header'; import { SiteHeader } from '../components/site-header';
import { SiteFooter } from '../components/site-footer'; import { SiteFooter } from '../components/site-footer';
import { SitePageFrame } from '../components/site-page-frame';
export const viewport: Viewport = { export const viewport: Viewport = {
width: 'device-width', width: 'device-width',
@ -161,7 +162,7 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac
</head> </head>
<body> <body>
<SiteHeader /> <SiteHeader />
<main>{children}</main> <SitePageFrame>{children}</SitePageFrame>
<SiteFooter /> <SiteFooter />
</body> </body>
</html> </html>

View File

@ -35,7 +35,7 @@ export function FounderPortalShell({
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false); const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
return ( return (
<div className="min-h-screen bg-brand-bg telemetry-grid-bg font-body text-sm text-slate-200 antialiased selection:bg-primary-container selection:text-on-primary-container"> <div className="founder-portal-root min-h-screen bg-brand-bg telemetry-grid-bg font-body text-sm text-slate-200 antialiased selection:bg-primary-container selection:text-on-primary-container">
{/* Sidebar (Desktop persistent + Mobile off-canvas drawer) */} {/* Sidebar (Desktop persistent + Mobile off-canvas drawer) */}
<FounderSidebar <FounderSidebar
club={club} club={club}
@ -63,7 +63,7 @@ export function FounderPortalShell({
/> />
{/* Content Body Container */} {/* Content Body Container */}
<main className="relative pt-24 pb-16 px-4 sm:px-6 lg:px-8 w-full max-w-[1440px] mx-auto flex-1"> <main className="relative pt-24 pb-16 px-6 sm:px-8 lg:px-8 w-full max-w-[1536px] mx-auto flex-1">
{children} {children}
</main> </main>
</div> </div>

View File

@ -51,7 +51,7 @@ export function FounderTopBar({
return ( return (
<header className="fixed top-0 left-0 lg:left-72 right-0 h-16 bg-surface-container-lowest/95 backdrop-blur-md border-b border-brand-border/60 z-40"> <header className="fixed top-0 left-0 lg:left-72 right-0 h-16 bg-surface-container-lowest/95 backdrop-blur-md border-b border-brand-border/60 z-40">
<div className="w-full max-w-[1440px] mx-auto h-full px-4 sm:px-6 lg:px-8 flex items-center justify-between gap-3 sm:gap-4"> <div className="w-full max-w-[1536px] mx-auto h-full px-6 sm:px-8 lg:px-8 flex items-center justify-between gap-3 sm:gap-4">
{/* Left: Mobile hamburger + Breadcrumbs + Switch Club */} {/* Left: Mobile hamburger + Breadcrumbs + Switch Club */}
<div className="flex items-center gap-2.5 sm:gap-4 min-w-0"> <div className="flex items-center gap-2.5 sm:gap-4 min-w-0">
{/* Mobile Hamburger Toggle */} {/* Mobile Hamburger Toggle */}

View File

@ -0,0 +1,22 @@
'use client';
import React from 'react';
import { usePathname } from 'next/navigation';
/**
* SitePageFrame wraps page content.
* For portal and operations routes that manage their own internal <main> landmark,
* it renders a non-semantic <div> to avoid invalid nested <main> elements.
* For standard public and content routes, it renders a semantic <main> landmark
* to ensure assistive technologies can identify the primary content.
*/
export function SitePageFrame({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
const isPortalRoute = pathname?.includes('/manage') || pathname?.startsWith('/admin');
if (isPortalRoute) {
return <div className="site-page-frame">{children}</div>;
}
return <main className="site-page-frame">{children}</main>;
}

View File

@ -263,9 +263,11 @@ async function runAllTests() {
const shellSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/founder-portal-shell.tsx'), 'utf8'); const shellSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/founder-portal-shell.tsx'), 'utf8');
const sidebarSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/founder-sidebar.tsx'), 'utf8'); const sidebarSrc = fs.readFileSync(path.resolve(__dirname, '../components/founder-portal/founder-sidebar.tsx'), 'utf8');
// Desktop persistent sidebar: lg:pl-72, lg:translate-x-0, max-w-[1440px] // Desktop persistent sidebar: lg:pl-72, lg:translate-x-0, max-w-[1536px]
assert(shellSrc.includes('lg:pl-72'), 'Missing lg:pl-72 desktop sidebar offset'); assert(shellSrc.includes('lg:pl-72'), 'Missing lg:pl-72 desktop sidebar offset');
assert(shellSrc.includes('max-w-[1440px]'), 'Missing max-w-[1440px] desktop canvas container'); assert(shellSrc.includes('max-w-[1536px]'), 'FounderPortalShell must use max-w-[1536px] desktop canvas container');
assert(!shellSrc.includes('max-w-[1440px]'), 'FounderPortalShell must NOT retain old max-w-[1440px] cap');
assert(shellSrc.includes('founder-portal-root'), 'Missing founder-portal-root class on shell');
assert(sidebarSrc.includes('w-72'), 'Missing w-72 persistent sidebar width'); assert(sidebarSrc.includes('w-72'), 'Missing w-72 persistent sidebar width');
// Mobile drawer: translate-x-full lg:translate-x-0, touch targets // Mobile drawer: translate-x-full lg:translate-x-0, touch targets