this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update blog post page

- Add <Nav />
- Add light/dark toggle
- Apply formatting

+135 -22
+14
src/assets/moon.svg
··· 1 + <svg 2 + xmlns="http://www.w3.org/2000/svg" 3 + width="24" 4 + height="24" 5 + viewBox="0 0 24 24" 6 + fill="none" 7 + stroke="currentColor" 8 + stroke-width="2" 9 + stroke-linecap="round" 10 + stroke-linejoin="round" 11 + class="lucide lucide-moon-icon lucide-moon" 12 + > 13 + <path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" /> 14 + </svg>
+22
src/assets/sun.svg
··· 1 + <svg 2 + xmlns="http://www.w3.org/2000/svg" 3 + width="24" 4 + height="24" 5 + viewBox="0 0 24 24" 6 + fill="none" 7 + stroke="currentColor" 8 + stroke-width="2" 9 + stroke-linecap="round" 10 + stroke-linejoin="round" 11 + class="lucide lucide-sun-icon lucide-sun" 12 + > 13 + <circle cx="12" cy="12" r="4" /> 14 + <path d="M12 2v2" /> 15 + <path d="M12 20v2" /> 16 + <path d="m4.93 4.93 1.41 1.41" /> 17 + <path d="m17.66 17.66 1.41 1.41" /> 18 + <path d="M2 12h2" /> 19 + <path d="M20 12h2" /> 20 + <path d="m6.34 17.66-1.41 1.41" /> 21 + <path d="m19.07 4.93-1.41 1.41" /> 22 + </svg>
+99 -22
src/pages/blog/[id].astro
··· 1 1 --- 2 2 import Base from "@/Base.astro"; 3 + import Nav from "@/components/generic/Nav.astro"; 4 + 5 + import Sun from "@/assets/sun.svg"; 6 + import Moon from "@/assets/moon.svg"; 7 + 3 8 import { render } from "astro:content"; 4 9 import { getEntry } from "astro:content"; 10 + import { parse } from "node:path"; 11 + 5 12 const { id } = Astro.params; 6 - const r404 = Astro.redirect("/404"); 13 + if (!id) return Astro.redirect("/404"); 7 14 8 - if (!id) return r404; 9 15 const post = await getEntry("blog", id); 10 - if (!post) return r404; 16 + if (!post) return Astro.redirect("/404"); 11 17 12 18 const { 13 19 data: { title, hasMdx }, ··· 18 24 19 25 if (!post.filePath) throw new Error("Post does not have a filepath"); 20 26 return import(`../../content/posts/${parse(post.filePath).name}.mdx`).then( 21 - (x) => x.Content 27 + (x) => x.Content, 22 28 ); 23 29 })(); 24 30 --- 25 31 26 - <Base title={title}> 27 - <main data-nojs> 32 + <Base {title}> 33 + <heading> 34 + <Nav current={title} /> 35 + 36 + <h1>{title}</h1> 37 + 38 + <button id="colour-toggle" style="display: none"> 39 + <Sun data-mode-light /> 40 + <Moon data-mode-dark /> 41 + </button> 42 + </heading> 43 + <main data-colour-scheme-nojs> 28 44 <div class="content"> 29 - <h1>{title}</h1> 30 45 <Content /> 31 46 </div> 32 47 </main> 33 48 </Base> 34 49 35 50 <script> 36 - document.querySelectorAll("main[data-nojs]").forEach((el) => { 37 - if (!(el instanceof HTMLElement)) throw new Error("Not HTML Element!"); 38 - delete el.dataset["nojs"]; 39 - const colourScheme = matchMedia("(prefers-color-scheme: light)"); 51 + const els = document.querySelectorAll("main[data-colour-scheme-nojs]"); 52 + if (els.length !== 1) 53 + throw new Error( 54 + "No `main[data-colour-scheme-nojs]`` found, or multiple found", 55 + ); 56 + const el = els[0]; 57 + if (!(el instanceof HTMLElement)) throw new Error("Not HTML Element!"); 58 + 59 + const button = document.getElementById("colour-toggle"); 60 + if (!button) throw new Error("No #colour-toggle element"); 61 + 62 + const modeToggled = { 63 + light: document.querySelectorAll("[data-mode-light]"), 64 + dark: document.querySelectorAll("[data-mode-dark]"), 65 + }; 66 + 67 + delete el.dataset["colourSchemeNojs"]; 68 + 69 + let lightMode = matchMedia("(prefers-color-scheme: light)").matches; 70 + const updateColourScheme = () => { 71 + modeToggled[lightMode ? "light" : "dark"].forEach((el) => { 72 + if (!(el instanceof SVGElement || el instanceof HTMLElement)) return; 73 + el.style.display = "block"; 74 + }); 75 + modeToggled[!lightMode ? "light" : "dark"].forEach((el) => { 76 + if (!(el instanceof SVGElement || el instanceof HTMLElement)) return; 77 + el.style.display = "none"; 78 + }); 79 + el.dataset["mode"] = lightMode ? "light" : "dark"; 80 + }; 81 + updateColourScheme(); 40 82 41 - const updateColourScheme = () => { 42 - el.dataset["mode"] = colourScheme.matches ? "light" : "dark"; 43 - }; 83 + button.style.display = "block"; 84 + button.addEventListener("click", () => { 85 + lightMode = !lightMode; 44 86 updateColourScheme(); 45 - 46 - colourScheme.addEventListener("change", () => updateColourScheme()); 47 87 }); 48 88 </script> 49 89 ··· 54 94 } 55 95 56 96 /* set colours based on system colour scheme */ 57 - :root:has([data-nojs]) { 97 + :root:has([data-colour-scheme-nojs]) { 58 98 --bg: light-dark(white, black); 59 99 --text: light-dark(black, white); 60 100 } ··· 73 113 } 74 114 } 75 115 76 - main { 116 + heading { 117 + font-size: 1.6rem; 118 + 119 + position: fixed; 120 + top: 0; 121 + width: 100%; 122 + z-index: 999; 123 + display: flex; 124 + align-items: center; 125 + justify-content: space-between; 126 + 77 127 background-color: var(--bg); 78 - color: var(--text); 128 + padding-bottom: 0.5rem; 79 129 80 - min-height: 100lvh; 130 + & > :last-child { 131 + margin-right: 1rem; 132 + margin-top: 0.5rem; 133 + } 134 + } 135 + 136 + #colour-toggle { 137 + background-color: var(--text); 138 + border: none; 139 + border-radius: 50%; 140 + padding: 0.5rem; 141 + 142 + & svg { 143 + fill: var(--bg); 144 + stroke: var(--bg); 145 + } 146 + } 147 + 148 + body { 149 + background-color: var(--bg); 150 + color: var(--text); 81 151 } 82 152 83 153 .content, 84 154 .full-width { 155 + padding-top: 4em; 156 + 85 157 --padding-inline: 2rem; 86 158 --content-max-width: 60ch; 87 159 --breakout-max-width: 80ch; 88 160 89 - --content-size: min(100% - var(--padding-inline) * 2, var(--content-max-width)); 90 - --breakout-size: calc((var(--breakout-max-width) - var(--content-max-width)) / 2); 161 + --content-size: min( 162 + 100% - var(--padding-inline) * 2, 163 + var(--content-max-width) 164 + ); 165 + --breakout-size: calc( 166 + (var(--breakout-max-width) - var(--content-max-width)) / 2 167 + ); 91 168 92 169 display: grid; 93 170 grid-template-columns: