Make track cards, track links, and project filters keyboard-operable

This commit is contained in:
encie22 committed 2026-10-15 15:30:24 +10:30
1 parent b75f17e604
commit f5d2b417e6
4 files changed
+24 -11

No files matched your search

+5 -2
View File
@@ -6,6 +6,7 @@ interface Props extends HTMLAttributes<"span"> {
textColour?: String;
size?: String;
hover?: String;
as?: "span" | "button";
}
const {
@@ -14,11 +15,13 @@ const {
size = "text-xs",
hover = "hover:bg-white hover:text-primary hover:ring-primary hover:ring-2",
class: className,
as: Tag = "span",
...attrs
} = Astro.props as Props;
---
<span
<Tag
type={Tag === "button" ? "button" : undefined}
class:list={[
"inline-block rounded px-2 py-1 font-bold uppercase",
colour,
@@ -27,5 +30,5 @@ const {
size,
hover
]}
{...attrs}><slot /></span
{...attrs}><slot /></Tag
>
+7 -5
View File
@@ -20,7 +20,9 @@ if (!track.data.card) {
}
---
<div
<button
type="button"
aria-label={`Play ${track.data.card.text.primary}`}
class:list={[
"relative flex min-h-42 flex-auto hover:cursor-pointer",
index < 2 ? "lg:w-1/2" : "sm:w-1/2 md:w-1/3 lg:w-1/4"
@@ -33,8 +35,8 @@ if (!track.data.card) {
class="h-full w-full object-cover"
/>
<div
class="bg-primary absolute inset-0 z-10 flex h-full w-full flex-col items-center justify-center p-16 text-center opacity-0 transition duration-300 hover:opacity-90"
<span
class="bg-primary absolute inset-0 z-10 flex h-full w-full flex-col items-center justify-center p-16 text-center opacity-0 transition duration-300 hover:opacity-90 focus-visible:opacity-90"
>
<span class="text-md md:text-l block font-bold text-gray-100"
>{track.data.card.text.secondary}</span
@@ -42,5 +44,5 @@ if (!track.data.card) {
<span class="block text-xl font-extrabold uppercase md:text-2xl"
>{track.data.card.text.primary}</span
>
</div>
</div>
</span>
</button>
+4 -2
View File
@@ -21,7 +21,9 @@ const fullFilePath = join(process.cwd(), "public", track.data.src);
const duration = await getAudioDurationInSeconds(fullFilePath);
---
<div
<button
type="button"
aria-label={`Play ${track.data.metadata.title}`}
class:list={[
"text-primary flex items-center transition hover:cursor-pointer hover:text-gray-300",
className
@@ -31,4 +33,4 @@ const duration = await getAudioDurationInSeconds(fullFilePath);
>
<Icon name="fa7-solid:play-circle" class="mr-2 inline-block" />
<span class="inline-block">{track.data.metadata.title}</span>
</div>
</button>
+8 -2
View File
@@ -23,12 +23,16 @@ const types = [...new Set(projects.map((project) => project.data.type))];
<SectionTitle Tag="h1">Recent Projects</SectionTitle>
<div id="filter-tokens" class="my-8 space-y-2 space-x-2">
<Token
as="button"
aria-pressed="true"
class="filter-token !text-primary ring-primary bg-white ring-2 hover:cursor-pointer"
data-type="all">All</Token
>
{
types.map((type) => (
<Token
as="button"
aria-pressed="false"
class="filter-token hover:cursor-pointer"
data-type={slugify(type)}
>
@@ -70,14 +74,15 @@ const types = [...new Set(projects.map((project) => project.data.type))];
const token = (e.target as Element).closest<HTMLElement>(".filter-token");
if (!token) return;
tokens.forEach((t) =>
tokens.forEach((t) => {
t.classList.remove(
"bg-white",
"!text-primary",
"ring-primary",
"ring-2"
)
);
t.setAttribute("aria-pressed", "false");
});
token.classList.add(
"bg-white",
@@ -85,6 +90,7 @@ const types = [...new Set(projects.map((project) => project.data.type))];
"ring-primary",
"ring-2"
);
token.setAttribute("aria-pressed", "true");
const type = token.dataset.type;