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:
parent
59900f46f2
commit
1a2ac12893
|
|
@ -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:hover { filter: brightness(1.12); }
|
||||
.button:disabled { cursor: wait; opacity: .6; }
|
||||
.button-small { font-size: 13px; padding: 9px 13px; }
|
||||
main { margin: 0 auto; max-width: 1240px; padding: 6rem 28px 100px; }
|
||||
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; }
|
||||
.site-page-frame { 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), 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 h1 { max-width: none !important; }
|
||||
.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-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; }
|
||||
@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; } }
|
||||
.flagship-section-heading { margin-top: 90px; }
|
||||
.flagship-feature-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import type { Metadata, Viewport } from 'next';
|
|||
import './globals.css';
|
||||
import { SiteHeader } from '../components/site-header';
|
||||
import { SiteFooter } from '../components/site-footer';
|
||||
import { SitePageFrame } from '../components/site-page-frame';
|
||||
|
||||
export const viewport: Viewport = {
|
||||
width: 'device-width',
|
||||
|
|
@ -161,7 +162,7 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac
|
|||
</head>
|
||||
<body>
|
||||
<SiteHeader />
|
||||
<main>{children}</main>
|
||||
<SitePageFrame>{children}</SitePageFrame>
|
||||
<SiteFooter />
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export function FounderPortalShell({
|
|||
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
|
||||
|
||||
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) */}
|
||||
<FounderSidebar
|
||||
club={club}
|
||||
|
|
@ -63,7 +63,7 @@ export function FounderPortalShell({
|
|||
/>
|
||||
|
||||
{/* 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}
|
||||
</main>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export function FounderTopBar({
|
|||
|
||||
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">
|
||||
<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 */}
|
||||
<div className="flex items-center gap-2.5 sm:gap-4 min-w-0">
|
||||
{/* Mobile Hamburger Toggle */}
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
}
|
||||
|
|
@ -263,9 +263,11 @@ async function runAllTests() {
|
|||
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');
|
||||
|
||||
// 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('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');
|
||||
|
||||
// Mobile drawer: translate-x-full lg:translate-x-0, touch targets
|
||||
|
|
|
|||
Loading…
Reference in New Issue