fix: styles and add zooming into location

This commit is contained in:
2025-10-03 15:27:02 +02:00
parent b82141eb75
commit 00da815d52
4 changed files with 118 additions and 130 deletions

View File

@@ -1,121 +1,54 @@
@import 'tailwindcss';
@import 'tw-animate-css';
@custom-variant dark (&:is(.dark *));
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823);
--card: oklch(1 0 0);
--card-foreground: oklch(0.141 0.005 285.823);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.141 0.005 285.823);
--primary: oklch(0.21 0.006 285.885);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.967 0.001 286.375);
--secondary-foreground: oklch(0.21 0.006 285.885);
--muted: oklch(0.967 0.001 286.375);
--muted-foreground: oklch(0.552 0.016 285.938);
--accent: oklch(0.967 0.001 286.375);
--accent-foreground: oklch(0.21 0.006 285.885);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.92 0.004 286.32);
--input: oklch(0.92 0.004 286.32);
--ring: oklch(0.705 0.015 286.067);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.141 0.005 285.823);
--sidebar-primary: oklch(0.21 0.006 285.885);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.967 0.001 286.375);
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
--sidebar-border: oklch(0.92 0.004 286.32);
--sidebar-ring: oklch(0.705 0.015 286.067);
@font-face {
font-family: 'Washington';
src: url('/fonts/Washington.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
.dark {
--background: oklch(0.141 0.005 285.823);
--foreground: oklch(0.985 0 0);
--card: oklch(0.21 0.006 285.885);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.21 0.006 285.885);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.92 0.004 286.32);
--primary-foreground: oklch(0.21 0.006 285.885);
--secondary: oklch(0.274 0.006 286.033);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.274 0.006 286.033);
--muted-foreground: oklch(0.705 0.015 286.067);
--accent: oklch(0.274 0.006 286.033);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.552 0.016 285.938);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.21 0.006 285.885);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.274 0.006 286.033);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.552 0.016 285.938);
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
body {
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
sans-serif;
line-height: 1.5;
background-color: #f8f8f8;
color: #333;
margin: 0 auto;
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
h1 {
font-family: 'Washington', serif;
font-weight: normal;
}
h2,
h3,
h4,
h5,
h6 {
font-family: 'Times New Roman', Times, serif;
font-weight: normal;
}
button {
cursor: pointer;
font-family: inherit;
}
input {
font-family: inherit;
}
a {
color: inherit;
text-decoration: none;
}

View File

@@ -1,7 +1,13 @@
<script lang="ts">
import { MapLibre } from 'svelte-maplibre';
import { MapLibre, Marker } from 'svelte-maplibre';
import type { StyleSpecification } from 'svelte-maplibre';
import { coordinates, getMapCenter, getMapZoom } from '$lib/stores/location';
import {
coordinates,
getMapCenter,
getMapZoom,
shouldZoomToLocation,
locationActions
} from '$lib/stores/location';
import LocationButton from './LocationButton.svelte';
interface Props {
@@ -41,16 +47,46 @@
// Reactive center and zoom based on location or props
const mapCenter = $derived(
$coordinates && autoCenter
$coordinates && (autoCenter || $shouldZoomToLocation)
? ([$coordinates.longitude, $coordinates.latitude] as [number, number])
: center || $getMapCenter
);
const mapZoom = $derived($coordinates && autoCenter ? zoom || $getMapZoom : zoom || 13);
const mapZoom = $derived(() => {
if ($shouldZoomToLocation && $coordinates) {
// Force zoom to calculated level when location button is clicked
return $getMapZoom;
}
if ($coordinates && autoCenter) {
return $getMapZoom;
}
return zoom || 13;
});
// Effect to clear zoom trigger after it's been used
$effect(() => {
if ($shouldZoomToLocation) {
// Use a timeout to ensure the map has updated before clearing the trigger
setTimeout(() => {
locationActions.clearZoomTrigger();
}, 100);
}
});
</script>
<div class="map-container {className}">
<MapLibre {style} center={mapCenter} zoom={mapZoom} />
<MapLibre {style} center={mapCenter} zoom={mapZoom()}>
{#if $coordinates}
<Marker lngLat={[$coordinates.longitude, $coordinates.latitude]}>
<div class="location-marker">
<div class="marker-pulse"></div>
<div class="marker-outer">
<div class="marker-inner"></div>
</div>
</div>
</Marker>
{/if}
</MapLibre>
{#if showLocationButton}
<div class="location-controls">

View File

@@ -12,6 +12,7 @@ interface LocationState {
error: LocationError | null;
isWatching: boolean;
lastUpdated: Date | null;
shouldZoomToLocation: boolean;
}
const initialState: LocationState = {
@@ -19,7 +20,8 @@ const initialState: LocationState = {
status: 'idle',
error: null,
isWatching: false,
lastUpdated: null
lastUpdated: null,
shouldZoomToLocation: false
};
// Main location store
@@ -37,6 +39,10 @@ export const hasLocationAccess = derived(
locationStore,
($location) => $location.coordinates !== null
);
export const shouldZoomToLocation = derived(
locationStore,
($location) => $location.shouldZoomToLocation
);
// Location actions
export const locationActions = {
@@ -58,7 +64,8 @@ export const locationActions = {
coordinates,
status: 'success',
error: null,
lastUpdated: new Date()
lastUpdated: new Date(),
shouldZoomToLocation: true
}));
return coordinates;
@@ -169,6 +176,16 @@ export const locationActions = {
const ageInMinutes = (Date.now() - currentState.lastUpdated.getTime()) / (1000 * 60);
return ageInMinutes > maxAgeMinutes;
},
/**
* Clear the zoom trigger flag
*/
clearZoomTrigger(): void {
locationStore.update((state) => ({
...state,
shouldZoomToLocation: false
}));
}
};
@@ -182,14 +199,17 @@ export const getMapCenter = derived(coordinates, ($coordinates) => {
});
// Utility function to get appropriate zoom level based on accuracy
export const getMapZoom = derived(coordinates, ($coordinates) => {
export const getMapZoom = derived([coordinates, shouldZoomToLocation], ([$coordinates, $shouldZoom]) => {
if ($coordinates?.accuracy) {
// More aggressive zoom levels when location button is clicked
const baseZoom = $shouldZoom ? 2 : 0; // Add 2 zoom levels when triggered by button
// Adjust zoom based on accuracy (lower accuracy = lower zoom)
if ($coordinates.accuracy < 10) return 18; // Very accurate
if ($coordinates.accuracy < 50) return 16; // Good accuracy
if ($coordinates.accuracy < 100) return 14; // Moderate accuracy
if ($coordinates.accuracy < 500) return 12; // Low accuracy
return 10; // Very low accuracy
if ($coordinates.accuracy < 10) return Math.min(20, 18 + baseZoom); // Very accurate
if ($coordinates.accuracy < 50) return Math.min(19, 16 + baseZoom); // Good accuracy
if ($coordinates.accuracy < 100) return Math.min(18, 14 + baseZoom); // Moderate accuracy
if ($coordinates.accuracy < 500) return Math.min(16, 12 + baseZoom); // Low accuracy
return Math.min(15, 10 + baseZoom); // Very low accuracy
}
return 13; // Default zoom level
return $shouldZoom ? 16 : 13; // More aggressive default when triggered by button
});

View File

@@ -13,7 +13,6 @@
<style>
.home-container {
background-color: #f8f8f8;
min-height: 100vh;
}
.main-content {
@@ -29,7 +28,7 @@
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.map-section :global(.map-container) {