From 39d051953042faeca528dfce437610a7185288b2 Mon Sep 17 00:00:00 2001 From: Anastasiia Ivanchenko Date: Sun, 11 Oct 2026 22:22:50 +0300 Subject: [PATCH 1/2] Move theme, guide and GitHub actions onto the map canvas Desktop: one card in the top right. Phones: separate round buttons under the search, styled like the location button. Projection and hour basis share a row in Settings, with Sphere listed first. Refs #140 --- src/components/layout/MapToolbar.tsx | 91 ++++++++++++++++++++++++- src/components/map/ReliefMap.tsx | 12 +++- src/components/map/ViewModeTabs.tsx | 2 +- src/components/panels/HelpPanel.tsx | 41 +---------- src/components/panels/SettingsPanel.tsx | 48 ++++--------- 5 files changed, 116 insertions(+), 78 deletions(-) diff --git a/src/components/layout/MapToolbar.tsx b/src/components/layout/MapToolbar.tsx index a77fc2c..4f9f98e 100644 --- a/src/components/layout/MapToolbar.tsx +++ b/src/components/layout/MapToolbar.tsx @@ -1,8 +1,18 @@ "use client"; import Image from "next/image"; -import { ChartLine, CircleQuestionMark, Settings } from "lucide-react"; +import { + ChartLine, + CircleQuestionMark, + Compass, + Moon, + Settings, + Sun, +} from "lucide-react"; import { SITE_NAME } from "@/lib/constants/site"; +import { requestGuide } from "@/lib/tour"; +import { useTheme } from "@/providers/ThemeProvider"; +import { Button } from "@/components/ui/button"; import { Card, CardContent, CardTitle } from "@/components/ui/card"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; @@ -14,6 +24,81 @@ const PANELS = [ { value: "help", label: "Help", Icon: CircleQuestionMark }, ] as const; +const REPO_URL = "https://github.com/EarthyScience/EarthPrints"; + +function GitHubMark({ className }: { className?: string }) { + return ( + + ); +} + +function CanvasActions({ floating }: { floating: boolean }) { + const { isLight, toggleTheme } = useTheme(); + const ThemeIcon = isLight ? Moon : Sun; + const button = floating + ? ({ + variant: "outline", + size: "icon-lg", + className: + "size-12 rounded-full bg-background shadow-lg dark:bg-background [&_svg]:size-5", + } as const) + : ({ variant: "ghost", size: "icon" } as const); + + return ( + <> + + + + + ); +} + +/** One card on desktop; separate floating buttons under the search on phones. */ +export function MapActions() { + return ( + <> + + + + + +
+ +
+ + ); +} + type MapToolbarProps = { openPanel: ToolbarPanel | null; onOpenPanelChange: (panel: ToolbarPanel | null) => void; @@ -60,9 +145,9 @@ export function MapToolbar({ aria-label="Map tools" className={`[--card-spacing:--spacing(1)] ${openPanel || hideOnMobile ? "max-md:hidden" : ""} max-md:fixed max-md:inset-x-3 max-md:bottom-[max(--spacing(3),env(safe-area-inset-bottom))] max-md:rounded-full max-md:shadow-lg`} > - + onOpenPanelChange((value[0] as ToolbarPanel | undefined) ?? null) diff --git a/src/components/map/ReliefMap.tsx b/src/components/map/ReliefMap.tsx index a57fc26..6a352f6 100644 --- a/src/components/map/ReliefMap.tsx +++ b/src/components/map/ReliefMap.tsx @@ -30,7 +30,12 @@ import { useTheme } from "@/providers/ThemeProvider"; import { useCellSeries } from "@/hooks/useCellSeries"; import { useGeolocation } from "@/hooks/useGeolocation"; import { useMapSettings } from "@/hooks/useMapSettings"; -import { MapToolbar, type ToolbarPanel } from "@/components/layout/MapToolbar"; +import { subscribeGuideRequests } from "@/lib/tour"; +import { + MapActions, + MapToolbar, + type ToolbarPanel, +} from "@/components/layout/MapToolbar"; import { MapControls } from "@/components/map/MapControls"; import { MapSearch } from "@/components/map/MapSearch"; import { MapTour } from "@/components/map/MapTour"; @@ -69,6 +74,7 @@ export function ReliefMap() { const [viewState, setViewState] = useState(DEFAULT_MAP_VIEW); const [mapSize, setMapSize] = useState({ width: 0, height: 0 }); const [openPanel, setOpenPanel] = useState(null); + useEffect(() => subscribeGuideRequests(() => setOpenPanel(null)), []); const [tourExpandsPanel, setTourExpandsPanel] = useState(false); const [tourCoversBottom, setTourCoversBottom] = useState(false); const [tourOpensDetails, setTourOpensDetails] = useState(false); @@ -303,6 +309,10 @@ export function ReliefMap() { ) : null} + +
+ +
diff --git a/src/components/map/ViewModeTabs.tsx b/src/components/map/ViewModeTabs.tsx index 7516fe5..ac93519 100644 --- a/src/components/map/ViewModeTabs.tsx +++ b/src/components/map/ViewModeTabs.tsx @@ -5,8 +5,8 @@ import type { MapViewMode } from "@/types/map"; import { SegmentedTabs } from "@/components/ui/segmented-tabs"; const VIEW_MODES = [ - { value: "sphere", label: "Sphere", icon: Globe }, { value: "2d", label: "Plan", icon: Map }, + { value: "sphere", label: "Sphere", icon: Globe }, ] as const; type ViewModeTabsProps = {