mirror of
https://github.com/thiloho/thiloho.github.io.git
synced 2025-11-22 10:21:36 +01:00
Initialize project with general functionality
This commit is contained in:
17
src/components/Date.astro
Normal file
17
src/components/Date.astro
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
interface Props {
|
||||
date: Date;
|
||||
}
|
||||
|
||||
const { date } = Astro.props;
|
||||
---
|
||||
|
||||
<time datetime={date.toISOString()}>
|
||||
{
|
||||
date.toLocaleString("en-us", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
})
|
||||
}
|
||||
</time>
|
||||
9
src/components/Footer.astro
Normal file
9
src/components/Footer.astro
Normal file
@@ -0,0 +1,9 @@
|
||||
<footer
|
||||
class="flex flex-col items-center p-4 bg-neutral-100 dark:bg-neutral-900 prose prose-neutral dark:prose-invert max-w-none prose-a:text-blue-800 prose-a:dark:text-blue-300 prose-a:hover:no-underline"
|
||||
>
|
||||
<p class="mb-2">© 2025 Thilo Hohlt</p>
|
||||
<div class="flex gap-4">
|
||||
<a href="/legal-disclosure">Legal Disclosure</a>
|
||||
<a href="https://github.com/thiloho">GitHub</a>
|
||||
</div>
|
||||
</footer>
|
||||
49
src/components/Head.astro
Normal file
49
src/components/Head.astro
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
import { ClientRouter } from "astro:transitions";
|
||||
import "../styles/global.css";
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
metaDescription: string;
|
||||
}
|
||||
|
||||
const { title, metaDescription } = Astro.props;
|
||||
---
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<meta name="apple-mobile-web-app-title" content="THohlt" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={metaDescription} />
|
||||
<ClientRouter />
|
||||
<script is:inline>
|
||||
const setTheme = () => {
|
||||
let theme = "light";
|
||||
|
||||
if (localStorage.getItem("theme")) {
|
||||
theme = localStorage.getItem("theme");
|
||||
} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
theme = "dark";
|
||||
}
|
||||
|
||||
if (theme === "light") {
|
||||
document.documentElement.classList.remove("dark");
|
||||
} else {
|
||||
document.documentElement.classList.add("dark");
|
||||
}
|
||||
|
||||
window.localStorage.setItem("theme", theme);
|
||||
};
|
||||
|
||||
setTheme();
|
||||
|
||||
document.addEventListener("astro:after-swap", setTheme);
|
||||
</script>
|
||||
</head>
|
||||
33
src/components/Header.astro
Normal file
33
src/components/Header.astro
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
import Date from "./Date.astro";
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
pubDate?: Date;
|
||||
modDate?: Date;
|
||||
}
|
||||
|
||||
const { title, pubDate, modDate } = Astro.props;
|
||||
---
|
||||
|
||||
<header class="bg-white dark:bg-neutral-800">
|
||||
<div
|
||||
class="prose prose-neutral dark:prose-invert mx-auto px-4 py-8 border-b border-neutral-200 dark:border-neutral-700 prose-h1:font-bold"
|
||||
>
|
||||
{
|
||||
pubDate ? (
|
||||
<hgroup>
|
||||
<h1 class="mb-2">{title}</h1>
|
||||
<p>
|
||||
Published: <Date date={pubDate} />
|
||||
<br />
|
||||
Last modified:{" "}
|
||||
{modDate ? <Date date={modDate} /> : <span>No changes yet</span>}
|
||||
</p>
|
||||
</hgroup>
|
||||
) : (
|
||||
<h1>{title}</h1>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</header>
|
||||
77
src/components/Nav.astro
Normal file
77
src/components/Nav.astro
Normal file
@@ -0,0 +1,77 @@
|
||||
---
|
||||
import Logo from "../img/TH.svg";
|
||||
|
||||
const routes = ["blog"];
|
||||
---
|
||||
|
||||
<nav class="max-w-none bg-neutral-100 dark:bg-neutral-900 sticky top-0 z-10">
|
||||
<div
|
||||
class="dark:text-neutral-300 flex items-center justify-between max-w-screen-lg mx-auto ps-4 pe-2"
|
||||
>
|
||||
<a href="/" title="Home">
|
||||
<Logo width={42} height={42} />
|
||||
</a>
|
||||
<div class="flex">
|
||||
{
|
||||
routes.map((route) => (
|
||||
<a
|
||||
class="inline-block p-2 border-b-2 border-transparent hover:bg-neutral-200 hover:border-neutral-400 hover:dark:bg-neutral-700 hover:dark:border-neutral-600"
|
||||
href={`/${route}`}
|
||||
>
|
||||
{route
|
||||
.split(" ")
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(" ")}
|
||||
</a>
|
||||
))
|
||||
}
|
||||
<button
|
||||
class="theme-toggle p-2 cursor-pointer border-b-2 border-transparent hover:bg-neutral-200 hover:border-neutral-400 hover:dark:bg-neutral-700 hover:dark:border-neutral-600"
|
||||
title="Toggle dark mode"
|
||||
>
|
||||
<!-- Moon -->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="size-5 dark:hidden"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M7.455 2.004a.75.75 0 0 1 .26.77 7 7 0 0 0 9.958 7.967.75.75 0 0 1 1.067.853A8.5 8.5 0 1 1 6.647 1.921a.75.75 0 0 1 .808.083Z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
|
||||
<!-- Sun -->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="size-5 hidden dark:block"
|
||||
>
|
||||
<path
|
||||
d="M10 2a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 10 2ZM10 15a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 10 15ZM10 7a3 3 0 1 0 0 6 3 3 0 0 0 0-6ZM15.657 5.404a.75.75 0 1 0-1.06-1.06l-1.061 1.06a.75.75 0 0 0 1.06 1.06l1.06-1.06ZM6.464 14.596a.75.75 0 1 0-1.06-1.06l-1.06 1.06a.75.75 0 0 0 1.06 1.06l1.06-1.06ZM18 10a.75.75 0 0 1-.75.75h-1.5a.75.75 0 0 1 0-1.5h1.5A.75.75 0 0 1 18 10ZM5 10a.75.75 0 0 1-.75.75h-1.5a.75.75 0 0 1 0-1.5h1.5A.75.75 0 0 1 5 10ZM14.596 15.657a.75.75 0 0 0 1.06-1.06l-1.06-1.061a.75.75 0 1 0-1.06 1.06l1.06 1.06ZM5.404 6.464a.75.75 0 0 0 1.06-1.06l-1.06-1.06a.75.75 0 1 0-1.061 1.06l1.06 1.06Z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<script>
|
||||
const setToggleListener = () => {
|
||||
const toggleBtn = document.querySelector(".theme-toggle");
|
||||
|
||||
toggleBtn?.addEventListener("click", () => {
|
||||
const element = document.documentElement;
|
||||
element.classList.toggle("dark");
|
||||
|
||||
const isDark = element.classList.contains("dark");
|
||||
localStorage.setItem("theme", isDark ? "dark" : "light");
|
||||
});
|
||||
};
|
||||
|
||||
setToggleListener();
|
||||
|
||||
document.addEventListener("astro:after-swap", setToggleListener);
|
||||
</script>
|
||||
Reference in New Issue
Block a user