make everything noscript compatible as best as possible

This commit is contained in:
Moritz Hölting 2026-03-21 18:56:09 +01:00
parent bbdc4ea50e
commit 1a0eaf2dcb
9 changed files with 106 additions and 108 deletions

View File

@ -1,12 +0,0 @@
function animate() {
const animateElements = document.querySelectorAll('.animate')
animateElements.forEach((element, index) => {
setTimeout(() => {
element.classList.add('show')
}, index * 150)
});
}
document.addEventListener("DOMContentLoaded", animate)
document.addEventListener("astro:after-swap", animate)

View File

@ -1,7 +1,6 @@
import type { CollectionEntry } from "astro:content";
import { formatDate } from "@/lib/utils";
import { Icon } from '@iconify-icon/solid';
import { Icon } from "@iconify-icon/solid";
type Props = {
entry: CollectionEntry<"blog"> | CollectionEntry<"projects">;
@ -31,13 +30,11 @@ export default function ArrowCard({ entry, pill }: Props) {
<div class="text-sm line-clamp-2">{entry.data.summary}</div>
<ul class="flex flex-wrap mt-2 gap-1">
{entry.data.tags.map(
(tag) => (
<li class="text-xs font-departure uppercase py-0.5 px-1 rounded bg-black/5 dark:bg-white/20 text-black/75 dark:text-white/75">
{tag}
</li>
)
)}
{entry.data.tags.map((tag) => (
<li class="text-xs font-departure uppercase py-0.5 px-1 rounded bg-black/5 dark:bg-white/20 text-black/75 dark:text-white/75">
{tag}
</li>
))}
</ul>
</div>
<div class="relative overflow-hidden w-4 h-4">

View File

@ -82,7 +82,6 @@ const { title, description, image = "/open-graph.jpg" } = Astro.props;
<!-- Global Scripts -->
<script is:inline src="/js/theme.js"></script>
<script is:inline src="/js/scroll.js"></script>
<script is:inline src="/js/animate.js"></script>
<ClientRouter />
@ -107,11 +106,3 @@ const { title, description, image = "/open-graph.jpg" } = Astro.props;
integrity="sha384-m7LqaUc4JRc2uA7D4zSVUs/sgkYhmOOe9+Gd8DFmmAXH8vzs15fmw05YXvpxsoQB"
crossorigin="anonymous"
/>
<noscript>
<style>
.noscript-hide {
display: none;
}
</style>
</noscript>

View File

@ -10,20 +10,23 @@ type Props = {
};
export default function Blog({ data, tags }: Props) {
function filterPosts(): CollectionEntry<"blog">[] {
return data.filter((entry) =>
Array.from(filter()).every((value) =>
entry.data.tags.some(
(tag: string) =>
tag.toLowerCase() === String(value).toLowerCase(),
),
),
);
}
const [filter, setFilter] = createSignal(new Set<string>());
const [posts, setPosts] = createSignal<CollectionEntry<"blog">[]>([]);
const [posts, setPosts] =
createSignal<CollectionEntry<"blog">[]>(filterPosts());
createEffect(() => {
setPosts(
data.filter((entry) =>
Array.from(filter()).every((value) =>
entry.data.tags.some(
(tag: string) =>
tag.toLowerCase() === String(value).toLowerCase()
)
)
)
);
setPosts(filterPosts());
});
function toggleTag(tag: string) {
@ -32,14 +35,14 @@ export default function Blog({ data, tags }: Props) {
new Set(
prev.has(tag)
? [...prev].filter((t) => t !== tag)
: [...prev, tag]
)
: [...prev, tag],
),
);
}
return (
<div class="grid grid-cols-1 sm:grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-1">
<div class="not-noscript:grid grid-cols-1 sm:grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-1 noscript:hidden">
<div class="sticky top-24">
<div class="text-sm font-semibold font-departure uppercase mb-2 text-black dark:text-white">
Filter
@ -58,21 +61,27 @@ export default function Blog({ data, tags }: Props) {
"hover:bg-black/10 hover:dark:bg-white/15",
"transition-colors duration-300 ease-in-out",
filter().has(tag) &&
"text-black dark:text-white"
"text-black dark:text-white",
)}
>
<div class={cn(
"relative size-5 fill-black/50 dark:fill-white/50",
"transition-colors duration-300 ease-in-out",
filter().has(tag) &&
"fill-black dark:fill-white"
)}>
<div
class={cn(
"relative size-5 fill-black/50 dark:fill-white/50",
"transition-colors duration-300 ease-in-out",
filter().has(tag) &&
"fill-black dark:fill-white",
)}
>
<Icon icon="pixelarticons:square" />
<Icon icon="pixel:check" class={cn("absolute top-0 right-0",
filter().has(tag)
? "block"
: "hidden"
)} />
<Icon
icon="pixel:check"
class={cn(
"absolute top-0 right-0",
filter().has(tag)
? "block"
: "hidden",
)}
/>
</div>
{tag}
</button>

View File

@ -11,7 +11,10 @@ const { pathname } = Astro.url;
const subpath = pathname.match(/[^/]+/g);
---
<header id="header" class="fixed top-0 w-full h-16 z-50">
<header
id="header"
class="fixed top-0 w-full h-16 z-50 noscript:bg-zinc-200/75 noscript:border-black/10 noscript:backdrop-blur-sm noscript:saturate-200"
>
<Container size="md">
<div
class="relative h-full w-full flex flex-row justify-between items-center"

View File

@ -10,22 +10,23 @@ type Props = {
};
export default function Projects({ data, tags }: Props) {
function filterProjects(): CollectionEntry<"projects">[] {
return data.filter((entry) =>
Array.from(filter()).every((value) =>
entry.data.tags.some(
(tag: string) =>
tag.toLowerCase() === String(value).toLowerCase(),
),
),
);
}
const [filter, setFilter] = createSignal(new Set<string>());
const [projects, setProjects] = createSignal<CollectionEntry<"projects">[]>(
[]
);
const [projects, setProjects] =
createSignal<CollectionEntry<"projects">[]>(filterProjects());
createEffect(() => {
setProjects(
data.filter((entry) =>
Array.from(filter()).every((value) =>
entry.data.tags.some(
(tag: string) =>
tag.toLowerCase() === String(value).toLowerCase()
)
)
)
);
setProjects(filterProjects());
});
function toggleTag(tag: string) {
@ -34,14 +35,14 @@ export default function Projects({ data, tags }: Props) {
new Set(
prev.has(tag)
? [...prev].filter((t) => t !== tag)
: [...prev, tag]
)
: [...prev, tag],
),
);
}
return (
<div class="grid grid-cols-1 sm:grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-1">
<div class="not-noscript:grid grid-cols-1 sm:grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-1 noscript:hidden">
<div class="sticky top-24">
<div class="text-sm font-semibold font-departure uppercase mb-2 text-black dark:text-white">
Filter
@ -60,21 +61,27 @@ export default function Projects({ data, tags }: Props) {
"hover:bg-black/10 hover:dark:bg-white/15",
"transition-colors duration-300 ease-in-out",
filter().has(tag) &&
"text-black dark:text-white"
"text-black dark:text-white",
)}
>
<div class={cn(
"relative size-5 fill-black/50 dark:fill-white/50",
"transition-colors duration-300 ease-in-out",
filter().has(tag) &&
"fill-black dark:fill-white"
)}>
<div
class={cn(
"relative size-5 fill-black/50 dark:fill-white/50",
"transition-colors duration-300 ease-in-out",
filter().has(tag) &&
"fill-black dark:fill-white",
)}
>
<Icon icon="pixelarticons:square" />
<Icon icon="pixel:check" class={cn("absolute top-0 right-0",
filter().has(tag)
? "block"
: "hidden"
)} />
<Icon
icon="pixel:check"
class={cn(
"absolute top-0 right-0",
filter().has(tag)
? "block"
: "hidden",
)}
/>
</div>
{tag}
</button>

View File

@ -11,19 +11,10 @@ const { suffix } = Astro.props;
name="doomsday-year"
id="doomsday-year"
min="1583"
class="w-16 font-departure"
/><span class="noscript-hide">{suffix}</span>
<noscript>
<span class="text-red-500"
>JavaScript is required for this feature to work.</span
>
<style>
#doomsday-year {
display: none;
}
</style>
</noscript>
class="w-16 font-departure noscript:hidden"
/><span class="text-red-500 not-noscript:hidden"
>JavaScript is required for this feature to work</span
>{suffix}
<script>
const currentYearInput = document.getElementById(

View File

@ -98,6 +98,7 @@ First, we take the last two digits of the year. If this number is odd, we add 11
Finally, we take 7 minus modulo 7 of the result and count forward that many days from the Doomsday of the century. The resulting weekday is the Doomsday of the year.
This algorithm can be remembered with the following flowchart:
<div class="noscript:hidden">
```mermaid
flowchart TD
B[Let T = last two digits of year] --> C{Is T odd?}
@ -116,6 +117,10 @@ flowchart TD
K --> L[Doomsday of the year]
```
</div>
<div class="not-noscript:hidden font-semibold italic">
Please enable JavaScript to see the flowchart for the first method.
</div>
The second method is more mathematical and follows the steps:

View File

@ -84,12 +84,19 @@
.animate {
opacity: 0;
transform: translateY(5px);
transition: opacity 1s ease, transform 1s ease;
animation: fadeInUp 1s forwards;
animation-delay: 0.5s;
}
.animate.show {
opacity: 1;
transform: translateY(0);
@keyframes fadeInUp {
0% {
opacity: 0;
transform: translateY(5px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
article img {