Finalize homepage with Affiliated Clubs + add gradient to homepage

This commit is contained in:
Antoine Phan
2025-10-18 14:26:52 -04:00
4 changed files with 152 additions and 138 deletions

View File

@@ -1,54 +1,67 @@
<script lang="ts"> <script lang="ts">
import { ExternalLink, Wrench, Zap, Code2 } from '@lucide/svelte'; import { ExternalLink, Wrench, Zap, CodeXml } from '@lucide/svelte';
const clubs = [ // All icons from @lucide/svelte share the same component type; reuse one for typing
type IconComponent = typeof Wrench;
type Club = {
name: string;
description: string;
website: string;
icon: IconComponent;
features: string[];
};
const clubs: Club[] = [
{ {
name: 'The Factory', name: 'The Factory',
description: description:
'A hardware design lab run by students, for students. A dedicated space for developing personal projects, gaining experience with cutting-edge hardware, and fostering innovation.', 'A hardware design lab run by students, for students. A dedicated space for developing personal projects, gaining experience with cutting-edge hardware, and fostering innovation.',
website: 'https://factory.mcgilleus.ca/', website: 'https://factory.mcgilleus.ca/',
icon: Wrench, icon: Wrench,
features: ['PCB Printer', '3D Printing', 'Arduino & Raspberry Pi', 'Hardware Workshops'] features: ['Hardware Lab Space', '3D Printing', 'Equipment Rental', 'Hardware Workshops']
}, },
{ {
name: 'IEEE McGill', name: 'IEEE McGill',
description: description:
'One of the largest IEEE student branches in Eastern Canada. Dedicated to professional development through networking, workshops, competitions, and industry connections.', 'One of the largest IEEE student branches in Eastern Canada. Dedicated to professional development through networking, workshops, competitions, and industry connections.',
website: 'https://ieeemcgill.com/', website: 'https://ieee.mcgilleus.ca/',
icon: Zap, icon: Zap,
features: ['Technical Talks', 'Company Tours', 'IEEEXtreme Competition', 'Networking Events'] features: ['Technical Talks', 'Arduino Workshops', 'IEEEXtreme Competition', 'Networking Events']
}, },
{ {
name: 'CodeJam', name: 'CodeJam',
description: description:
"McGill Engineering's largest and longest-running hackathon. A 36-hour programming competition where students create innovative solutions to real-world problems.", "McGill Engineering's largest and longest-running hackathon. A 36-hour programming competition where students create innovative solutions to real-world problems.",
website: 'https://codejam.mcgilleus.ca/', website: 'https://codejam.mcgilleus.ca/',
icon: Code2, icon: CodeXml,
features: ['Annual Hackathon', 'Industry Mentors', 'Prize Pool', 'Networking with Sponsors'] features: ['Annual Hackathon', 'Industry Mentors', 'Networking Opportunities', "Big Prize Pool"]
} }
]; ];
</script> </script>
<section <div class="container mx-auto px-4">
class="to-ecsess-50 dark:from-ecsess-950 dark:to-ecsess-900 w-full bg-gradient-to-b from-white py-16"
>
<div class="container mx-auto px-4">
<!-- Section Header --> <!-- Section Header -->
<div class="mb-12 text-center"> <div class="mb-12 text-center">
<h2 class="text-ecsess-800 dark:text-ecsess-100 mb-4 text-4xl font-bold md:text-5xl"> <h2
id="affiliated-clubs-title"
class="text-ecsess-800 dark:text-ecsess-100 mb-4 text-4xl font-bold md:text-5xl"
>
Affiliated Clubs & Labs Affiliated Clubs & Labs
</h2> </h2>
<p class="text-ecsess-700 dark:text-ecsess-200 mx-auto max-w-2xl text-lg"> <p class="text-ecsess-700 dark:text-ecsess-200 mx-auto max-w-2xl text-lg">
Explore opportunities to enhance your skills, build innovative projects, and connect with Explore opportunities to enhance your skills, build innovative projects, and connect with the
the engineering community through our affiliated organizations. engineering community through our affiliated organizations.
</p> </p>
</div> </div>
<!-- Clubs Grid --> <!-- Clubs Grid -->
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3"> <div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{#each clubs as club} {#each clubs as club, i (club.name)}
<div {@const Icon = club.icon}
class="group dark:bg-ecsess-950 relative flex flex-col overflow-hidden rounded-2xl bg-white shadow-lg transition-all duration-300 hover:-translate-y-2 hover:shadow-2xl" <article
class="group bg-ecsess-950 relative flex flex-col overflow-hidden rounded-2xl shadow-ecsess-800 shadow-xl transition-all duration-300 hover:-translate-y-2 hover:shadow-2xl"
aria-labelledby={`club-${i}-title`}
> >
<!-- Decorative gradient bar --> <!-- Decorative gradient bar -->
<div class="from-ecsess-400 via-ecsess-500 to-ecsess-600 h-2 bg-gradient-to-r"></div> <div class="from-ecsess-400 via-ecsess-500 to-ecsess-600 h-2 bg-gradient-to-r"></div>
@@ -57,59 +70,53 @@
<!-- Icon and Name --> <!-- Icon and Name -->
<div class="mb-4 flex items-center gap-4"> <div class="mb-4 flex items-center gap-4">
<div <div
class="bg-ecsess-100 group-hover:bg-ecsess-500 dark:bg-ecsess-800 flex h-14 w-14 items-center justify-center rounded-xl shadow-md transition-all duration-300 group-hover:scale-110" class="group-hover:bg-ecsess-500 bg-ecsess-800 flex h-14 w-14 items-center justify-center rounded-xl shadow-md transition-all duration-300 group-hover:scale-110"
> >
{#if club.icon === Wrench} <Icon
<Wrench
class="text-ecsess-600 dark:text-ecsess-300 h-7 w-7 transition-colors group-hover:text-white" class="text-ecsess-600 dark:text-ecsess-300 h-7 w-7 transition-colors group-hover:text-white"
strokeWidth={2.5} strokeWidth={2.5}
aria-hidden="true"
focusable="false"
/> />
{:else if club.icon === Zap}
<Zap
class="text-ecsess-600 dark:text-ecsess-300 h-7 w-7 transition-colors group-hover:text-white"
strokeWidth={2.5}
/>
{:else if club.icon === Code2}
<Code2
class="text-ecsess-600 dark:text-ecsess-300 h-7 w-7 transition-colors group-hover:text-white"
strokeWidth={2.5}
/>
{/if}
</div> </div>
<h3 class="text-ecsess-800 dark:text-ecsess-50 text-2xl font-bold"> <h3
id={`club-${i}-title`}
class="text-ecsess-800 dark:text-ecsess-50 text-2xl font-bold"
>
{club.name} {club.name}
</h3> </h3>
</div> </div>
<!-- Description --> <!-- Description -->
<p class="text-ecsess-700 dark:text-ecsess-200 mb-6 flex-1 text-sm leading-relaxed"> <p class="text-ecsess-700 dark:text-ecsess-200 mb-6 flex-1 text-base leading-relaxed">
{club.description} {club.description}
</p> </p>
<!-- Features --> <!-- Features -->
<div class="mb-6 space-y-2"> <ul class="mb-6 space-y-2" role="list">
{#each club.features as feature} {#each club.features as feature (feature)}
<div class="flex items-center gap-2"> <li class="flex items-center gap-2 pl-3">
<div class="bg-ecsess-500 h-1.5 w-1.5 rounded-full"></div> <div class="bg-ecsess-500 h-1.5 w-1.5 rounded-full" aria-hidden="true"></div>
<span class="text-ecsess-600 dark:text-ecsess-300 text-xs font-semibold"> <span class="text-ecsess-600 dark:text-ecsess-300 text-base font-semibold">
{feature} {feature}
</span> </span>
</div> </li>
{/each} {/each}
</div> </ul>
<!-- Visit Button --> <!-- Visit Button -->
<a <a
href={club.website} href={club.website}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer external"
aria-label={`Visit ${club.name} website`}
class="bg-ecsess-500 hover:bg-ecsess-600 dark:bg-ecsess-400 dark:hover:bg-ecsess-500 flex items-center justify-center gap-2 rounded-xl px-6 py-3 text-sm font-bold text-white shadow-md transition-all hover:shadow-lg active:scale-95" class="bg-ecsess-500 hover:bg-ecsess-600 dark:bg-ecsess-400 dark:hover:bg-ecsess-500 flex items-center justify-center gap-2 rounded-xl px-6 py-3 text-sm font-bold text-white shadow-md transition-all hover:shadow-lg active:scale-95"
> >
Visit Website Visit Website
<ExternalLink class="h-4 w-4" strokeWidth={2.5} /> <ExternalLink class="h-4 w-4" strokeWidth={2.5} aria-hidden="true" focusable="false" />
</a> </a>
</div> </div>
</div> </article>
{/each} {/each}
</div> </div>
@@ -119,5 +126,4 @@
Want to get involved? Visit their websites to learn about upcoming events and how to join! Want to get involved? Visit their websites to learn about upcoming events and how to join!
</p> </p>
</div> </div>
</div> </div>
</section>

View File

@@ -32,12 +32,6 @@
url: 'mailto:ecsess.president@mcgilleus.ca', url: 'mailto:ecsess.president@mcgilleus.ca',
icon: 'email', icon: 'email',
ariaLabel: 'Send us an email' ariaLabel: 'Send us an email'
},
{
name: 'Lounge Location',
url: 'https://maps.app.goo.gl/4RHKGJEE8FfcDs1H8',
icon: 'location',
ariaLabel: 'View lounge location on map'
} }
]; ];
</script> </script>
@@ -45,19 +39,17 @@
<footer class="bg-ecsess-black text-ecsess-100 mx-auto min-w-fit px-4 py-8"> <footer class="bg-ecsess-black text-ecsess-100 mx-auto min-w-fit px-4 py-8">
<div class="mx-auto max-w-7xl"> <div class="mx-auto max-w-7xl">
<!-- Business Card Layout --> <!-- Business Card Layout -->
<div class="mb-6 grid grid-cols-1 gap-8 md:grid-cols-3"> <div class="mb-6 grid grid-cols-1 gap-6 md:grid-cols-3">
<!-- Left: ECSESS Info & Location --> <!-- Left: ECSESS Lounge -->
<div class="text-center md:text-left"> <div class="border-ecsess-800 border-b-1 pb-4 text-center md:border-0 md:text-left">
<h3 class="text-ecsess-150 mb-2 text-xl font-bold">ECSESS</h3> <p class="text-ecsess-300 mb-3 text-lg">
<p class="text-ecsess-200 mb-3 text-sm"> Visit the ECSESS lounge!
Electrical, Computer & Software<br />
Engineering Students' Society
</p> </p>
<a <a
href="https://maps.app.goo.gl/4RHKGJEE8FfcDs1H8" href="https://maps.app.goo.gl/m9ZqjTrPM7pcBzhbA"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="text-ecsess-200 hover:text-ecsess-100 inline-flex items-center gap-2 transition-colors" class="text-ecsess-300 hover:text-ecsess-100 border-b-1 border-b-transparent hover:border-b-ecsess-100 inline-flex items-center gap-2 justify-baseline transition-all pb-0.5"
> >
<svg <svg
class="h-4 w-4 flex-shrink-0" class="h-4 w-4 flex-shrink-0"
@@ -79,15 +71,15 @@
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
/> />
</svg> </svg>
<span class="text-sm">ENGTR 1060</span> <span class="text-base">ENGTR 1060</span>
</a> </a>
</div> </div>
<!-- Center: Connect With Us --> <!-- Center: Connect With Us -->
<div class="text-center"> <div class="border-ecsess-800 border-b-1 pb-8 text-center md:border-0">
<h3 class="text-ecsess-150 mb-3 text-lg font-semibold">Connect With Us</h3> <h3 class="text-ecsess-150 mb-3 text-lg font-semibold">Connect With Us</h3>
<div class="flex flex-wrap items-center justify-center gap-3"> <div class="flex flex-wrap items-center justify-center gap-3">
{#each socialLinks.filter((link) => link.icon !== 'location') as link} {#each socialLinks as link}
<a <a
href={link.url} href={link.url}
target={link.icon === 'email' ? '_self' : '_blank'} target={link.icon === 'email' ? '_self' : '_blank'}
@@ -166,12 +158,12 @@
<!-- Right: Contribute --> <!-- Right: Contribute -->
<div class="text-center md:text-right"> <div class="text-center md:text-right">
<p class="text-ecsess-200 mb-3 text-sm"> <p class="text-ecsess-200 mb-3 text-base">
Want to report an issue or <br /> Catch a bug or have an idea? <br />
contribute to the website? Let us know!
</p> </p>
<a <a
href="https://github.com/mcgill-ecsess/ecsess-site" href="https://github.com/mcgill-ecsess/ECSESS"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="bg-ecsess-800 hover:bg-ecsess-600 inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-semibold text-white transition-colors" class="bg-ecsess-800 hover:bg-ecsess-600 inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-semibold text-white transition-colors"
@@ -183,7 +175,7 @@
clip-rule="evenodd" clip-rule="evenodd"
/> />
</svg> </svg>
<span>GitHub Repo</span> <span>ECSESS on GitHub</span>
</a> </a>
</div> </div>
</div> </div>
@@ -194,8 +186,8 @@
<!-- Copyright --> <!-- Copyright -->
<div> <div>
<p class="text-ecsess-150 text-center text-sm"> <p class="text-ecsess-150 text-center text-sm">
Created by ECSESS with love {'<3'}. <br /> 🄯 ECSESS {year} under GNU General Public License v3.0. <br />
&copy; ECSESS {year}, under GNU General Public License v3.0. Designed with love {'<3'}.
</p> </p>
</div> </div>
</div> </div>

View File

@@ -1,16 +1,31 @@
<script> <script>
let { children = () => 'Section placeholder', black = false } = $props(); /**
* Props:
* - from/to: pass full Tailwind gradient color classes (e.g., 'from-ecsess-950', 'to-ecsess-800')
* - direction: Tailwind gradient direction suffix (e.g., 'to-b', 'to-r'), defaults to vertical
* - black: legacy toggle for solid background (kept for backward compatibility)
*/
let {
children = () => 'Section placeholder',
from = '',
to = '',
direction = 'to-b', // to bottom
black = false
} = $props();
let tailwindClasses = $state( const base =
'mx-auto flex min-h-[90vh] flex-col items-center justify-center gap-4 p-4 text-center text-ecsess-100' 'mx-auto flex min-h-[90vh] flex-col items-center justify-center gap-4 p-4 text-center text-ecsess-100';
);
if (black) { // Compute classes: prefer gradient when from/to provided; otherwise fallback to previous behavior
tailwindClasses += ' bg-ecsess-black'; let tailwindClasses = $state(base);
$effect(() => {
if (from && to) {
tailwindClasses = `${base} bg-gradient-${direction} ${from} ${to}`;
} else { } else {
// green background tailwindClasses = base + (black ? ' bg-ecsess-black' : ' bg-ecsess-800');
tailwindClasses += ' bg-ecsess-800';
} }
});
</script> </script>
<div class={tailwindClasses}> <div class={tailwindClasses}>

View File

@@ -20,7 +20,7 @@
<SeoMetaTags canonical={data.canonical} /> <SeoMetaTags canonical={data.canonical} />
<!-- ECSESS Introduction --> <!-- ECSESS Introduction -->
<Section> <Section from="from-ecsess-black" to="to-ecsess-900">
<div class="place-self-center md:grid md:grid-cols-1 md:gap-6 lg:grid-cols-3"> <div class="place-self-center md:grid md:grid-cols-1 md:gap-6 lg:grid-cols-3">
<div class="place-self-center md:place-content-around lg:col-span-1 lg:m-8"> <div class="place-self-center md:place-content-around lg:col-span-1 lg:m-8">
<div class="flex h-1/2 flex-col place-content-center text-center"> <div class="flex h-1/2 flex-col place-content-center text-center">
@@ -56,7 +56,7 @@
</Section> </Section>
<!-- Office Hours Calendar --> <!-- Office Hours Calendar -->
<Section black> <Section from="from-ecsess-900" to="to-ecsess-800">
<div class="w-full"> <div class="w-full">
<h1 id="office-hours">Office Hours</h1> <h1 id="office-hours">Office Hours</h1>
<OhSchedule allOhs={data.allOHs} /> <OhSchedule allOhs={data.allOHs} />
@@ -64,10 +64,11 @@
</Section> </Section>
<!-- Affiliated Clubs --> <!-- Affiliated Clubs -->
<AffiliatedClubs /> <Section from="from-ecsess-800" to="to-ecsess-950">
<AffiliatedClubs />
</Section>
<!-- FAQs and Sponsors --> <!-- FAQs and Sponsors -->
<Section> <Section from="from-ecsess-950" to="to-ecsess-black">
<div class="grid w-full max-w-[80vw] grid-cols-1 gap-12 lg:grid-cols-2 lg:gap-24"> <div class="grid w-full max-w-[80vw] grid-cols-1 gap-12 lg:grid-cols-2 lg:gap-24">
<div> <div>
<h1>FAQs</h1> <h1>FAQs</h1>