refactor(header): improve mobile header layout with responsive action controls

This commit is contained in:
2026-04-21 23:23:43 -04:00
parent 7f7c945396
commit 88265678db
2 changed files with 112 additions and 36 deletions

View File

@@ -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 (
<DragDropContainer
@@ -447,8 +455,13 @@ export default function HomePage() {
onImageDrop={(file) => handleImagesSelect([file])}
>
<div className={appFrameClasses}>
<header className={appHeaderSurfaceClasses}>
<div className="flex min-w-0 flex-col">
<header className={cn(appHeaderSurfaceClasses, headerLayoutClasses)}>
<div
className={cn(
"flex min-w-0 flex-col",
isMobile ? "w-full" : undefined,
)}
>
<p className="font-mono text-[11px] uppercase text-muted-foreground">
Local Calendar
</p>
@@ -456,7 +469,7 @@ export default function HomePage() {
Event timeline
</h1>
</div>
<div className="flex flex-wrap items-center justify-end gap-2">
<div className={headerActionsClasses}>
<Badge
variant="outline"
className={getConnectionBadgeClasses(isOnline)}
@@ -468,41 +481,63 @@ export default function HomePage() {
)}
<span>{isOnline ? "Online ready" : "Offline mode"}</span>
</Badge>
<SignIn />
<ModeToggle />
<Button
type="button"
variant="outline"
size="sm"
onClick={handleExport}
disabled={events.length === 0}
<div
className={
isMobile
? mobileUtilityActionsClasses
: desktopUtilityActionsClasses
}
>
Export
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button type="button" variant="outline" size="sm">
<MoreHorizontal className="h-4 w-4" />
More
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48">
<DropdownMenuItem onClick={openManualEventDialog}>
Manual create
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setActiveView("settings")}>
Settings
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
variant="destructive"
onClick={handleClearAll}
<SignIn />
{!isMobile && (
<Button
type="button"
variant="outline"
size="sm"
onClick={handleExport}
disabled={events.length === 0}
>
Clear all events
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
Export
</Button>
)}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
type="button"
variant="outline"
size={isMobile ? "icon" : "sm"}
aria-label="More actions"
>
<MoreHorizontal className="h-4 w-4" />
{moreTriggerLabel}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48">
{isMobile && (
<DropdownMenuItem
onClick={handleExport}
disabled={events.length === 0}
>
Export
</DropdownMenuItem>
)}
<DropdownMenuItem onClick={openManualEventDialog}>
Manual create
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setActiveView("settings")}>
Settings
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
variant="destructive"
onClick={handleClearAll}
disabled={events.length === 0}
>
Clear all events
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
</header>