Make track cards, track links, and project filters keyboard-operable
This commit is contained in:
4 files changed
+24
-11
No files matched your search
@@ -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
|
||||||
>
|
>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user