diff --git a/src/components/MembershipPage.tsx b/src/components/MembershipPage.tsx index 09fb13d4..e8711ae5 100644 --- a/src/components/MembershipPage.tsx +++ b/src/components/MembershipPage.tsx @@ -88,7 +88,7 @@ export default function MembershipPage() { href="#join" onClick={handleJoinClick("secondary_cta")} data-membership-cta="true" - className="inline-flex min-h-[44px] items-center justify-center rounded-full bg-[#168039] px-6 py-3 font-semibold text-white shadow-sm transition-all duration-150 hover:bg-[#116b2f] hover:shadow-md active:bg-[#116b2f] active:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#168039] focus-visible:ring-offset-2" + className="inline-flex min-h-[88px] items-center justify-center rounded-full bg-[#168039] px-12 py-6 text-2xl font-semibold text-white shadow-sm transition-all duration-150 hover:bg-[#116b2f] hover:shadow-md active:bg-[#116b2f] active:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#168039] focus-visible:ring-offset-2" > Become a member diff --git a/src/components/TestimonialsMarquee.astro b/src/components/TestimonialsMarquee.astro index 6e1f3f70..2347dd8a 100644 --- a/src/components/TestimonialsMarquee.astro +++ b/src/components/TestimonialsMarquee.astro @@ -13,18 +13,21 @@ interface Props { membershipLive?: boolean; heading?: string; subheading?: string; + background?: "default" | "green"; } const { membershipLive = false, heading = "What it's like to work with T4P", subheading = "Project leaders, mentors, and members on their time inside the coalition.", + background = "default", } = Astro.props; const testimonials = getTestimonials(membershipLive); +const sectionBgClass = background === "green" ? "border-green-100 bg-green-50" : "border-zinc-200 bg-zinc-50"; --- -
+

{heading}

{subheading}

diff --git a/src/components/home/TestimonialsSection.astro b/src/components/home/TestimonialsSection.astro index f7f4e259..f2daab16 100644 --- a/src/components/home/TestimonialsSection.astro +++ b/src/components/home/TestimonialsSection.astro @@ -10,6 +10,7 @@ interface Props { accent?: string; /** Right-hand supporting line, beside the heading on wide viewports. */ subheading?: string; + background?: "default" | "green"; } const { @@ -18,12 +19,14 @@ const { heading = "What it's like to", accent = "work with T4P", subheading = "Project leaders, mentors, and members on their time inside the coalition.", + background = "default", } = Astro.props; const testimonials = getTestimonials(membershipLive); +const sectionBgClass = background === "green" ? "bg-positive-tint" : "bg-page"; --- -
+
(undefined); const [step, setStep] = useState<"about-you" | "payment">("about-you"); const [aboutYou, setAboutYou] = useState(null); const [revealed, setRevealed] = useState(false); const [advancingToPayment, setAdvancingToPayment] = useState(false); - const runsCalculatorTest = tier === "member"; - function handleAboutYouContinue(data: AboutYouData) { setAboutYou(data); setAdvancingToPayment(true); @@ -74,40 +70,6 @@ export default function LegacyJoinSection({ tier, heading }: LegacyJoinSectionPr ? { ...splitName(aboutYou.name), email: aboutYou.email } : undefined; - useEffect(() => { - if (!runsCalculatorTest) return; - - const urlParams = new URLSearchParams(window.location.search); - const urlParam = urlParams.get("calculator"); - - let assigned: boolean; - if (urlParam === "yes") { - assigned = true; - } else if (urlParam === "no") { - assigned = false; - } else { - const stored = localStorage.getItem("membership_ab_variant"); - if (stored === "Calculator") { - assigned = true; - } else if (stored === "No Calculator") { - assigned = false; - } else { - assigned = Math.random() < 0.5; - localStorage.setItem("membership_ab_variant", assigned ? "Calculator" : "No Calculator"); - } - } - - const assignedVariant = assigned ? "Calculator" : "No Calculator"; - setShowCalculator(assigned); - setVariant(assignedVariant); - - if (typeof window.plausible !== "undefined") { - window.plausible("Membership Page", { - props: { membership_variant: assignedVariant }, - }); - } - }, [runsCalculatorTest]); - useEffect(() => { // The CTA that dispatches "membership:reveal-join" may fire before this // island hydrates and registers its listener (e.g. the plain CTAs on @@ -129,17 +91,12 @@ export default function LegacyJoinSection({ tier, heading }: LegacyJoinSectionPr return () => window.removeEventListener("membership:reveal-join", handleReveal); }, []); - // The supporting tier always gets the calculator; the member tier only gets - // it in the "Calculator" A/B arm. - const calculatorVisible = step === "payment" && (tier === "supporting" || showCalculator); + const calculatorVisible = step === "payment"; - const intro = calculatorVisible - ? tier === "supporting" + const intro = + tier === "supporting" ? "Contribute any amount for supporting membership dues. We suggest monthly dues equal to one hour's salary, which you can calculate below:" - : "Contribute any amount for membership dues. We suggest monthly dues equal to one hour's salary, which you can calculate below:" - : tier === "supporting" - ? "Contribute any amount for supporting membership dues. We suggest monthly dues equal to one hour's salary." - : "Contribute any amount for membership dues. We suggest monthly dues equal to one hour's salary."; + : "Contribute any amount for membership dues. We suggest monthly dues equal to one hour's salary, which you can calculate below:"; return ( @@ -217,7 +174,7 @@ export default function LegacyJoinSection({ tier, heading }: LegacyJoinSectionPr {aboutYou && ( - + )} diff --git a/src/components/membership/MembershipDues.tsx b/src/components/membership/MembershipDues.tsx index e5ed0b1e..21864766 100644 --- a/src/components/membership/MembershipDues.tsx +++ b/src/components/membership/MembershipDues.tsx @@ -35,17 +35,11 @@ const JOIN_PANEL_HEIGHT = 640; const NEXT_BUTTON_LOADING_MS = 400; export default function MembershipDues({ tier = "member" }: MembershipDuesProps) { - // Default to the no-calculator variant so this renders identically during - // SSR (no window/localStorage access) before the A/B assignment runs below. - const [showCalculator, setShowCalculator] = useState(false); - const [variant, setVariant] = useState(undefined); const [step, setStep] = useState<"about-you" | "payment">("about-you"); const [aboutYou, setAboutYou] = useState(null); const [revealed, setRevealed] = useState(false); const [advancingToPayment, setAdvancingToPayment] = useState(false); - const runsCalculatorTest = tier === "member"; - function handleAboutYouContinue(data: AboutYouData) { setAboutYou(data); setAdvancingToPayment(true); @@ -64,40 +58,6 @@ export default function MembershipDues({ tier = "member" }: MembershipDuesProps) ? { ...splitName(aboutYou.name), email: aboutYou.email } : undefined; - useEffect(() => { - if (!runsCalculatorTest) return; - - const urlParams = new URLSearchParams(window.location.search); - const urlParam = urlParams.get("calculator"); - - let assigned: boolean; - if (urlParam === "yes") { - assigned = true; - } else if (urlParam === "no") { - assigned = false; - } else { - const stored = localStorage.getItem("membership_ab_variant"); - if (stored === "Calculator") { - assigned = true; - } else if (stored === "No Calculator") { - assigned = false; - } else { - assigned = Math.random() < 0.5; - localStorage.setItem("membership_ab_variant", assigned ? "Calculator" : "No Calculator"); - } - } - - const assignedVariant = assigned ? "Calculator" : "No Calculator"; - setShowCalculator(assigned); - setVariant(assignedVariant); - - if (typeof window.plausible !== "undefined") { - window.plausible("Membership Page", { - props: { membership_variant: assignedVariant }, - }); - } - }, [runsCalculatorTest]); - useEffect(() => { // The CTA that dispatches "membership:reveal-join" may fire before this // island hydrates and registers its listener (e.g. plain CTAs tracked @@ -119,17 +79,12 @@ export default function MembershipDues({ tier = "member" }: MembershipDuesProps) return () => window.removeEventListener("membership:reveal-join", handleReveal); }, []); - // The supporting tier always gets the calculator; the member tier only gets - // it in the "Calculator" A/B arm. - const calculatorVisible = step === "payment" && (tier === "supporting" || showCalculator); + const calculatorVisible = step === "payment"; - const intro = calculatorVisible - ? tier === "supporting" + const intro = + tier === "supporting" ? "Contribute any amount for supporting membership dues. We suggest monthly dues equal to one hour's salary, which you can calculate below:" - : "Contribute any amount for membership dues. We suggest monthly dues equal to one hour's salary, which you can calculate below:" - : tier === "supporting" - ? "Contribute any amount for supporting membership dues. We suggest monthly dues equal to one hour's salary." - : "Contribute any amount for membership dues. We suggest monthly dues equal to one hour's salary."; + : "Contribute any amount for membership dues. We suggest monthly dues equal to one hour's salary, which you can calculate below:"; return (
@@ -199,7 +154,7 @@ export default function MembershipDues({ tier = "member" }: MembershipDuesProps)
{aboutYou && (
- +
)}
diff --git a/src/components/membership/QgivJoin.tsx b/src/components/membership/QgivJoin.tsx index 7298ed90..ccce72f7 100644 --- a/src/components/membership/QgivJoin.tsx +++ b/src/components/membership/QgivJoin.tsx @@ -22,11 +22,6 @@ function prefillKey(prefill?: QgivPrefill): string { interface QgivJoinProps { tier: MembershipTier; - /** - * Plausible prop recording which membership-page A/B variant the visitor saw. - * Only meaningful for the `member` tier. - */ - variant?: string; className?: string; prefill?: QgivPrefill; } @@ -46,7 +41,7 @@ interface QgivTransactionDetail { * embed and the listener — keeping them apart is what caused /membership-new to * silently stop sending Hub invites and EmailOctopus tags. */ -export default function QgivJoin({ tier, variant, className, prefill }: QgivJoinProps) { +export default function QgivJoin({ tier, className, prefill }: QgivJoinProps) { const form = QGIV_FORMS[tier]; const scriptLoadedRef = useRef(false); const containerRef = useRef(null); @@ -183,7 +178,6 @@ export default function QgivJoin({ tier, variant, className, prefill }: QgivJoin props: { amount: transaction.total != null ? String(transaction.total) : "", membership_tier: tier, - ...(variant ? { membership_variant: variant } : {}), }, }); } @@ -205,7 +199,7 @@ export default function QgivJoin({ tier, variant, className, prefill }: QgivJoin document.addEventListener("QGIV.donationComplete", handleDonationComplete); return () => document.removeEventListener("QGIV.donationComplete", handleDonationComplete); - }, [tier, variant]); + }, [tier]); // Safety net for a tier whose embed ID has been cleared: link out to the // hosted form so the page still converts, at the cost of losing completion diff --git a/src/components/ui/Button.astro b/src/components/ui/Button.astro index a6775c18..37917365 100644 --- a/src/components/ui/Button.astro +++ b/src/components/ui/Button.astro @@ -1,7 +1,7 @@ --- interface Props { variant?: "primary" | "ghost" | "text"; - size?: "md" | "lg"; + size?: "md" | "lg" | "xl"; href?: string; arrow?: boolean; class?: string; @@ -22,6 +22,7 @@ const base = const sizes = { md: "px-5 py-3.5", lg: "px-10 py-5 min-[810px]:px-11", + xl: "btn-xl px-10 py-7 min-[810px]:px-14 min-[810px]:py-8", }; const variants = { @@ -41,8 +42,8 @@ const Tag = href ? "a" : "button"; { arrow && ( + + diff --git a/src/pages/membership-new.astro b/src/pages/membership-new.astro index 3f8501a9..2b62e1eb 100644 --- a/src/pages/membership-new.astro +++ b/src/pages/membership-new.astro @@ -135,7 +135,7 @@ const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true";
- + diff --git a/src/pages/membership.astro b/src/pages/membership.astro index ec5b05ea..ddf390e3 100644 --- a/src/pages/membership.astro +++ b/src/pages/membership.astro @@ -47,6 +47,6 @@ import "../styles/base.css";
- + diff --git a/src/pages/supporting-member-new.astro b/src/pages/supporting-member-new.astro index ea319a42..a4212c6a 100644 --- a/src/pages/supporting-member-new.astro +++ b/src/pages/supporting-member-new.astro @@ -116,7 +116,7 @@ const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true";
- + diff --git a/src/pages/supporting-member.astro b/src/pages/supporting-member.astro index be8c9c51..b2e89186 100644 --- a/src/pages/supporting-member.astro +++ b/src/pages/supporting-member.astro @@ -194,14 +194,14 @@ const logoWallLabel = `Projects supported by Tech for Palestine: ${showcaseProje href="#join" data-track-join-click="secondary_cta" data-membership-cta="true" - class="inline-flex min-h-[44px] items-center justify-center rounded-full bg-[#168039] px-6 py-3 font-semibold text-white shadow-sm transition-all duration-150 hover:bg-[#116b2f] hover:shadow-md active:bg-[#116b2f] active:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#168039] focus-visible:ring-offset-2" + class="inline-flex min-h-[88px] items-center justify-center rounded-full bg-[#168039] px-12 py-6 text-2xl font-semibold text-white shadow-sm transition-all duration-150 hover:bg-[#116b2f] hover:shadow-md active:bg-[#116b2f] active:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#168039] focus-visible:ring-offset-2" > Become a Supporting Member - +