diff --git a/src/app/page.tsx b/src/app/page.tsx index 7e3803e..a78584c 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -15,7 +15,6 @@ import { DragDropContainer } from "@/components/drag-drop-container"; import { EventDialog } from "@/components/event-dialog"; import { EventsList } from "@/components/events-list"; import { IcsFilePicker } from "@/components/ics-file-picker"; -import { ModeToggle } from "@/components/mode-toggle"; import { SettingsPanel } from "@/components/settings-panel"; import SignIn from "@/components/sign-in"; import { Badge } from "@/components/ui/badge"; @@ -432,12 +431,21 @@ export default function HomePage() { isMobile ? "px-4 pb-24 pt-4" : "px-8 py-4", ); const appHeaderSurfaceClasses = getAppHeaderSurfaceClasses(isMobile); + const headerLayoutClasses = cn( + isMobile ? "flex-col items-start" : "items-center justify-between", + ); const appSectionSurfaceClasses = getAppSectionSurfaceClasses(isMobile); const appNavSurfaceClasses = getAppNavSurfaceClasses(isMobile); const mainContentClasses = cn( "grid items-start gap-4", isMobile ? "grid-cols-1" : "grid-cols-[minmax(0,0.75fr)_minmax(0,1.25fr)]", ); + const headerActionsClasses = isMobile + ? "flex w-full items-center justify-between gap-2" + : "flex flex-wrap items-center justify-end gap-2"; + const mobileUtilityActionsClasses = "flex items-center gap-2"; + const desktopUtilityActionsClasses = "flex items-center gap-2"; + const moreTriggerLabel = isMobile ? null : "More"; return ( handleImagesSelect([file])} >
-
-
+
+

Local Calendar

@@ -456,7 +469,7 @@ export default function HomePage() { Event timeline
-
+
{isOnline ? "Online ready" : "Offline mode"} - - - - - - - - - - Manual create - - setActiveView("settings")}> - Settings - - - + {!isMobile && ( + + )} + + + + + + {isMobile && ( + + Export + + )} + + Manual create + + setActiveView("settings")}> + Settings + + + + Clear all events + + + +
diff --git a/tests/home-page-layout.test.ts b/tests/home-page-layout.test.ts index 8610db6..e1fbbed 100644 --- a/tests/home-page-layout.test.ts +++ b/tests/home-page-layout.test.ts @@ -7,6 +7,8 @@ describe("home page hierarchy", () => { expect(source).toContain("useIsMobile"); expect(source).toContain("grid-cols-[minmax(0,0.75fr)_minmax(0,1.25fr)]"); + expect(source).toContain('"items-center justify-between"'); + expect(source).toContain("desktopUtilityActionsClasses"); expect(source).toContain("AI capture"); expect(source).toContain("Event timeline"); }); @@ -25,4 +27,43 @@ describe("home page hierarchy", () => { expect(source).toContain("Import"); expect(source).toContain("Manual create"); }); + + test("mobile header gives controls their own full-width row so the title is not squeezed by actions", () => { + const source = readFileSync("src/app/page.tsx", "utf8"); + + expect(source).toContain("isMobile ? \"w-full\" : undefined"); + expect(source).toContain("headerActionsClasses"); + expect(source).toContain('"flex w-full items-center justify-between gap-2"'); + expect(source).toContain("flex flex-wrap items-center justify-end gap-2"); + }); + + test("mobile header keeps export inside the More menu instead of a dedicated button", () => { + const source = readFileSync("src/app/page.tsx", "utf8"); + + expect(source).toContain("!isMobile && ("); + expect(source).toContain("Export"); + expect(source).toContain("onClick={handleExport}"); + }); + + test("mobile More trigger collapses to an icon button so utility actions fit on one row", () => { + const source = readFileSync("src/app/page.tsx", "utf8"); + + expect(source).toContain('size={isMobile ? "icon" : "sm"}'); + expect(source).toContain("moreTriggerLabel"); + expect(source).toContain('isMobile ? null : "More"'); + }); + + test("mobile header omits the theme toggle so auth and overflow actions have a stable hierarchy", () => { + const source = readFileSync("src/app/page.tsx", "utf8"); + + expect(source).not.toContain(""); + }); + + test("mobile header uses a column layout with a dedicated action row instead of desktop justify-between framing", () => { + const source = readFileSync("src/app/page.tsx", "utf8"); + + expect(source).toContain("headerLayoutClasses"); + expect(source).toContain('isMobile ? "flex-col items-start"'); + expect(source).toContain('"flex w-full items-center justify-between gap-2"'); + }); });