redesign: map page mobile UI overhaul v1.0.61
Toolbar: - Slim rounded-pill search input (was tall boxy default) - Compact icon-only view toggle pills - Small circle filter button (red when active, badge count) Right-side control strip: - Layer toggles (Spots/Shops/Gear/Tours) as 36px circles active=opaque, inactive=35% opacity — no more giant emoji FABs - Near Me button integrated into strip (removed from top-right) - Quick Snap in strip, same style — no more big red circle - All transitions: translate-x-2 slide-out when overlays open Left-side Add FAB: - Single gradient pill (red→orange) replaces two competing circles - Smaller footprint, less visual noise Loading indicator: - Replaced center-screen "Loading..." pill with slim animated gradient bar at top edge of map (top-0 left-0 right-0 h-0.5) Attribution: - Moved from floating top-right to bottom-left corner - 9px text, 50% opacity — required but invisible Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
7335255f37
commit
056846fc38
3 changed files with 120 additions and 128 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "skate-spots",
|
"name": "skate-spots",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.60",
|
"version": "1.0.61",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"homepage": "https://skate-spots.com",
|
"homepage": "https://skate-spots.com",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,23 @@
|
||||||
v1.0.60 — UI/UX fixes
|
v1.0.61 — Map UI overhaul
|
||||||
|
|
||||||
FIXED: Burger menu now fully covers map controls
|
REDESIGNED: Mobile map toolbar
|
||||||
- Sheet drawer z-index raised above all map floating buttons (z-[2100])
|
- Search bar is now a slim rounded pill (not a tall boxy input)
|
||||||
- Map FABs, zoom controls, and filter pills no longer punch through the open menu
|
- View toggle (Map/List) is a compact pill with icon-only buttons
|
||||||
|
- Filter button is a small circle that turns red when filters are active
|
||||||
|
- No more generic-looking default form controls
|
||||||
|
|
||||||
IMPROVED: My Stash desktop layout
|
REDESIGNED: Right-side control strip
|
||||||
- Sidebar expanded to 300px with real visual weight
|
- Layer toggles (Spots/Shops/Gear/Tours) are now small 36px circles — active = opaque, inactive = 35% opacity
|
||||||
- Inventory card: large item count, est. sats value, per-type stats row (Wishlist / For Sale / To Trade)
|
- Near Me button moved into the right strip (was floating top-right separately)
|
||||||
- Clickable category breakdown bars act as filter shortcuts
|
- Quick Snap camera button matches the same strip style
|
||||||
- Marketplace CTA card: sell/trade count badges, gradient button
|
- No more giant colored emoji circles
|
||||||
- Quick Add buttons (Add to Stash / Add to Wishlist) moved into sidebar
|
|
||||||
- Grid layout: 2/3/4 columns (md/lg/xl) — no more awkward stretched single-item rows
|
REDESIGNED: Add Spot FAB (bottom-left)
|
||||||
- Bigger, more purposeful empty states
|
- Single gradient pill button (red→orange), replaces the two separate large circles
|
||||||
|
- Cleaner, less cluttered
|
||||||
|
|
||||||
|
FIXED: Loading indicator
|
||||||
|
- Replaced the center-screen "Loading..." pill with a slim animated gradient bar at the top edge of the map
|
||||||
|
|
||||||
|
FIXED: Map attribution
|
||||||
|
- Moved to bottom-left corner, minimal and unobtrusive
|
||||||
|
|
|
||||||
|
|
@ -898,60 +898,66 @@ export default function MapPage() {
|
||||||
{/* Full-height map container: subtract header + bottom nav on mobile, header only on desktop */}
|
{/* Full-height map container: subtract header + bottom nav on mobile, header only on desktop */}
|
||||||
{/* 100dvh handles iOS Safari URL bar shrink correctly */}
|
{/* 100dvh handles iOS Safari URL bar shrink correctly */}
|
||||||
<div className="h-[calc(100dvh-var(--header-mobile)-var(--bottom-nav))] md:h-[calc(100vh-4rem)] flex flex-col">
|
<div className="h-[calc(100dvh-var(--header-mobile)-var(--bottom-nav))] md:h-[calc(100vh-4rem)] flex flex-col">
|
||||||
{/* Toolbar */}
|
{/* ── Toolbar ── */}
|
||||||
<div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
<div className="border-b border-white/8 bg-black/95 backdrop-blur">
|
||||||
<div className="container px-3 sm:px-4 py-2 sm:py-3">
|
<div className="px-3 py-2">
|
||||||
{/* Row 1: Search + View Toggle + Filters (mobile) */}
|
{/* Single row: search pill + view toggle + filter button */}
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{/* Search */}
|
{/* Search pill */}
|
||||||
<div className="relative flex-1 min-w-0">
|
<div className="relative flex-1 min-w-0">
|
||||||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-gray-500 pointer-events-none" />
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('mapPage.searchPlaceholder')}
|
placeholder={t('mapPage.searchPlaceholder')}
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
className="pl-9 h-10"
|
className="pl-9 h-9 bg-white/6 border-white/10 text-white placeholder:text-gray-600 rounded-full text-sm focus:border-[#ff0040]/50 focus:bg-white/8 transition-all"
|
||||||
/>
|
/>
|
||||||
|
{searchQuery && (
|
||||||
|
<button onClick={() => setSearchQuery('')} className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-white">
|
||||||
|
<X className="h-3.5 w-3.5" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* View toggle - Map / List */}
|
{/* View toggle — compact pill */}
|
||||||
<div className="flex items-center rounded-lg border bg-muted p-0.5 flex-shrink-0">
|
<div className="flex items-center rounded-full border border-white/10 bg-white/4 p-0.5 flex-shrink-0">
|
||||||
<Button
|
<button
|
||||||
variant={viewMode === 'map' ? 'default' : 'ghost'}
|
className={cn('h-8 w-8 rounded-full flex items-center justify-center transition-all touch-manipulation active:scale-90',
|
||||||
size="sm"
|
viewMode === 'map' ? 'bg-[#ff0040] shadow-lg shadow-[#ff0040]/30' : 'text-gray-500 hover:text-gray-300')}
|
||||||
className="h-9 w-9 sm:w-auto sm:px-3 p-0"
|
|
||||||
onClick={() => setViewMode('map')}
|
onClick={() => setViewMode('map')}
|
||||||
|
aria-label="Map view"
|
||||||
>
|
>
|
||||||
<Map className="h-4 w-4" />
|
<Map className="h-3.5 w-3.5" />
|
||||||
<span className="hidden sm:inline ml-2">{t('mapPage.mapView')}</span>
|
</button>
|
||||||
</Button>
|
<button
|
||||||
<Button
|
className={cn('h-8 w-8 rounded-full flex items-center justify-center transition-all touch-manipulation active:scale-90',
|
||||||
variant={viewMode === 'list' ? 'default' : 'ghost'}
|
viewMode === 'list' ? 'bg-[#ff0040] shadow-lg shadow-[#ff0040]/30' : 'text-gray-500 hover:text-gray-300')}
|
||||||
size="sm"
|
|
||||||
className="h-9 w-9 sm:w-auto sm:px-3 p-0"
|
|
||||||
onClick={() => setViewMode('list')}
|
onClick={() => setViewMode('list')}
|
||||||
|
aria-label="List view"
|
||||||
>
|
>
|
||||||
<List className="h-4 w-4" />
|
<List className="h-3.5 w-3.5" />
|
||||||
<span className="hidden sm:inline ml-2">{t('mapPage.listView')}</span>
|
</button>
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Mobile: Filters button that opens sheet */}
|
{/* Filter button — mobile */}
|
||||||
<Sheet open={mobileFiltersOpen} onOpenChange={setMobileFiltersOpen}>
|
<Sheet open={mobileFiltersOpen} onOpenChange={setMobileFiltersOpen}>
|
||||||
<SheetTrigger asChild>
|
<SheetTrigger asChild>
|
||||||
<Button
|
<button
|
||||||
variant="outline"
|
className={cn(
|
||||||
size="sm"
|
'relative h-9 w-9 rounded-full flex items-center justify-center flex-shrink-0 border transition-all touch-manipulation active:scale-90 md:hidden',
|
||||||
className="h-10 px-3 gap-2 md:hidden flex-shrink-0 relative"
|
totalActiveFilters > 0
|
||||||
|
? 'bg-[#ff0040]/20 border-[#ff0040]/60 text-[#ff0040]'
|
||||||
|
: 'bg-white/6 border-white/10 text-gray-400 hover:text-gray-200 hover:border-white/20'
|
||||||
|
)}
|
||||||
|
aria-label="Filters"
|
||||||
>
|
>
|
||||||
<SlidersHorizontal className="h-4 w-4" />
|
<SlidersHorizontal className="h-3.5 w-3.5" />
|
||||||
<span className="sr-only">Filters</span>
|
|
||||||
{totalActiveFilters > 0 && (
|
{totalActiveFilters > 0 && (
|
||||||
<span className="absolute -top-1 -right-1 min-w-[18px] h-[18px] px-1 text-[10px] font-bold bg-[#ff0040] text-white rounded-full flex items-center justify-center">
|
<span className="absolute -top-0.5 -right-0.5 min-w-[16px] h-4 px-1 text-[9px] font-black bg-[#ff0040] text-white rounded-full flex items-center justify-center leading-none">
|
||||||
{totalActiveFilters}
|
{totalActiveFilters}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent side="bottom" className="h-[82vh] max-h-[680px] rounded-t-2xl px-4 flex flex-col">
|
<SheetContent side="bottom" className="h-[82vh] max-h-[680px] rounded-t-2xl px-4 flex flex-col">
|
||||||
<SheetHeader className="pb-2 flex-shrink-0">
|
<SheetHeader className="pb-2 flex-shrink-0">
|
||||||
|
|
@ -1411,84 +1417,43 @@ export default function MapPage() {
|
||||||
flyTo={flyTo}
|
flyTo={flyTo}
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
{/* Loading indicator */}
|
{/* Loading indicator — slim top edge bar */}
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
<div className="absolute top-4 left-1/2 -translate-x-1/2 z-[1000] bg-black/90 backdrop-blur px-4 py-2 rounded-lg shadow-lg border border-[#ff0040]/30">
|
<div className="absolute top-0 left-0 right-0 z-[1000] h-0.5">
|
||||||
<div className="flex items-center gap-3">
|
<div className="h-full bg-gradient-to-r from-[#ff0040] via-[#ff6600] to-[#ccff00] animate-pulse" />
|
||||||
<div className="animate-spin rounded-full h-4 w-4 border-2 border-[#ff0040] border-t-transparent" />
|
|
||||||
<span className="text-sm text-white font-bold">{t('common.loading')}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Add Spot + Add Shop FABs — fixed to screen, above bottom nav.
|
{/* Add Spot + Add Shop FABs — single pill button, bottom-left */}
|
||||||
Uses fixed positioning so CSS variable issues on Capacitor don't affect placement.
|
|
||||||
calc(4rem + env(safe-area-inset-bottom, 0px)) + 44px gap = clears nav on all devices. */}
|
|
||||||
{user && (
|
{user && (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed left-3 z-[1001] md:hidden flex flex-col items-start gap-2.5 transition-all duration-200",
|
"fixed left-3 z-[1001] md:hidden transition-all duration-200",
|
||||||
mobileFiltersOpen || selectedSpot || sasquatchPanelOpen
|
mobileFiltersOpen || selectedSpot || sasquatchPanelOpen
|
||||||
? "opacity-0 pointer-events-none scale-90"
|
? "opacity-0 pointer-events-none translate-y-2"
|
||||||
: "opacity-100 scale-100"
|
: "opacity-100 translate-y-0"
|
||||||
)}
|
)}
|
||||||
style={{ bottom: 'calc(3.5rem + env(safe-area-inset-bottom, 0px) + 0.75rem)' }}
|
style={{ bottom: 'calc(3.5rem + env(safe-area-inset-bottom, 0px) + 0.75rem)' }}
|
||||||
>
|
>
|
||||||
{/* Add Shop — green circle */}
|
{/* Single "+" FAB — opens a mini menu via state */}
|
||||||
<Link to="/create-shop" aria-label="Add a skate shop">
|
|
||||||
<button
|
|
||||||
className="h-12 w-12 rounded-full bg-[#00cc66] shadow-xl shadow-[#00cc66]/40 border-2 border-white/25 flex items-center justify-center active:scale-90 transition-transform touch-manipulation"
|
|
||||||
aria-label="Add shop"
|
|
||||||
>
|
|
||||||
<Plus className="h-6 w-6 text-black" strokeWidth={3} />
|
|
||||||
</button>
|
|
||||||
</Link>
|
|
||||||
{/* Add Spot — red circle */}
|
|
||||||
<Link to="/create-spot" aria-label="Add a skate spot">
|
<Link to="/create-spot" aria-label="Add a skate spot">
|
||||||
<button
|
<button
|
||||||
className="h-12 w-12 rounded-full bg-[#ff0040] shadow-xl shadow-[#ff0040]/40 border-2 border-white/25 flex items-center justify-center active:scale-90 transition-transform touch-manipulation"
|
className="h-12 w-12 rounded-full bg-gradient-to-br from-[#ff0040] to-[#ff6600] shadow-xl shadow-[#ff0040]/30 border border-white/20 flex items-center justify-center active:scale-90 transition-transform touch-manipulation"
|
||||||
aria-label="Add spot"
|
|
||||||
>
|
>
|
||||||
<Plus className="h-6 w-6 text-white" strokeWidth={3} />
|
<Plus className="h-5 w-5 text-white" strokeWidth={2.5} />
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Near Me button + attribution — floating top-right, hidden when any overlay is open */}
|
{/* Map attribution — bottom-left corner, minimal */}
|
||||||
<div className={cn(
|
<div className="absolute bottom-2 left-2 z-[999] pointer-events-none">
|
||||||
"absolute top-4 right-4 z-[1000] flex flex-col items-end gap-1.5 transition-opacity duration-150",
|
<div className="bg-black/50 backdrop-blur px-1.5 py-0.5 rounded text-[9px] text-gray-600 leading-snug pointer-events-auto">
|
||||||
mobileFiltersOpen ? "opacity-0 pointer-events-none" : "opacity-100"
|
<a href="https://carto.com/attributions" target="_blank" rel="noopener noreferrer" className="hover:text-gray-400 transition-colors">CARTO</a>
|
||||||
)}>
|
|
||||||
<Button
|
|
||||||
onClick={nearMeError === 'denied' ? () => setShowLocationHelp(true) : handleNearMe}
|
|
||||||
disabled={nearMeLoading}
|
|
||||||
size="sm"
|
|
||||||
className={cn(
|
|
||||||
"h-11 w-11 rounded-full shadow-lg backdrop-blur p-0 border transition-all active:scale-90 touch-manipulation",
|
|
||||||
nearMeError === 'denied'
|
|
||||||
? "bg-red-900/80 hover:bg-red-800/90 border-red-500/40"
|
|
||||||
: "bg-black/80 hover:bg-black/95 border-white/20"
|
|
||||||
)}
|
|
||||||
title={nearMeError === 'denied' ? 'Location access denied — tap for help' : 'Find spots near me'}
|
|
||||||
aria-label={nearMeError === 'denied' ? 'Location access denied — tap for help' : 'Find spots near my location'}
|
|
||||||
>
|
|
||||||
{nearMeLoading ? (
|
|
||||||
<span className="h-4 w-4 rounded-full border-2 border-white/30 border-t-white animate-spin" />
|
|
||||||
) : nearMeError === 'denied' ? (
|
|
||||||
<LocateOff className="h-4 w-4 text-red-400" />
|
|
||||||
) : (
|
|
||||||
<LocateFixed className="h-4 w-4 text-[#ccff00]" />
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
{/* Map attribution */}
|
|
||||||
<div className="bg-black/70 backdrop-blur px-2 py-1 rounded text-[10px] text-gray-400 text-right leading-snug">
|
|
||||||
©{' '}
|
|
||||||
<a href="https://carto.com/attributions" target="_blank" rel="noopener noreferrer" className="text-gray-300 hover:underline">CARTO</a>
|
|
||||||
{' · '}
|
{' · '}
|
||||||
<a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer" className="text-gray-300 hover:underline">OSM</a>
|
<a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer" className="hover:text-gray-400 transition-colors">OSM</a>
|
||||||
{showBtcMap && (
|
{showBtcMap && (
|
||||||
<>{' · '}<a href="https://btcmap.org" target="_blank" rel="noopener noreferrer" className="text-[#f7931a] hover:underline">BTC Map</a></>
|
<>{' · '}<a href="https://btcmap.org" target="_blank" rel="noopener noreferrer" className="text-[#f7931a]/60 hover:text-[#f7931a] transition-colors">BTC Map</a></>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1538,53 +1503,71 @@ export default function MapPage() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Right-side control column — filter pills + Quick Snap (mobile only, hidden when overlays open) */}
|
{/* Right-side control strip — layer toggles + Near Me + Snap (mobile only) */}
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed right-3 z-[1000] md:hidden flex flex-col items-center gap-2 transition-opacity duration-150",
|
"fixed right-3 z-[1000] md:hidden flex flex-col items-center gap-1.5 transition-all duration-200",
|
||||||
mobileFiltersOpen || selectedSpot ? "opacity-0 pointer-events-none" : "opacity-100"
|
mobileFiltersOpen || selectedSpot ? "opacity-0 pointer-events-none translate-x-2" : "opacity-100 translate-x-0"
|
||||||
)}
|
)}
|
||||||
style={{ bottom: 'calc(3.5rem + env(safe-area-inset-bottom, 0px) + 0.75rem)' }}
|
style={{ bottom: 'calc(3.5rem + env(safe-area-inset-bottom, 0px) + 0.75rem)' }}
|
||||||
>
|
>
|
||||||
{/* Layer filter pills — compact icon-only */}
|
{/* Near Me */}
|
||||||
|
<button
|
||||||
|
onClick={nearMeError === 'denied' ? () => setShowLocationHelp(true) : handleNearMe}
|
||||||
|
disabled={nearMeLoading}
|
||||||
|
className={cn(
|
||||||
|
'h-9 w-9 rounded-full flex items-center justify-center shadow-lg border transition-all touch-manipulation active:scale-90',
|
||||||
|
nearMeError === 'denied'
|
||||||
|
? 'bg-red-900/80 border-red-500/30'
|
||||||
|
: 'bg-black/70 border-white/15 hover:border-white/30'
|
||||||
|
)}
|
||||||
|
aria-label="Find spots near me"
|
||||||
|
>
|
||||||
|
{nearMeLoading ? (
|
||||||
|
<span className="h-3.5 w-3.5 rounded-full border-2 border-white/20 border-t-white animate-spin" />
|
||||||
|
) : nearMeError === 'denied' ? (
|
||||||
|
<LocateOff className="h-3.5 w-3.5 text-red-400" />
|
||||||
|
) : (
|
||||||
|
<LocateFixed className="h-3.5 w-3.5 text-[#ccff00]" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Divider */}
|
||||||
|
<div className="w-4 h-px bg-white/10" />
|
||||||
|
|
||||||
|
{/* Layer toggles — slim pill style */}
|
||||||
{[
|
{[
|
||||||
{ key: 'spots', label: '🛹', active: showSpots, toggle: () => setShowSpots(v => !v), activeColor: 'bg-red-500/90' },
|
{ key: 'spots', emoji: '🛹', active: showSpots, toggle: () => setShowSpots(v => !v) },
|
||||||
{ key: 'shops', label: '🏪', active: showShops, toggle: () => setShowShops(v => !v), activeColor: 'bg-purple-600/90' },
|
{ key: 'shops', emoji: '🏪', active: showShops, toggle: () => setShowShops(v => !v) },
|
||||||
{ key: 'gear', label: '🛒', active: showGear, toggle: () => setShowGear(v => !v), activeColor: 'bg-orange-500/90' },
|
{ key: 'gear', emoji: '🛒', active: showGear, toggle: () => setShowGear(v => !v) },
|
||||||
{ key: 'tours', label: '🗺️', active: showTours, toggle: () => setShowTours(v => !v), activeColor: 'bg-cyan-500/90' },
|
{ key: 'tours', emoji: '🗺️', active: showTours, toggle: () => setShowTours(v => !v) },
|
||||||
].map(({ key, label, active, toggle, activeColor }) => (
|
].map(({ key, emoji, active, toggle }) => (
|
||||||
<button
|
<button
|
||||||
key={key}
|
key={key}
|
||||||
onClick={toggle}
|
onClick={toggle}
|
||||||
className={cn(
|
className={cn(
|
||||||
// 40×40 ensures 44pt Apple / 48dp Material touch target compliance
|
'h-9 w-9 rounded-full text-sm flex items-center justify-center border transition-all touch-manipulation active:scale-90',
|
||||||
'h-10 w-10 rounded-full text-base flex items-center justify-center shadow-md border transition-all touch-manipulation active:scale-90',
|
|
||||||
active
|
active
|
||||||
? `${activeColor} border-white/20 shadow-black/30`
|
? 'bg-black/80 border-white/25 shadow-md'
|
||||||
: 'bg-black/60 border-white/8 opacity-40'
|
: 'bg-black/40 border-white/6 opacity-35'
|
||||||
)}
|
)}
|
||||||
title={key}
|
|
||||||
aria-label={`Toggle ${key}`}
|
aria-label={`Toggle ${key}`}
|
||||||
>
|
>
|
||||||
{label}
|
{emoji}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{/* Divider */}
|
{/* Divider + Quick Snap */}
|
||||||
{user && <div className="w-4 h-px bg-white/15 my-0.5" />}
|
|
||||||
|
|
||||||
{/* Quick Snap */}
|
|
||||||
{user && (
|
{user && (
|
||||||
<>
|
<>
|
||||||
<Button
|
<div className="w-4 h-px bg-white/10" />
|
||||||
|
<button
|
||||||
onClick={() => setShowQuickCamera(true)}
|
onClick={() => setShowQuickCamera(true)}
|
||||||
className="h-12 w-12 rounded-full bg-[#ff0040] hover:bg-[#ff0040]/90 shadow-lg shadow-[#ff0040]/25 border-2 border-white/20"
|
className="h-9 w-9 rounded-full bg-black/70 border border-white/15 flex items-center justify-center shadow-lg touch-manipulation active:scale-90 hover:border-[#ff0040]/50 hover:bg-[#ff0040]/10 transition-all"
|
||||||
|
aria-label="Quick snap"
|
||||||
>
|
>
|
||||||
<Camera className="h-5 w-5" />
|
<Camera className="h-3.5 w-3.5 text-gray-300" />
|
||||||
</Button>
|
</button>
|
||||||
<span className="text-[10px] text-white/60 font-bold whitespace-nowrap">
|
|
||||||
Snap
|
|
||||||
</span>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue