darkmode
This commit is contained in:
@@ -103,10 +103,10 @@
|
||||
|
||||
<Popover.Root bind:open={popoverOpen}>
|
||||
<Popover.Trigger
|
||||
class="flex h-9 w-full cursor-pointer items-center gap-2 rounded-md border border-border bg-background px-3 text-[0.8125rem] text-muted-foreground transition-[border-color,box-shadow] duration-150 hover:border-primary"
|
||||
class="flex h-10 w-full cursor-pointer items-center gap-2.5 rounded-full border-2 border-primary/30 bg-background px-4 text-[0.8125rem] font-medium text-muted-foreground shadow-xs transition-[border-color,box-shadow] duration-150 hover:border-primary/70 hover:shadow-md"
|
||||
>
|
||||
<svg
|
||||
class="h-3.5 w-3.5 shrink-0 opacity-50"
|
||||
class="h-4 w-4 shrink-0 text-primary"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { resolve } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
import { type GeoLocation, storedLocation } from '$lib/stores/settings';
|
||||
import { type GeoLocation, type Theme, storedLocation, storedTheme } from '$lib/stores/settings';
|
||||
|
||||
import { buildLocationRoute } from '$lib/utils/location';
|
||||
|
||||
@@ -23,6 +23,19 @@
|
||||
location = value;
|
||||
});
|
||||
|
||||
const themeCycle: Theme[] = ['system', 'light', 'dark'];
|
||||
const themeTitles: Record<Theme, string> = {
|
||||
system: 'Theme: follow system',
|
||||
light: 'Theme: light',
|
||||
dark: 'Theme: dark'
|
||||
};
|
||||
|
||||
function cycleTheme() {
|
||||
storedTheme.update(
|
||||
(current) => themeCycle[(themeCycle.indexOf(current) + 1) % themeCycle.length]
|
||||
);
|
||||
}
|
||||
|
||||
function navigateToLocation(newLocation: GeoLocation) {
|
||||
storedLocation.set(newLocation);
|
||||
const locationRoute = buildLocationRoute(newLocation);
|
||||
@@ -54,17 +67,19 @@
|
||||
|
||||
<!-- Current location display -->
|
||||
{#if location}
|
||||
<div class="hidden items-center gap-2 sm:flex">
|
||||
<div
|
||||
class="hidden items-center gap-2 rounded-full border border-border/70 bg-muted/40 py-1 ps-1 pe-3 sm:flex"
|
||||
>
|
||||
<img
|
||||
class="h-5 w-5 rounded-full"
|
||||
class="h-6 w-6 rounded-full ring-1 ring-border"
|
||||
src="/images/country-flags/{(location.country_code || 'united_nations').toLowerCase()}.svg"
|
||||
alt={location.country}
|
||||
/>
|
||||
<span class="text-sm font-medium text-foreground">
|
||||
<span class="text-sm font-semibold text-foreground">
|
||||
{location.name}
|
||||
</span>
|
||||
{#if location.admin1 || location.country}
|
||||
<span class="text-xs text-muted-foreground">
|
||||
<span class="hidden text-xs text-muted-foreground lg:inline">
|
||||
{#if location.admin1}{location.admin1},{/if}
|
||||
{location.country}
|
||||
</span>
|
||||
@@ -75,7 +90,7 @@
|
||||
<!-- Spacer -->
|
||||
<div class="flex-1"></div>
|
||||
|
||||
<!-- Location search -->
|
||||
<!-- Location search: primary way to switch places, so keep it loud -->
|
||||
<div class="w-full max-w-sm md:max-w-md">
|
||||
<LocationSearch
|
||||
label="Search location..."
|
||||
@@ -84,6 +99,58 @@
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Theme toggle: system → light → dark -->
|
||||
<button
|
||||
class="flex h-9 w-9 shrink-0 cursor-pointer items-center justify-center rounded-full border border-border/70 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
|
||||
onclick={cycleTheme}
|
||||
title={themeTitles[$storedTheme]}
|
||||
aria-label={themeTitles[$storedTheme]}
|
||||
>
|
||||
{#if $storedTheme === 'light'}
|
||||
<!-- sun -->
|
||||
<svg
|
||||
class="h-4.5 w-4.5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.75"
|
||||
>
|
||||
<circle cx="12" cy="12" r="4" />
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
d="M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32 1.41 1.41M2 12h2m16 0h2M4.93 19.07l1.41-1.41m11.32-11.32 1.41-1.41"
|
||||
/>
|
||||
</svg>
|
||||
{:else if $storedTheme === 'dark'}
|
||||
<!-- moon -->
|
||||
<svg
|
||||
class="h-4.5 w-4.5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.75"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8Z"
|
||||
/>
|
||||
</svg>
|
||||
{:else}
|
||||
<!-- monitor (system) -->
|
||||
<svg
|
||||
class="h-4.5 w-4.5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.75"
|
||||
>
|
||||
<rect x="3" y="4" width="18" height="13" rx="2" />
|
||||
<path stroke-linecap="round" d="M8 21h8m-4-4v4" />
|
||||
</svg>
|
||||
{/if}
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -66,22 +66,27 @@
|
||||
<div
|
||||
class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-primary text-primary-foreground"
|
||||
>
|
||||
<!-- umbrella-with-rain logo mark (matches favicon) -->
|
||||
<svg
|
||||
class="h-4.5 w-4.5"
|
||||
class="h-5 w-5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="2"
|
||||
stroke-width="1.75"
|
||||
>
|
||||
<!-- rain falls from above onto the canopy -->
|
||||
<path stroke-linecap="round" d="M4.5 3v.01M19.5 3v.01M8.5 1.5v.01M15.5 2.5v.01" />
|
||||
<path stroke-linecap="round" d="M12 4.5V6" />
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z"
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
d="M4 14a8 8 0 0 1 16 0c-.66-1-1.99-1-2.66 0-.67-1-2-1-2.67 0-.67-1-2-1-2.67 0-.67-1-2-1-2.67 0C8.66 13 7.33 13 6.66 14 6 13 4.66 13 4 14Z"
|
||||
/>
|
||||
<path stroke-linecap="round" d="M12 14v5a1.9 1.9 0 0 1-3.8 0" />
|
||||
</svg>
|
||||
</div>
|
||||
{#if !collapsed}
|
||||
<span class="text-sm font-semibold whitespace-nowrap text-sidebar-foreground">
|
||||
<span class="text-sm font-bold tracking-tight whitespace-nowrap text-sidebar-foreground">
|
||||
OMbrella
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user