Tidy up metadata, headings, forms, and small accessibility fixes
Build and Deploy to Web Server / deploy (push) Successful in 4m34s

This commit is contained in:
encie22 committed 2026-10-15 10:55:24 +10:30
1 parent ff54fe8848
commit 1cf8ddc940
18 files changed
+107 -59

No files matched your search

+38 -16
View File
@@ -1,7 +1,11 @@
---
import { Icon } from "astro-icon/components";
const ID = `contact-form-${Math.random().toString(36)}`;
interface Props {
id?: string;
}
const { id: ID = "contact-form" } = Astro.props;
---
<form
@@ -9,60 +13,78 @@ const ID = `contact-form-${Math.random().toString(36)}`;
id={ID}
>
<div>
<label for="name" class="block font-bold">Name</label>
<label for={`${ID}-name`} class="block font-bold">Name</label>
<input
type="text"
id="name"
id={`${ID}-name`}
name="name"
required
autocomplete="name"
maxlength="100"
class="mt-2 block w-full rounded p-2 shadow dark:bg-gray-600"
/>
</div>
<div>
<label for="email" class="block font-bold">Your email</label>
<label for={`${ID}-email`} class="block font-bold">Your email</label>
<input
type="email"
id="email"
id={`${ID}-email`}
name="email"
required
autocomplete="email"
maxlength="254"
class="mt-2 block w-full rounded p-2 shadow dark:bg-gray-600"
/>
</div>
<div>
<label for="subject" class="block font-bold">Subject</label>
<label for={`${ID}-subject`} class="block font-bold">Subject</label>
<input
type="text"
id="subject"
id={`${ID}-subject`}
name="subject"
required
maxlength="150"
class="mt-2 block w-full rounded p-2 shadow dark:bg-gray-600"
/>
</div>
<div>
<label for="message" class="block font-bold">Message</label>
<label for={`${ID}-message`} class="block font-bold">Message</label>
<textarea
id="message"
id={`${ID}-message`}
name="message"
rows="4"
required
maxlength="5000"
class="mt-2 block w-full rounded p-2 shadow dark:bg-gray-600"></textarea>
</div>
<button
id="submit"
id={`${ID}-submit`}
type="submit"
class="bg-primary text-md font-header hover:text-primary repeat hover:ring-primary mx-auto inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow transition hover:bg-white hover:ring-2"
class="bg-primary text-md font-header hover:text-primary hover:ring-primary mx-auto inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow transition hover:bg-white hover:ring-2"
><Icon
name="mdi:loading"
id="loading-icon"
id={`${ID}-loading-icon`}
class="mr-4 hidden animate-spin"
/><span id="response-message" class="inline">Send message</span></button
/><span
id={`${ID}-response-message`}
class="inline"
role="status"
aria-live="polite">Send message</span
></button
>
</form>
<script define:vars={{ ID }}>
function init() {
const form = document.getElementById(ID);
const responseMsg = form.querySelector("#response-message");
const button = form.querySelector("#submit");
const loadingIcon = form.querySelector("#loading-icon");
if (!form) return;
const responseMsg = form.querySelector(
`#${CSS.escape(ID + "-response-message")}`
);
const button = form.querySelector(`#${CSS.escape(ID + "-submit")}`);
const loadingIcon = form.querySelector(
`#${CSS.escape(ID + "-loading-icon")}`
);
form.addEventListener("submit", async function (event) {
event.preventDefault();
+5 -2
View File
@@ -16,16 +16,19 @@ const imagesArray = await Promise.all(
<div class="absolute -z-50 h-full w-full bg-black"></div>
<img
src={imagesArray[0].default.src}
alt=""
class:list={[
"object-no-repeat absolute -z-50 h-full w-full object-cover object-center transition duration-2000",
"absolute -z-50 h-full w-full object-cover object-center transition duration-2000",
transitionStyle
]}
id="hero-image-1"
/>
<img
src={imagesArray[1].default.src}
alt=""
aria-hidden="true"
class:list={[
"object-no-repeat absolute -z-50 h-full w-full object-cover object-center transition duration-2000",
"absolute -z-50 h-full w-full object-cover object-center transition duration-2000",
transitionStyle
]}
id="hero-image-2"
+19 -5
View File
@@ -62,7 +62,13 @@ const { navbarDisplay = "normal" } = Astro.props as Props;
<!-- Mobile Menu Button -->
<div class="md:hidden">
<button id="menu-toggle" class="text-2xl focus:outline-none">
<button
id="menu-toggle"
class="text-2xl focus:outline-none"
aria-label="Toggle navigation menu"
aria-expanded="false"
aria-controls="mobile-menu"
>
☰
</button>
</div>
@@ -100,10 +106,7 @@ const { navbarDisplay = "normal" } = Astro.props as Props;
<!-- Extra spacing for non-transparent navbar -->
<div
class:list={[
"y-0 r-0 h-12",
navbarDisplay === "transparent" ? "hidden" : "block"
]}
class:list={["h-12", navbarDisplay === "transparent" ? "hidden" : "block"]}
>
</div>
@@ -141,12 +144,23 @@ const { navbarDisplay = "normal" } = Astro.props as Props;
if (nav) {
const visible = nav.getAttribute("data-mobile-menu") === "visible";
nav.setAttribute("data-mobile-menu", visible ? "hidden" : "visible");
toggle.setAttribute("aria-expanded", visible ? "false" : "true");
}
checkScroll();
});
}
document.addEventListener("keydown", (e) => {
if (
e.key === "Escape" &&
nav?.getAttribute("data-mobile-menu") === "visible"
) {
nav.setAttribute("data-mobile-menu", "hidden");
toggle?.setAttribute("aria-expanded", "false");
}
});
checkScroll();
});
+6 -2
View File
@@ -399,7 +399,10 @@ const playerArtworkOpacity = 0.4;
this.UI.progress.bar.addEventListener("click", function (event) {
event.stopPropagation();
window.player.seek(event.clientX / window.innerWidth);
const rect = this.getBoundingClientRect();
const per =
rect.width > 0 ? (event.clientX - rect.left) / rect.width : 0;
window.player.seek(Math.min(Math.max(per, 0), 1));
});
// Tap the circle to expand (not the play button).
@@ -578,8 +581,9 @@ const playerArtworkOpacity = 0.4;
*/
pause() {
// Get the Howl we want to manipulate.
var sound = this.playlist[this.index].howl;
var sound = this.playlist[this.index]?.howl;
if (!sound) return;
sound.pause();
this.syncPlayPauseUI(false);
+11 -8
View File
@@ -16,7 +16,7 @@ import { Schema } from "astro-seo-schema";
<!-- SEO -->
<link rel="canonical" href={url} />
<meta name="robots" content="all" />
<meta name="robots" content="index, follow" />
<Schema
item={{
"@context": "https://schema.org",
@@ -86,8 +86,11 @@ import { Schema } from "astro-seo-schema";
/>
<meta property="og:image:alt" content={image?.alt || site.image.alt} />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:width" content={image?.width.toString() || "1920"} />
<meta property="og:image:height" content={image?.height.toString() || "1080"} />
<meta property="og:image:width" content={image?.width?.toString() || "1920"} />
<meta
property="og:image:height"
content={image?.height?.toString() || "1080"}
/>
<!-- Twitter -->
<meta name="twitter:site" content="@nathancummins.au" />
@@ -100,8 +103,8 @@ import { Schema } from "astro-seo-schema";
? image.externalURL
: site.image.externalURL}
/>
<meta name="twitter:image:alt" content={title} />
<meta name="twitter:domain" content={import.meta.env.SITE} />
<!-- Theming -->
<meta name="theme-color" content="#ff2d00" />
<meta name="twitter:image:alt" content={image?.alt || site.image.alt} />
<meta
name="twitter:domain"
content={import.meta.env.SITE ?? "www.nathancummins.com.au"}
/>
+1 -1
View File
@@ -7,7 +7,7 @@ interface Props {
}
const {
Tag = "h1",
Tag = "h2",
lineColour = "border-primary",
lineColourDark = "dark:text-primary",
class: className
+2 -2
View File
@@ -26,13 +26,13 @@ const linkIsExternal: boolean =
target={href?.toString().startsWith("http") ? "_blank" : undefined}
rel={linkIsExternal ? "noopener noreferrer" : undefined}
{...attrs}
><span class="group-hover:text-primary-100"><slot /></span>{
><span class="group-hover:text-primary-600"><slot /></span>{
includeExternalLinkIcon && linkIsExternal && (
<sup class="ml-0.5 inline-block">
<Icon
name="mdi:external-link"
class:list={[
"text-primary group-hover:text-primary-100 m-0 inline-block"
"text-primary group-hover:text-primary-600 m-0 inline-block"
]}
/>
</sup>
+5 -3
View File
@@ -2,9 +2,11 @@
import { Icon } from "astro-icon/components";
---
<span
class="theme:switcher flex justify-center text-center align-middle text-2xl"
<button
type="button"
class="theme:switcher mx-auto flex w-full justify-center text-center align-middle text-2xl"
onclick="toggleTheme()"
aria-label="Toggle colour theme"
>
<span class="theme:light-mode">
<Icon name="fa7-solid:sun" />
@@ -12,7 +14,7 @@ import { Icon } from "astro-icon/components";
<span class="theme:dark-mode">
<Icon name="fa7-solid:moon" />
</span>
</span>
</button>
<script is:inline>
function updateThemeIconAndAriaLabel(
+1 -1
View File
@@ -8,6 +8,6 @@ export default {
image: {
externalURL: `${import.meta.env.SITE}/nathan-cummins-composer-orchestrator-conductor.jpg`,
src: "nathan-cummins-composer-orchestrator-conductor.jpg",
alt: "Nathan Cummins"
alt: "Picture of Nathan Cummins, Adelaide composer, orchestrator, and conductor"
} as SiteImage
};
+1
View File
@@ -14,6 +14,7 @@ interface Window {
}
interface ImportMetaEnv {
readonly SITE?: string;
readonly EMAIL_USER: string;
readonly EMAIL_PASS: string;
readonly EMAIL_PORT: number;
+5 -4
View File
@@ -17,7 +17,7 @@ const allProjectHeros = import.meta.glob<{ default: ImageMetadata }>(
);
const allImages = import.meta.glob<{ default: ImageMetadata }>(
"/**/*.{jpeg,jpg,png,gif}",
"/src/assets/**/*.{jpeg,jpg,png,gif}",
{
eager: true
}
@@ -82,11 +82,12 @@ export function getAllProjectImages(project: Project): ImageMetadata[] {
}
export function shuffleArray<T>(array: Array<T>): Array<T> {
for (let i = array.length - 1; i > 0; i--) {
const copy = [...array];
for (let i = copy.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
[copy[i], copy[j]] = [copy[j], copy[i]];
}
return array;
return copy;
}
export async function convertEagerImagesImportGlobToArray(
+5 -6
View File
@@ -17,27 +17,26 @@ const heroImagesArray = await convertEagerImagesImportGlobToArray(heroImages);
images={heroImagesArray}
class="h-full w-full"
foreground={true}
foreground={true}
foregroundOpacity="opacity-80"
/>
</div>
<div
class="absolute inset-0 flex h-full w-full flex-col justify-center px-8 py-36 text-center"
>
<h1
<p
class="font-header pb-8 text-5xl font-medium text-white uppercase text-shadow-lg/75 md:text-7xl lg:text-9xl"
>
Oops!
</h1>
<h2
</p>
<h1
class="font-header text-2xl font-medium text-gray-300 uppercase text-shadow-lg/75 md:text-2xl lg:text-4xl"
>
404 - Page not found
</h2>
</h1>
<a
href="/"
class="bg-primary text-md font-header hover:text-primary repeat hover:ring-primary mx-auto mt-8 inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow-lg/75 transition hover:bg-white hover:ring-2"
class="bg-primary text-md font-header hover:text-primary hover:ring-primary mx-auto mt-8 inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow-lg/75 transition hover:bg-white hover:ring-2"
>
Home
</a>
+1 -1
View File
@@ -22,7 +22,7 @@ import { Image } from "astro:assets";
class="mx-auto mb-8 size-125 rounded-full object-cover shadow-lg/75 transition ease-in-out md:hover:scale-150"
height={750}
/>
<SectionTitle class="py-8">Dr Nathan Cummins</SectionTitle>
<SectionTitle Tag="h1" class="py-8">Dr Nathan Cummins</SectionTitle>
<H2>{site.tagline}</H2>
<Paragraph
>Nathan Cummins is a composer, orchestrator, conductor, and sound
+1 -1
View File
@@ -11,7 +11,7 @@ import { Icon } from "astro-icon/components";
<div class="w-full">
<section id="contact" class="bg-primary dark:bg-gray-800">
<div class="mx-auto max-w-4xl px-8 py-16 text-center">
<SectionTitle class="text-white" lineColour="text-white"
<SectionTitle Tag="h1" class="text-white" lineColour="text-white"
>Let's get in touch!</SectionTitle
>
<ContactForm />
+4 -4
View File
@@ -78,7 +78,7 @@ const tracks = (
<a
href="/contact/"
class="bg-primary text-md font-header hover:text-primary repeat hover:ring-primary mx-auto mt-8 inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow-lg/75 transition hover:bg-white hover:ring-2"
class="bg-primary text-md font-header hover:text-primary hover:ring-primary mx-auto mt-8 inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow-lg/75 transition hover:bg-white hover:ring-2"
>
Get in touch!
</a>
@@ -98,7 +98,7 @@ const tracks = (
<span class="block w-full text-center"
><a
href="/about/"
class="bg-primary text-md font-header hover:text-primary repeat hover:ring-primary mx-auto mt-8 inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow-lg/75 transition hover:bg-white hover:ring-2"
class="bg-primary text-md font-header hover:text-primary hover:ring-primary mx-auto mt-8 inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow-lg/75 transition hover:bg-white hover:ring-2"
>
Find out more
</a></span
@@ -121,7 +121,7 @@ const tracks = (
><div class="flex h-full w-full items-center">
<a
href="/contact/"
class="text-md font-header repeat text-primary hover:bg-primary mx-auto inline-block rounded bg-white px-6 py-3 font-light uppercase drop-shadow-lg/75 transition hover:text-white hover:ring-2 hover:ring-white"
class="text-md font-header text-primary hover:bg-primary mx-auto inline-block rounded bg-white px-6 py-3 font-light uppercase drop-shadow-lg/75 transition hover:text-white hover:ring-2 hover:ring-white"
>
Get in touch!
</a>
@@ -150,7 +150,7 @@ const tracks = (
</div>
<a
href="/projects/"
class="bg-primary text-md font-header hover:text-primary repeat hover:ring-primary mx-auto mt-8 inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow-lg/75 transition hover:bg-white hover:ring-2"
class="bg-primary text-md font-header hover:text-primary hover:ring-primary mx-auto mt-8 inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow-lg/75 transition hover:bg-white hover:ring-2"
>
Explore more projects
</a>
+1 -1
View File
@@ -20,7 +20,7 @@ const types = [...new Set(projects.map((project) => project.data.type))];
<div class="w-full">
<section id="projects" class="bg-white dark:bg-gray-950">
<div class="mx-auto max-w-4xl px-8 py-16 text-center">
<SectionTitle>Recent Projects</SectionTitle>
<SectionTitle Tag="h1">Recent Projects</SectionTitle>
<div id="filter-tokens" class="my-8 space-y-2 space-x-2">
<Token
class="filter-token !text-primary ring-primary bg-white ring-2 hover:cursor-pointer"
+1 -1
View File
@@ -11,7 +11,7 @@ import MainLayout from "@layouts/MainLayout.astro";
<div class="w-full bg-white py-16 dark:bg-gray-950">
<section id="intro">
<div class="mx-auto max-w-4xl px-8 text-left">
<SectionTitle class="pb-8">Sheet Music</SectionTitle>
<SectionTitle Tag="h1" class="pb-8">Sheet Music</SectionTitle>
<Paragraph
>Sheet music for many of my pieces and orchestrations is available for
purchase or rent. If you are interested in sheet music for performance
-1
View File
@@ -1,5 +1,4 @@
@import url("https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&display=swap");
@import "../../public/fonts/inter/inter.css";
@import "tailwindcss";
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));