...
This commit is contained in:
@@ -10,12 +10,17 @@
|
||||
import BusPage from "./pages/BusPage.svelte";
|
||||
import ContactPage from "./pages/ContactPage.svelte";
|
||||
import AccessibilityPage from "./pages/AccessibilityPage.svelte";
|
||||
import { getTheme } from "./lib/theme.svelte";
|
||||
|
||||
route("/", HomePage);
|
||||
route("/taxi", TaxiPage);
|
||||
route("/bus", BusPage);
|
||||
route("/contact", ContactPage);
|
||||
route("/accessibility", AccessibilityPage);
|
||||
|
||||
$effect(() => {
|
||||
document.body.dataset.theme = getTheme();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex min-h-screen flex-col bg-primary-200 text-contrast-900">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import Link from "./lib/components/link/Link.svelte";
|
||||
import { Routes } from "./lib/global/routes";
|
||||
import { Routes } from "./lib/routes";
|
||||
</script>
|
||||
|
||||
<footer
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
import moonIcon from "./assets/icons/moon.svg";
|
||||
import { slide } from "svelte/transition";
|
||||
import Toggle from "./lib/components/Toggle.svelte";
|
||||
import { darkTheme } from "./lib/stores/theme";
|
||||
import { Routes } from "./lib/global/routes";
|
||||
import { Routes } from "./lib/routes";
|
||||
import { isCurrentPath } from "./lib/components/Router.svelte";
|
||||
import { getTheme, toggleTheme } from "./lib/theme.svelte";
|
||||
|
||||
let sidebarOpen = false;
|
||||
|
||||
@@ -63,15 +63,7 @@
|
||||
{/each}
|
||||
</ul>
|
||||
<div class="flex w-fit flex-col items-center gap-3">
|
||||
<Toggle
|
||||
invertColor={true}
|
||||
checked={$darkTheme}
|
||||
leftIcon={sunIcon}
|
||||
rightIcon={moonIcon}
|
||||
on:change={() => {
|
||||
$darkTheme = $darkTheme = !$darkTheme;
|
||||
}}
|
||||
/>
|
||||
<Toggle invertColor={true} checked={getTheme() == "dark"} leftIcon={sunIcon} rightIcon={moonIcon} on:change={toggleTheme} />
|
||||
</div>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
80
src/app.css
80
src/app.css
@@ -2,72 +2,36 @@
|
||||
|
||||
@custom-variant dark (&:where([data-theme='dark'], [data-theme='dark'] *));
|
||||
|
||||
:root {
|
||||
--mb-color-primary-100: rgb(250 250 250);
|
||||
--mb-color-primary-200: rgb(240 240 240);
|
||||
--mb-color-primary-300: rgb(230 230 230);
|
||||
--mb-color-primary-400: rgb(220 220 220);
|
||||
--mb-color-primary-500: rgb(210 210 210);
|
||||
--mb-color-primary-600: rgb(200 200 200);
|
||||
--mb-color-primary-700: rgb(190 190 190);
|
||||
--mb-color-primary-800: rgb(180 180 180);
|
||||
--mb-color-primary-900: rgb(170 170 170);
|
||||
|
||||
--mb-color-contrast-100: rgb(220 220 220);
|
||||
--mb-color-contrast-200: rgb(200 200 200);
|
||||
--mb-color-contrast-300: rgb(180 180 180);
|
||||
--mb-color-contrast-400: rgb(160 160 160);
|
||||
--mb-color-contrast-500: rgb(140 140 140);
|
||||
--mb-color-contrast-600: rgb(110 110 110);
|
||||
--mb-color-contrast-700: rgb(80 80 80);
|
||||
--mb-color-contrast-800: rgb(60 60 60);
|
||||
--mb-color-contrast-900: rgb(30 30 30);
|
||||
body {
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--mb-color-primary-100: rgb(28 28 28);
|
||||
--mb-color-primary-200: rgb(32 32 32);
|
||||
--mb-color-primary-300: rgb(38 38 38);
|
||||
--mb-color-primary-400: rgb(44 44 44);
|
||||
--mb-color-primary-500: rgb(50 50 50);
|
||||
--mb-color-primary-600: rgb(56 56 56);
|
||||
--mb-color-primary-700: rgb(62 62 62);
|
||||
--mb-color-primary-800: rgb(68 68 68);
|
||||
--mb-color-primary-900: rgb(74 74 74);
|
||||
|
||||
--mb-color-contrast-100: rgb(25 25 25);
|
||||
--mb-color-contrast-200: rgb(50 50 50);
|
||||
--mb-color-contrast-300: rgb(80 80 80);
|
||||
--mb-color-contrast-400: rgb(110 110 110);
|
||||
--mb-color-contrast-500: rgb(140 140 140);
|
||||
--mb-color-contrast-600: rgb(160 160 160);
|
||||
--mb-color-contrast-700: rgb(180 180 180);
|
||||
--mb-color-contrast-800: rgb(200 200 200);
|
||||
--mb-color-contrast-900: rgb(220 220 220);
|
||||
body[data-theme="dark"] {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-accent: rgb(255 29 37);
|
||||
|
||||
--color-primary-100: var(--mb-color-primary-100);
|
||||
--color-primary-200: var(--mb-color-primary-200);
|
||||
--color-primary-300: var(--mb-color-primary-300);
|
||||
--color-primary-400: var(--mb-color-primary-400);
|
||||
--color-primary-500: var(--mb-color-primary-500);
|
||||
--color-primary-600: var(--mb-color-primary-600);
|
||||
--color-primary-700: var(--mb-color-primary-700);
|
||||
--color-primary-800: var(--mb-color-primary-800);
|
||||
--color-primary-900: var(--mb-color-primary-900);
|
||||
--color-primary-100: light-dark(rgb(250 250 250), rgb(28 28 28));
|
||||
--color-primary-200: light-dark(rgb(240 240 240), rgb(32 32 32));
|
||||
--color-primary-300: light-dark(rgb(230 230 230), rgb(38 38 38));
|
||||
--color-primary-400: light-dark(rgb(220 220 220), rgb(44 44 44));
|
||||
--color-primary-500: light-dark(rgb(210 210 210), rgb(50 50 50));
|
||||
--color-primary-600: light-dark(rgb(200 200 200), rgb(56 56 56));
|
||||
--color-primary-700: light-dark(rgb(190 190 190), rgb(62 62 62));
|
||||
--color-primary-800: light-dark(rgb(180 180 180), rgb(68 68 68));
|
||||
--color-primary-900: light-dark(rgb(170 170 170), rgb(74 74 74));
|
||||
|
||||
--color-contrast-100: var(--mb-color-contrast-100);
|
||||
--color-contrast-200: var(--mb-color-contrast-200);
|
||||
--color-contrast-300: var(--mb-color-contrast-300);
|
||||
--color-contrast-400: var(--mb-color-contrast-400);
|
||||
--color-contrast-500: var(--mb-color-contrast-500);
|
||||
--color-contrast-600: var(--mb-color-contrast-600);
|
||||
--color-contrast-700: var(--mb-color-contrast-700);
|
||||
--color-contrast-800: var(--mb-color-contrast-800);
|
||||
--color-contrast-900: var(--mb-color-contrast-900);
|
||||
--color-contrast-100: light-dark(rgb(220 220 220), rgb(25 25 25));
|
||||
--color-contrast-200: light-dark(rgb(200 200 200), rgb(50 50 50));
|
||||
--color-contrast-300: light-dark(rgb(180 180 180), rgb(80 80 80));
|
||||
--color-contrast-400: light-dark(rgb(160 160 160), rgb(110 110 110));
|
||||
--color-contrast-500: light-dark(rgb(140 140 140), rgb(140 140 140));
|
||||
--color-contrast-600: light-dark(rgb(110 110 110), rgb(160 160 160));
|
||||
--color-contrast-700: light-dark(rgb(80 80 80), rgb(180 180 180));
|
||||
--color-contrast-800: light-dark(rgb(60 60 60), rgb(200 200 200));
|
||||
--color-contrast-900: light-dark(rgb(30 30 30), rgb(220 220 220));
|
||||
|
||||
--shadow-t-lg: 0px -4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
export class RouteError extends Error {}
|
||||
export class MissingRouteError extends RouteError {}
|
||||
export class RouteFormatError extends RouteError {}
|
||||
export class DuplicateRouteError extends RouteError {}
|
||||
|
||||
type RouteInfo = {
|
||||
path: string;
|
||||
@@ -67,7 +66,8 @@
|
||||
*/
|
||||
export function route(path: string, component: Component<{}>): void {
|
||||
if (routes.has(path)) {
|
||||
throw new DuplicateRouteError(`Route already registered for path: '${path}'.`);
|
||||
console.warn(`Route already registered for path: '${path}'.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const params = Array.from(path.matchAll(/\[([^\]]+)\]/g)).map((x) => x[1]);
|
||||
@@ -179,53 +179,6 @@
|
||||
// @ts-ignore
|
||||
window.navigation.removeEventListener("navigate", handleNavigate);
|
||||
};
|
||||
} else {
|
||||
function refresh() {
|
||||
currentUrl = new URL(window.location.href);
|
||||
}
|
||||
|
||||
function makeProxy(target: any) {
|
||||
return new Proxy(target, {
|
||||
apply: (target, thisArg, argArray) => {
|
||||
const result = target.apply(thisArg, argArray);
|
||||
refresh();
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.history.pushState = makeProxy(window.history.pushState);
|
||||
window.history.replaceState = makeProxy(window.history.replaceState);
|
||||
window.history.go = makeProxy(window.history.go);
|
||||
window.history.forward = makeProxy(window.history.forward);
|
||||
window.history.back = makeProxy(window.history.back);
|
||||
|
||||
function handleClick(e: MouseEvent) {
|
||||
if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
const anchor = (e.target as Element)?.closest("a");
|
||||
if (!(anchor instanceof HTMLAnchorElement)) return;
|
||||
if (anchor.target === "_blank") return;
|
||||
|
||||
const targetUrl = new URL(anchor.href, document.baseURI);
|
||||
const documentUrl = new URL(document.baseURI);
|
||||
|
||||
if (targetUrl.origin === documentUrl.origin) {
|
||||
e.preventDefault();
|
||||
history.pushState({}, "", targetUrl);
|
||||
currentUrl = targetUrl;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("popstate", refresh);
|
||||
document.addEventListener("click", handleClick);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("popstate", refresh);
|
||||
document.removeEventListener("click", handleClick);
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import homeIcon from "../../assets/icons/home_icon.svg";
|
||||
import contactIcon from "../../assets/icons/contact_icon.svg";
|
||||
import busIcon from "../../assets/icons/bus_icon.svg";
|
||||
import homeIcon from "../assets/icons/home_icon.svg";
|
||||
import contactIcon from "../assets/icons/contact_icon.svg";
|
||||
import busIcon from "../assets/icons/bus_icon.svg";
|
||||
|
||||
type Route = {
|
||||
url: string;
|
||||
@@ -1,36 +0,0 @@
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
function createThemeToggler() {
|
||||
let defaultValue = false;
|
||||
let savedValue = localStorage.getItem("dark_theme");
|
||||
|
||||
if (savedValue) {
|
||||
defaultValue = JSON.parse(savedValue);
|
||||
} else if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
defaultValue = true;
|
||||
}
|
||||
|
||||
if (defaultValue) {
|
||||
document.body.dataset.theme = "dark";
|
||||
} else {
|
||||
document.body.dataset.theme = "light";
|
||||
}
|
||||
|
||||
const { subscribe, update } = writable(defaultValue);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set: (value: boolean) => {
|
||||
update(() => value);
|
||||
if (value) {
|
||||
document.body.dataset.theme = "dark";
|
||||
} else {
|
||||
document.body.dataset.theme = "light";
|
||||
}
|
||||
|
||||
localStorage.setItem("dark_theme", JSON.stringify(value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const darkTheme = createThemeToggler();
|
||||
24
src/lib/theme.svelte.ts
Normal file
24
src/lib/theme.svelte.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
function loadTheme() {
|
||||
let theme = localStorage.getItem("theme");
|
||||
if (!theme) {
|
||||
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
theme = "dark";
|
||||
} else {
|
||||
theme = "light";
|
||||
}
|
||||
}
|
||||
|
||||
return theme;
|
||||
}
|
||||
|
||||
let currentTheme = $state(loadTheme());
|
||||
|
||||
export function toggleTheme() {
|
||||
const newTheme = currentTheme === "dark" ? "light" : "dark";
|
||||
localStorage.setItem("theme", newTheme);
|
||||
currentTheme = newTheme;
|
||||
}
|
||||
|
||||
export function getTheme(): string {
|
||||
return currentTheme;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export function debounce<T extends Function>(cb: T, wait = 500) {
|
||||
let h: any;
|
||||
let callable = () => {
|
||||
clearTimeout(h);
|
||||
h = setTimeout(() => cb(), wait);
|
||||
};
|
||||
return callable;
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
import twoTourBusses from "../assets/images/two_tour_busses.jpg";
|
||||
import van from "../assets/images/van.webp";
|
||||
import Link from "../lib/components/link/Link.svelte";
|
||||
import { Routes } from "../lib/global/routes";
|
||||
import { Routes } from "../lib/routes";
|
||||
|
||||
type CardCarouselItem = {
|
||||
header: string;
|
||||
|
||||
Reference in New Issue
Block a user