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 ( 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 - always visible */}
<Navbar isDiscoveryOpen={isDiscoveryOpen} onToggleDiscovery={() => setIsDiscoveryOpen(!isDiscoveryOpen)} /> <Navbar isDiscoveryOpen={isDiscoveryOpen} onToggleDiscovery={() => setIsDiscoveryOpen(!isDiscoveryOpen)} />

View File

@@ -54,7 +54,7 @@ export function AboutModal({ isOpen, onClose }: AboutModalProps) {
<div className="flex justify-center"> <div className="flex justify-center">
<Button <Button
variant="outline" 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 asChild
> >
<a href="https://github.com/soconnor0919/lewisburg-coffee" target="_blank" rel="noopener noreferrer"> <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" variant="ghost"
size="icon" size="icon"
onClick={(e) => toggleFavorite(activeShop.id, e)} 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>
<Button <Button
variant="ghost" variant="ghost"
size="icon" size="icon"
onClick={onClose} 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" /> <ChevronLeft className="w-4 h-4" />
</Button> </Button>
@@ -105,7 +105,7 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
onClose(); onClose();
if (onToggleOpen) onToggleOpen(); 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" /> <X className="w-4 h-4" />
</Button> </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" className="absolute inset-0 z-10 flex items-center justify-center"
style={FADE_BOTTOM_STYLE} style={FADE_BOTTOM_STYLE}
> >
<Skeleton className="h-full w-full absolute inset-0 bg-white/5" /> <Skeleton className="h-full w-full absolute inset-0 bg-glass-border" />
<Coffee className="h-12 w-12 text-white/20 animate-pulse relative z-20" /> <Coffee className="h-12 w-12 text-glass-text-secondary/20 animate-pulse relative z-20" />
</div> </div>
)} )}
<div className="absolute inset-0 z-0"> <div className="absolute inset-0 z-0">
@@ -150,7 +150,7 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
</div> </div>
<div className="space-y-3"> <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 <a
href={`https://www.google.com/maps/dir/?api=1&destination=${activeShop.lat},${activeShop.lng}`} href={`https://www.google.com/maps/dir/?api=1&destination=${activeShop.lat},${activeShop.lng}`}
target="_blank" target="_blank"
@@ -162,7 +162,7 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
</Button> </Button>
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
{activeShop.website && ( {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"> <a href={activeShop.website} target="_blank" rel="noopener noreferrer">
<Globe className="w-3.5 h-3.5" /> <Globe className="w-3.5 h-3.5" />
Website Website
@@ -170,7 +170,7 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
</Button> </Button>
)} )}
{activeShop.phone && ( {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}`}> <a href={`tel:${activeShop.phone}`}>
<Phone className="w-3.5 h-3.5" /> <Phone className="w-3.5 h-3.5" />
Call Call
@@ -207,7 +207,7 @@ export default function Drawer({ shop, shops, onSelect, onClose, isOpen, onToggl
<ScrollArea className="flex-1 min-h-0"> <ScrollArea className="flex-1 min-h-0">
<div className="p-4 space-y-6"> <div className="p-4 space-y-6">
{filteredShops.length === 0 ? ( {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" /> <Coffee className="h-12 w-12 mx-auto mb-3 opacity-20" />
<p>No shops found matching "{searchQuery}"</p> <p>No shops found matching "{searchQuery}"</p>
</div> </div>
@@ -272,13 +272,13 @@ function ShopListItem({ shop, onSelect, isFavorite, onToggleFavorite }: { shop:
<Button <Button
variant="ghost" variant="ghost"
size="icon" 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)} onClick={(e) => onToggleFavorite(shop.id, e)}
> >
<Heart className={`w-4 h-4 ${isFavorite ? 'fill-red-500 text-red-500' : ''}`} /> <Heart className={`w-4 h-4 ${isFavorite ? 'fill-red-500 text-red-500' : ''}`} />
</Button> </Button>
</div> </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>
</div> </div>
); );

View File

@@ -72,7 +72,7 @@ export function LocateControl() {
size="icon" size="icon"
onClick={handleLocate} onClick={handleLocate}
disabled={loading} 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' : ''}`} /> <Locate className={`h-5 w-5 ${loading ? 'animate-pulse' : ''}`} />
<span className="sr-only">Locate me</span> <span className="sr-only">Locate me</span>

View File

@@ -3,6 +3,7 @@
import * as React from "react"; import * as React from "react";
import { Layers, Moon, Sun, Globe } from "lucide-react"; import { Layers, Moon, Sun, Globe } from "lucide-react";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { useTheme } from "next-themes";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@@ -16,24 +17,33 @@ interface MapStyleControlProps {
} }
export function MapStyleControl({ currentStyle, onStyleChange }: 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 ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <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" /> <Layers className="h-5 w-5" />
<span className="sr-only">Change map style</span> <span className="sr-only">Change map style</span>
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-40 bg-background/90 backdrop-blur-xl"> <DropdownMenuContent align="end" className="w-40 bg-glass-background backdrop-blur-xl border-glass-border">
<DropdownMenuItem onClick={() => onStyleChange("dark")} className={currentStyle === "dark" ? "bg-accent" : ""}> <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" /> <Moon className="mr-2 h-4 w-4" />
Dark Dark
</DropdownMenuItem> </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" /> <Sun className="mr-2 h-4 w-4" />
Light Light
</DropdownMenuItem> </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" /> <Globe className="mr-2 h-4 w-4" />
Satellite Satellite
</DropdownMenuItem> </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 { Button } from "~/components/ui/button";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/components/ui/tooltip"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/components/ui/tooltip";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
@@ -59,9 +59,9 @@ export default function Navbar({ isDiscoveryOpen, onToggleDiscovery }: NavbarPro
setIsOnboarding(false); setIsOnboarding(false);
localStorage.setItem('discovery-panel-hint-seen', 'true'); 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> <span className="sr-only">Toggle Panel</span>
</Button> </Button>
</TooltipTrigger> </TooltipTrigger>
@@ -97,7 +97,7 @@ export default function Navbar({ isDiscoveryOpen, onToggleDiscovery }: NavbarPro
variant="ghost" variant="ghost"
size="icon" size="icon"
onClick={() => setShowAbout(false)} 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" /> <X className="w-5 h-5" />
</Button> </Button>
@@ -107,15 +107,15 @@ export default function Navbar({ isDiscoveryOpen, onToggleDiscovery }: NavbarPro
<Coffee className="w-8 h-8 text-amber-500" /> <Coffee className="w-8 h-8 text-amber-500" />
</div> </div>
<h2 className="text-2xl font-bold font-serif">Lewisburg Coffee Map</h2> <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, 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. or use the discovery panel to browse and search all available shops.
</p> </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"> <div className="text-xs text-glass-text-secondary space-y-2 font-sans w-full text-left">
<p><strong className="text-white/80">Features:</strong></p> <p><strong className="text-glass-text-primary">Features:</strong></p>
<ul className="list-disc list-inside space-y-1 ml-2"> <ul className="list-disc list-inside space-y-1 ml-2">
<li>Interactive map with coffee shop locations</li> <li>Interactive map with coffee shop locations</li>
<li>Search and filter coffee shops</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>Get directions to any shop</li>
<li>Light/Dark theme support</li> <li>Light/Dark theme support</li>
</ul> </ul>
<div className="pt-4 border-t border-white/10 mt-4"> <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-white transition-colors">OpenStreetMap</a> contributors</p> <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-white transition-colors">CARTO</a></p> <p>Tiles © <a href="https://carto.com/attributions" className="underline hover:text-glass-text-primary transition-colors">CARTO</a></p>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -88,7 +88,7 @@ export function WelcomeModal() {
</div> </div>
</div> </div>
<div className="flex justify-center"> <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 Start Exploring
</Button> </Button>
</div> </div>

View File

@@ -13,7 +13,7 @@ export function ZoomControls() {
variant="outline" variant="outline"
size="icon" size="icon"
onClick={() => map.zoomIn()} 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" /> <Plus className="h-5 w-5" />
<span className="sr-only">Zoom in</span> <span className="sr-only">Zoom in</span>
@@ -22,7 +22,7 @@ export function ZoomControls() {
variant="outline" variant="outline"
size="icon" size="icon"
onClick={() => map.zoomOut()} 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" /> <Minus className="h-5 w-5" />
<span className="sr-only">Zoom out</span> <span className="sr-only">Zoom out</span>
@@ -31,7 +31,7 @@ export function ZoomControls() {
variant="outline" variant="outline"
size="icon" size="icon"
onClick={() => map.setView([40.9645, -76.8845], 15)} 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" /> <Home className="h-5 w-5" />
<span className="sr-only">Reset view</span> <span className="sr-only">Reset view</span>

View File

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