Desktop map Layers popover (#6) + canonical entity colors (#7)

#6 Desktop parity:
- Replaced the four separate Spots/Shops/Gear/Tours toggle buttons in the
  desktop map toolbar with a single grouped "Layers" popover (with count
  badge), matching the mobile control. Declutters the dense toolbar row.

#7 Entity color discipline:
- Locked the four map-entity colors to a single canonical value each,
  matching the map markers (source of truth): Spots #ff0040, Shops #9333ea,
  Gear #f97316, Tours #06b6d4.
- Fixed the mismatch I'd introduced (Layers popover + Add FAB used #a855f7
  purple instead of the marker's #9333ea). Everything now agrees.

Note: broader purple usage (Stash, Cashu, NWC, Editors) is intentionally
left as-is — those are separate semantic uses, not the map entity language.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
shakespeare.diy 2026-07-24 10:32:57 +07:00
parent bb6b3e6b7e
commit aa4c5ca697

View file

@ -1165,53 +1165,58 @@ export default function MapPage() {
{/* Row 2: Entity toggles + Sort/Filter + Add buttons (DESKTOP ONLY) */} {/* Row 2: Entity toggles + Sort/Filter + Add buttons (DESKTOP ONLY) */}
<div className="hidden md:flex items-center gap-2 mt-2 overflow-x-auto scrollbar-hide -mx-3 px-3 sm:mx-0 sm:px-0"> <div className="hidden md:flex items-center gap-2 mt-2 overflow-x-auto scrollbar-hide -mx-3 px-3 sm:mx-0 sm:px-0">
{/* Entity toggles */} {/* Layers — grouped popover (matches the mobile Layers control).
<Button Replaces four separate entity-toggle buttons to declutter the
variant={showSpots ? 'default' : 'outline'} desktop toolbar while keeping the entity color language. */}
size="sm" <Popover>
className={cn( <PopoverTrigger asChild>
'gap-1 font-bold text-xs px-2.5 h-8 flex-shrink-0 touch-manipulation active:scale-95', <Button
showSpots ? 'bg-red-500 hover:bg-red-600' : 'border-gray-700' variant="outline"
)} size="sm"
onClick={() => setShowSpots(!showSpots)} className="gap-1.5 font-bold text-xs px-2.5 h-8 flex-shrink-0 border-gray-700 hover:border-white/30 touch-manipulation active:scale-95"
> >
🛹 <span className="hidden xs:inline">{t('mapPage.spots')}</span> <Layers className="h-3.5 w-3.5" />
</Button> <span>Layers</span>
<Button <span className="ml-0.5 min-w-[18px] h-[18px] px-1 text-[10px] font-black bg-[#ccff00] text-black rounded-full flex items-center justify-center leading-none">
variant={showShops ? 'default' : 'outline'} {mobileLayerCount}
size="sm" </span>
className={cn( </Button>
'gap-1 font-bold text-xs px-2.5 h-8 flex-shrink-0 touch-manipulation active:scale-95', </PopoverTrigger>
showShops ? 'bg-purple-600 hover:bg-purple-700' : 'border-gray-700' <PopoverContent align="start" className="w-52 p-2 bg-black/95 border-white/15 backdrop-blur-xl">
)} <p className="text-[10px] font-bold text-muted-foreground uppercase tracking-wider px-1.5 pb-1.5">Show on Map</p>
onClick={() => setShowShops(!showShops)} <div className="space-y-0.5">
> {[
🏪 <span className="hidden xs:inline">{t('mapPage.shops')}</span> { key: 'spots', label: 'Spots', dot: '#ff0040', active: showSpots, toggle: () => setShowSpots(v => !v) },
</Button> { key: 'shops', label: 'Shops', dot: '#9333ea', active: showShops, toggle: () => setShowShops(v => !v) },
<Button { key: 'gear', label: 'Gear', dot: '#f97316', active: showGear, toggle: () => setShowGear(v => !v) },
variant={showGear ? 'default' : 'outline'} { key: 'tours', label: 'Tours', dot: '#06b6d4', active: showTours, toggle: () => setShowTours(v => !v) },
size="sm" ].map(({ key, label, dot, active, toggle }) => (
className={cn( <button
'gap-1 font-bold text-xs px-2.5 h-8 flex-shrink-0 touch-manipulation active:scale-95', key={key}
showGear ? 'bg-orange-500 hover:bg-orange-600' : 'border-gray-700' onClick={toggle}
)} className={cn(
onClick={() => setShowGear(!showGear)} 'w-full flex items-center gap-2.5 px-1.5 py-2 rounded-lg text-sm font-semibold transition-colors',
> active ? 'text-white hover:bg-white/5' : 'text-gray-500 hover:bg-white/5'
<ShoppingBag className="h-3.5 w-3.5" /> )}
<span className="hidden xs:inline">{t('marketplace.gear')}</span> >
</Button> <span
<Button className={cn('w-2.5 h-2.5 rounded-full flex-shrink-0 transition-opacity', active ? 'opacity-100' : 'opacity-30')}
variant={showTours ? 'default' : 'outline'} style={{ backgroundColor: dot }}
size="sm" />
className={cn( <span className="flex-1 text-left">{label}</span>
'gap-1 font-bold text-xs px-2.5 h-8 flex-shrink-0 touch-manipulation active:scale-95', <span
showTours ? 'bg-cyan-500 hover:bg-cyan-600' : 'border-gray-700' className={cn(
)} 'w-4 h-4 rounded flex items-center justify-center flex-shrink-0 border transition-colors',
onClick={() => setShowTours(!showTours)} active ? 'bg-[#ccff00] border-[#ccff00]' : 'border-white/20'
> )}
<Route className="h-3.5 w-3.5" /> >
<span className="hidden xs:inline">Local Tours</span> {active && <Check className="h-3 w-3 text-black" strokeWidth={3} />}
</Button> </span>
</button>
))}
</div>
</PopoverContent>
</Popover>
{/* BTC Map toggle */} {/* BTC Map toggle */}
<Tooltip> <Tooltip>
@ -1548,7 +1553,7 @@ export default function MapPage() {
<div className="space-y-0.5"> <div className="space-y-0.5">
{[ {[
{ key: 'spots', label: 'Spots', dot: '#ff0040', active: showSpots, toggle: () => setShowSpots(v => !v) }, { key: 'spots', label: 'Spots', dot: '#ff0040', active: showSpots, toggle: () => setShowSpots(v => !v) },
{ key: 'shops', label: 'Shops', dot: '#a855f7', active: showShops, toggle: () => setShowShops(v => !v) }, { key: 'shops', label: 'Shops', dot: '#9333ea', active: showShops, toggle: () => setShowShops(v => !v) },
{ key: 'gear', label: 'Gear', dot: '#f97316', active: showGear, toggle: () => setShowGear(v => !v) }, { key: 'gear', label: 'Gear', dot: '#f97316', active: showGear, toggle: () => setShowGear(v => !v) },
{ key: 'tours', label: 'Tours', dot: '#06b6d4', active: showTours, toggle: () => setShowTours(v => !v) }, { key: 'tours', label: 'Tours', dot: '#06b6d4', active: showTours, toggle: () => setShowTours(v => !v) },
].map(({ key, label, dot, active, toggle }) => ( ].map(({ key, label, dot, active, toggle }) => (
@ -1594,7 +1599,7 @@ export default function MapPage() {
<> <>
{[ {[
{ label: 'Add Spot', to: '/create-spot', bg: 'bg-[#ff0040]', icon: <MapPin className="h-4 w-4 text-white" /> }, { label: 'Add Spot', to: '/create-spot', bg: 'bg-[#ff0040]', icon: <MapPin className="h-4 w-4 text-white" /> },
{ label: 'Add Shop', to: '/create-shop', bg: 'bg-[#a855f7]', icon: <Store className="h-4 w-4 text-white" /> }, { label: 'Add Shop', to: '/create-shop', bg: 'bg-[#9333ea]', icon: <Store className="h-4 w-4 text-white" /> },
{ label: 'Offer Tour', to: '/create-tour', bg: 'bg-[#06b6d4]', icon: <Route className="h-4 w-4 text-white" /> }, { label: 'Offer Tour', to: '/create-tour', bg: 'bg-[#06b6d4]', icon: <Route className="h-4 w-4 text-white" /> },
].map((a, i) => ( ].map((a, i) => (
<Link <Link