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
+25 -12

No files matched your search

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