feat: Refine glassmorphism styling for light and dark themes and synchronize app theme with map style selection.

This commit is contained in:
Sean O'Connor
2026-02-03 18:38:12 -05:00
parent b7fad1e691
commit 98bafe54dc
9 changed files with 57 additions and 41 deletions

View File

@@ -21,7 +21,7 @@ export default function HomePage() {
}, []);
return (
<main className="relative h-dvh w-screen overflow-hidden bg-black text-white font-serif">
<main className="relative h-dvh w-screen overflow-hidden bg-background text-foreground font-serif">
{/* Navbar - always visible */}
<Navbar isDiscoveryOpen={isDiscoveryOpen} onToggleDiscovery={() => setIsDiscoveryOpen(!isDiscoveryOpen)} />

View File

@@ -54,7 +54,7 @@ export function AboutModal({ isOpen, onClose }: AboutModalProps) {
<div className="flex justify-center">
<Button
variant="outline"
className="gap-2 border-glass-border bg-glass-border/20 hover:bg-glass-border text-glass-text-primary hover:text-white"
className="gap-2 border-glass-border bg-glass-border/20 hover:bg-glass-border text-glass-text-primary"
asChild
>
<a href="https://github.com/soconnor0919/lewisburg-coffee" target="_blank" rel="noopener noreferrer">

View File

@@ -86,15 +86,15 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
variant="ghost"
size="icon"
onClick={(e) => toggleFavorite(activeShop.id, e)}
className="bg-black/40 hover:bg-black/60 text-white rounded-full h-8 w-8 backdrop-blur-md border border-glass-border"
className="bg-glass-background hover:bg-glass-border text-glass-text-primary rounded-full h-8 w-8 backdrop-blur-md border border-glass-border"
>
<Heart className={`w-4 h-4 ${favorites.has(activeShop.id) ? 'fill-red-500 text-red-500' : 'text-white'}`} />
<Heart className={`w-4 h-4 ${favorites.has(activeShop.id) ? 'fill-red-500 text-red-500' : 'text-glass-text-primary'}`} />
</Button>
<Button
variant="ghost"
size="icon"
onClick={onClose}
className="bg-black/40 hover:bg-black/60 text-white rounded-full h-8 w-8 backdrop-blur-md border border-glass-border"
className="bg-glass-background hover:bg-glass-border text-glass-text-primary rounded-full h-8 w-8 backdrop-blur-md border border-glass-border"
>
<ChevronLeft className="w-4 h-4" />
</Button>
@@ -105,7 +105,7 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
onClose();
if (onToggleOpen) onToggleOpen();
}}
className="bg-black/40 hover:bg-black/60 text-white rounded-full h-8 w-8 backdrop-blur-md border border-glass-border"
className="bg-glass-background hover:bg-glass-border text-glass-text-primary rounded-full h-8 w-8 backdrop-blur-md border border-glass-border"
>
<X className="w-4 h-4" />
</Button>
@@ -119,8 +119,8 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
className="absolute inset-0 z-10 flex items-center justify-center"
style={FADE_BOTTOM_STYLE}
>
<Skeleton className="h-full w-full absolute inset-0 bg-white/5" />
<Coffee className="h-12 w-12 text-white/20 animate-pulse relative z-20" />
<Skeleton className="h-full w-full absolute inset-0 bg-glass-border" />
<Coffee className="h-12 w-12 text-glass-text-secondary/20 animate-pulse relative z-20" />
</div>
)}
<div className="absolute inset-0 z-0">
@@ -150,7 +150,7 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
</div>
<div className="space-y-3">
<Button className="w-full bg-white text-black hover:bg-white/90 gap-2 font-medium" asChild>
<Button className="w-full bg-black text-white hover:bg-black/90 dark:bg-white dark:text-black dark:hover:bg-white/90 gap-2 font-medium" asChild>
<a
href={`https://www.google.com/maps/dir/?api=1&destination=${activeShop.lat},${activeShop.lng}`}
target="_blank"
@@ -162,7 +162,7 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
</Button>
<div className="grid grid-cols-2 gap-3">
{activeShop.website && (
<Button variant="outline" className="w-full border-glass-border text-glass-text-primary hover:bg-glass-border hover:text-white gap-2 text-xs" asChild>
<Button variant="outline" className="w-full border-glass-border text-glass-text-primary hover:bg-glass-border hover:text-glass-text-primary gap-2 text-xs" asChild>
<a href={activeShop.website} target="_blank" rel="noopener noreferrer">
<Globe className="w-3.5 h-3.5" />
Website
@@ -170,7 +170,7 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
</Button>
)}
{activeShop.phone && (
<Button variant="outline" className="w-full border-glass-border text-glass-text-primary hover:bg-glass-border hover:text-white gap-2 text-xs" asChild>
<Button variant="outline" className="w-full border-glass-border text-glass-text-primary hover:bg-glass-border hover:text-glass-text-primary gap-2 text-xs" asChild>
<a href={`tel:${activeShop.phone}`}>
<Phone className="w-3.5 h-3.5" />
Call
@@ -207,7 +207,7 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
<ScrollArea className="flex-1 min-h-0">
<div className="p-4 space-y-6">
{filteredShops.length === 0 ? (
<div className="text-center py-8 text-white/40">
<div className="text-center py-8 text-glass-text-secondary/60">
<Coffee className="h-12 w-12 mx-auto mb-3 opacity-20" />
<p>No shops found matching "{searchQuery}"</p>
</div>
@@ -272,13 +272,13 @@ function ShopListItem({ shop, onSelect, isFavorite, onToggleFavorite }: { shop:
<Button
variant="ghost"
size="icon"
className="h-6 w-6 -mr-1 -mt-1 hover:bg-white/10 text-glass-text-secondary hover:text-red-500"
className="h-6 w-6 -mr-1 -mt-1 hover:bg-glass-border text-glass-text-secondary hover:text-red-500"
onClick={(e) => onToggleFavorite(shop.id, e)}
>
<Heart className={`w-4 h-4 ${isFavorite ? 'fill-red-500 text-red-500' : ''}`} />
</Button>
</div>
<p className="text-sm text-glass-text-secondary leading-snug group-hover:text-white/80 transition-colors line-clamp-2">{shop.address}</p>
<p className="text-sm text-glass-text-secondary leading-snug group-hover:text-glass-text-primary transition-colors line-clamp-2">{shop.address}</p>
</div>
</div>
);

View File

@@ -72,7 +72,7 @@ export function LocateControl() {
size="icon"
onClick={handleLocate}
disabled={loading}
className="rounded-xl border border-glass-border bg-glass-background text-glass-text-primary shadow-lg backdrop-blur-md transition-all hover:bg-glass-border hover:text-white"
className="rounded-xl border border-glass-border bg-glass-background text-glass-text-primary shadow-lg backdrop-blur-md transition-all hover:bg-glass-border"
>
<Locate className={`h-5 w-5 ${loading ? 'animate-pulse' : ''}`} />
<span className="sr-only">Locate me</span>

View File

@@ -3,6 +3,7 @@
import * as React from "react";
import { Layers, Moon, Sun, Globe } from "lucide-react";
import { Button } from "~/components/ui/button";
import { useTheme } from "next-themes";
import {
DropdownMenu,
DropdownMenuContent,
@@ -16,24 +17,33 @@ interface MapStyleControlProps {
}
export function MapStyleControl({ currentStyle, onStyleChange }: MapStyleControlProps) {
const { setTheme } = useTheme();
const handleStyleChange = (style: string) => {
onStyleChange(style);
if (style === "dark") setTheme("dark");
if (style === "light") setTheme("light");
if (style === "satellite") setTheme("dark"); // Satellite looks better with dark UI
};
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon" className="rounded-xl border border-glass-border bg-glass-background text-glass-text-primary shadow-lg backdrop-blur-md transition-all hover:bg-glass-border hover:text-white">
<Button variant="outline" size="icon" className="rounded-xl border border-glass-border bg-glass-background text-glass-text-primary shadow-lg backdrop-blur-md transition-all hover:bg-glass-border">
<Layers className="h-5 w-5" />
<span className="sr-only">Change map style</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-40 bg-background/90 backdrop-blur-xl">
<DropdownMenuItem onClick={() => onStyleChange("dark")} className={currentStyle === "dark" ? "bg-accent" : ""}>
<DropdownMenuContent align="end" className="w-40 bg-glass-background backdrop-blur-xl border-glass-border">
<DropdownMenuItem onClick={() => handleStyleChange("dark")} className={`text-glass-text-primary focus:bg-glass-border focus:text-glass-text-primary cursor-pointer ${currentStyle === "dark" ? "bg-glass-border" : ""}`}>
<Moon className="mr-2 h-4 w-4" />
Dark
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onStyleChange("light")} className={currentStyle === "light" ? "bg-accent" : ""}>
<DropdownMenuItem onClick={() => handleStyleChange("light")} className={`text-glass-text-primary focus:bg-glass-border focus:text-glass-text-primary cursor-pointer ${currentStyle === "light" ? "bg-glass-border" : ""}`}>
<Sun className="mr-2 h-4 w-4" />
Light
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onStyleChange("satellite")} className={currentStyle === "satellite" ? "bg-accent" : ""}>
<DropdownMenuItem onClick={() => handleStyleChange("satellite")} className={`text-glass-text-primary focus:bg-glass-border focus:text-glass-text-primary cursor-pointer ${currentStyle === "satellite" ? "bg-glass-border" : ""}`}>
<Globe className="mr-2 h-4 w-4" />
Satellite
</DropdownMenuItem>

View File

@@ -1,4 +1,4 @@
import { Coffee, Search, X } from "lucide-react";
import { Coffee, PanelLeft, X } from "lucide-react";
import { Button } from "~/components/ui/button";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/components/ui/tooltip";
import { useState, useEffect } from "react";
@@ -59,9 +59,9 @@ export default function Navbar({ isDiscoveryOpen, onToggleDiscovery }: NavbarPro
setIsOnboarding(false);
localStorage.setItem('discovery-panel-hint-seen', 'true');
}}
className={`h-10 w-10 rounded-lg transition-colors ${isDiscoveryOpen ? 'bg-glass-border text-amber-500' : 'text-glass-text-primary hover:bg-glass-border hover:text-white'}`}
className={`h-10 w-10 rounded-lg transition-colors ${isDiscoveryOpen ? 'bg-glass-border text-amber-500' : 'text-glass-text-primary hover:bg-glass-border'}`}
>
<Search className="h-5 w-5" />
<PanelLeft className="h-5 w-5" />
<span className="sr-only">Toggle Panel</span>
</Button>
</TooltipTrigger>
@@ -97,7 +97,7 @@ export default function Navbar({ isDiscoveryOpen, onToggleDiscovery }: NavbarPro
variant="ghost"
size="icon"
onClick={() => setShowAbout(false)}
className="absolute top-4 right-4 text-glass-text-secondary hover:text-white hover:bg-glass-border"
className="absolute top-4 right-4 text-glass-text-secondary hover:text-glass-text-primary hover:bg-glass-border"
>
<X className="w-5 h-5" />
</Button>
@@ -107,15 +107,15 @@ export default function Navbar({ isDiscoveryOpen, onToggleDiscovery }: NavbarPro
<Coffee className="w-8 h-8 text-amber-500" />
</div>
<h2 className="text-2xl font-bold font-serif">Lewisburg Coffee Map</h2>
<p className="text-white/60 font-serif leading-relaxed">
<p className="text-glass-text-secondary font-serif leading-relaxed">
Discover the best coffee spots in Lewisburg, PA. Click on any marker to learn more about each location,
or use the discovery panel to browse and search all available shops.
</p>
<div className="w-full h-px bg-white/10 my-4" />
<div className="w-full h-px bg-glass-border my-4" />
<div className="text-xs text-white/60 space-y-2 font-sans w-full text-left">
<p><strong className="text-white/80">Features:</strong></p>
<div className="text-xs text-glass-text-secondary space-y-2 font-sans w-full text-left">
<p><strong className="text-glass-text-primary">Features:</strong></p>
<ul className="list-disc list-inside space-y-1 ml-2">
<li>Interactive map with coffee shop locations</li>
<li>Search and filter coffee shops</li>
@@ -123,9 +123,9 @@ export default function Navbar({ isDiscoveryOpen, onToggleDiscovery }: NavbarPro
<li>Get directions to any shop</li>
<li>Light/Dark theme support</li>
</ul>
<div className="pt-4 border-t border-white/10 mt-4">
<p>Map Data © <a href="https://www.openstreetmap.org/copyright" className="underline hover:text-white transition-colors">OpenStreetMap</a> contributors</p>
<p>Tiles © <a href="https://carto.com/attributions" className="underline hover:text-white transition-colors">CARTO</a></p>
<div className="pt-4 border-t border-glass-border mt-4">
<p>Map Data © <a href="https://www.openstreetmap.org/copyright" className="underline hover:text-glass-text-primary transition-colors">OpenStreetMap</a> contributors</p>
<p>Tiles © <a href="https://carto.com/attributions" className="underline hover:text-glass-text-primary transition-colors">CARTO</a></p>
</div>
</div>
</div>

View File

@@ -88,7 +88,7 @@ export function WelcomeModal() {
</div>
</div>
<div className="flex justify-center">
<Button onClick={handleClose} className="w-full sm:w-auto min-w-[120px] bg-white text-black hover:bg-white/90">
<Button onClick={handleClose} className="w-full sm:w-auto min-w-[120px] bg-black text-white hover:bg-black/90 dark:bg-white dark:text-black dark:hover:bg-white/90">
Start Exploring
</Button>
</div>

View File

@@ -13,7 +13,7 @@ export function ZoomControls() {
variant="outline"
size="icon"
onClick={() => map.zoomIn()}
className="rounded-xl border border-glass-border bg-glass-background text-glass-text-primary shadow-lg backdrop-blur-md transition-all hover:bg-glass-border hover:text-white"
className="rounded-xl border border-glass-border bg-glass-background text-glass-text-primary shadow-lg backdrop-blur-md transition-all hover:bg-glass-border"
>
<Plus className="h-5 w-5" />
<span className="sr-only">Zoom in</span>
@@ -22,7 +22,7 @@ export function ZoomControls() {
variant="outline"
size="icon"
onClick={() => map.zoomOut()}
className="rounded-xl border border-glass-border bg-glass-background text-glass-text-primary shadow-lg backdrop-blur-md transition-all hover:bg-glass-border hover:text-white"
className="rounded-xl border border-glass-border bg-glass-background text-glass-text-primary shadow-lg backdrop-blur-md transition-all hover:bg-glass-border"
>
<Minus className="h-5 w-5" />
<span className="sr-only">Zoom out</span>
@@ -31,7 +31,7 @@ export function ZoomControls() {
variant="outline"
size="icon"
onClick={() => map.setView([40.9645, -76.8845], 15)}
className="rounded-xl border border-glass-border bg-glass-background text-glass-text-primary shadow-lg backdrop-blur-md transition-all hover:bg-glass-border hover:text-white"
className="rounded-xl border border-glass-border bg-glass-background text-glass-text-primary shadow-lg backdrop-blur-md transition-all hover:bg-glass-border"
>
<Home className="h-5 w-5" />
<span className="sr-only">Reset view</span>

View File

@@ -53,10 +53,10 @@
:root {
--radius: 0.625rem;
/* ... existing vars ... */
--glass-background: rgba(0, 0, 0, 0.7);
--glass-border: rgba(255, 255, 255, 0.15);
--glass-text-primary: rgba(255, 255, 255, 0.95);
--glass-text-secondary: rgba(255, 255, 255, 0.70);
--glass-background: rgba(255, 255, 255, 0.75);
--glass-border: rgba(0, 0, 0, 0.1);
--glass-text-primary: rgba(0, 0, 0, 0.9);
--glass-text-secondary: rgba(0, 0, 0, 0.6);
--background: oklch(1 0 0);
/* ... */
@@ -93,6 +93,11 @@
}
.dark {
--glass-background: rgba(0, 0, 0, 0.6);
--glass-border: rgba(255, 255, 255, 0.15);
--glass-text-primary: rgba(255, 255, 255, 0.95);
--glass-text-secondary: rgba(255, 255, 255, 0.70);
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
@@ -130,6 +135,7 @@
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}