From 5f5a32927aa3df2be4761374966dbad807d22e19 Mon Sep 17 00:00:00 2001 From: Willie Chalmers III Date: Wed, 30 Sep 2026 20:04:01 -0700 Subject: [PATCH 1/2] fix(site): Make join steps compact and clear Put the join form's purpose ahead of its progress cue and keep both stages visible without crowding the first question on small screens. Label the optional stage for all the details it asks about. Co-authored-by: Codex --- apps/site/public/scripts/join-steps.js | 47 ++++++++++++++----- apps/site/src/components/join/JoinForm.astro | 2 +- .../src/components/join/JoinProgress.astro | 12 +++-- apps/site/src/pages/join/member/index.astro | 9 ++-- 4 files changed, 49 insertions(+), 21 deletions(-) diff --git a/apps/site/public/scripts/join-steps.js b/apps/site/public/scripts/join-steps.js index b3e02553..7529b49e 100644 --- a/apps/site/public/scripts/join-steps.js +++ b/apps/site/public/scripts/join-steps.js @@ -2,6 +2,20 @@ // The basic details and optional questions share one form, so the join still // works without JavaScript. With JavaScript, they become two short screens. (() => { + function updateProgress(items, step) { + items.forEach((item, index) => { + const current = index + 1 === step; + if (current) item.setAttribute('aria-current', 'step'); + else item.removeAttribute('aria-current'); + item.classList.toggle('border-primary', current); + item.classList.toggle('border-outline/25', index + 1 > step); + item.classList.toggle('border-on-surface', index + 1 < step); + item.classList.toggle('text-on-surface', index + 1 <= step); + item.classList.toggle('text-on-surface-variant', index + 1 > step); + item.classList.toggle('font-bold', current); + }); + } + function run() { const form = document.querySelector('form[action="/join/member/"][data-enhance]'); const progress = document.querySelector('[data-join-progress]'); @@ -14,7 +28,23 @@ const email = form.querySelector('[name="email"]'); const consent = form.querySelector('[name="consent"]'); const items = progress.querySelectorAll('li'); - if (!first || !second || !continueButton || !backButton || !email || !consent) return; + const basicHeading = document.querySelector('[data-join-heading-basic]'); + const interestsHeading = document.querySelector('[data-join-heading-interests]'); + const intro = document.querySelector('[data-join-intro]'); + if ( + [ + first, + second, + continueButton, + backButton, + email, + consent, + basicHeading, + interestsHeading, + intro, + ].some((element) => !element) + ) + return; form.dataset.joinSteps = '1'; progress.style.display = ''; @@ -24,17 +54,10 @@ function show(step) { first.hidden = step !== 1; second.hidden = step !== 2; - items.forEach((item, index) => { - const current = index + 1 === step; - if (current) item.setAttribute('aria-current', 'step'); - else item.removeAttribute('aria-current'); - item.classList.toggle('border-primary', current); - item.classList.toggle('border-outline/25', index + 1 > step); - item.classList.toggle('border-on-surface', index + 1 < step); - item.classList.toggle('text-on-surface', index + 1 <= step); - item.classList.toggle('text-on-surface-variant', index + 1 > step); - item.classList.toggle('font-bold', current); - }); + basicHeading.hidden = step !== 1; + interestsHeading.hidden = step !== 2; + intro.hidden = step !== 1; + updateProgress(items, step); if (step === 2) second.querySelector('[data-join-stage-heading]')?.focus({ preventScroll: true }); else email.focus({ preventScroll: true }); diff --git a/apps/site/src/components/join/JoinForm.astro b/apps/site/src/components/join/JoinForm.astro index da6e95f6..cf5fe136 100644 --- a/apps/site/src/components/join/JoinForm.astro +++ b/apps/site/src/components/join/JoinForm.astro @@ -84,7 +84,7 @@ const { action } = Astro.props;

- Everything here is optional. Tell us what interests you! + Share what you'd like, or skip these questions.