Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ bun.lock
# next.js
/.next/
/out/
.next/

# production
/build
Expand Down
100 changes: 68 additions & 32 deletions components/Achievements/Achievements.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,78 @@
import { Achievementlist } from '../../data';
import Hero from '../Hero/Hero';
import { useEffect, useRef } from 'react';
import styles from './Achievements.module.scss';
import Footer from '../Footer/Footer';

const Achievements = () => {
const bgRef = useRef(null);

useEffect(() => {
const handleScroll = () => {
if (!bgRef.current) return;
const scrollY = window.scrollY;
const maxShift = 120;
const progress = Math.min(
scrollY / (document.body.scrollHeight - window.innerHeight),
1
);
bgRef.current.style.transform = `translateY(-${progress * maxShift}px)`;
};
window.addEventListener('scroll', handleScroll, { passive: true });
return () => window.removeEventListener('scroll', handleScroll);
}, []);

return (
<>
<Hero
imgName={'achievements-hero.jpg'}
backgroundPosition={'center top'}
title={<>Achievements</>}
subtitleList={["What we're proud of!"]}
isHome={false}
/>
<div className={styles.achievements} id='is'>
{Achievementlist.map((achYear, idx) => {
return (
<div className={styles.achYear} key={`year_${idx}`}>
<h3>{achYear.year}</h3>
<div className={styles.achList}>
{achYear.achs.map((ach, idx) => {
return (
<div className={styles.ach} key={`achievement_${idx}`}>
<div
style={{
backgroundImage: `url("/static/images/${ach.imgName}")`,
}}
className={styles.achImg}
></div>
<div className={styles.achName}>{ach.name}</div>
</div>
);
})}
<div className={styles.pageWrapper}>
{/* Sticky parallax background */}
<div className={styles.stickyBg}>
<div
ref={bgRef}
className={styles.bgImage}
style={{
backgroundImage: `url('/static/images/sra_board_2026.png')`,
}}
/>
<div className={styles.bgOverlay} />
</div>

{/* Page content */}
<div className={styles.content}>
{/* Page header */}
<header className={styles.pageHeader}>
<p className={styles.eyebrow}>SRA VJTI</p>
<h1 className={styles.pageTitle}>Achievements</h1>
<p className={styles.pageSubtitle}>What we&apos;re proud of.</p>
</header>

{/* Year sections */}
<div className={styles.achievements}>
{Achievementlist.map((achYear, idx) => (
<section className={styles.achYear} key={`year_${idx}`}>
<div className={styles.yearLabel}>
<span className={styles.yearLine} />
<span className={styles.yearText}>{achYear.year}</span>
<span className={styles.yearLine} />
</div>
<div className={styles.achGrid}>
{achYear.achs.map((ach, i) => (
<div className={styles.achCard} key={`ach_${i}`}>
<div
className={styles.achImg}
style={{
backgroundImage: `url('/static/images/${ach.imgName}')`,
...(ach.imgPosition && { backgroundPosition: ach.imgPosition }),
}}
/>
<div className={styles.achName}>{ach.name}</div>
</div>
))}
</div>
</div>
);
})}
</section>
))}
</div>
<Footer />
</div>
</>
</div>
);
};

Expand Down
228 changes: 187 additions & 41 deletions components/Achievements/Achievements.module.scss
Original file line number Diff line number Diff line change
@@ -1,45 +1,191 @@
@import '../variables';
// ── Achievements page — Apple dark-mode theme ──────────────────────

.achYear {
$font-apple: 'SF Pro Display', 'SF Pro Text', -apple-system, BlinkMacSystemFont,
'Helvetica Neue', Helvetica, Arial, sans-serif;

// Wrapper keeps the sticky background contained
.pageWrapper {
position: relative;
background: #000;
min-height: 100vh;
}

// ── Background system ──────────────────────────────────────────────
.stickyBg {
position: sticky;
top: 0;
height: 100vh;
margin-bottom: -100vh;
z-index: 0;
overflow: hidden;
}

.bgImage {
position: absolute;
inset: 0;
width: 100%;
margin: 50px auto;
h3 {
text-align: center;
width: 40%;
margin: auto;
color: $light;
font-size: 1.8rem;
border-bottom: 2px solid $light;
padding: {
bottom: 10px;
}
}

.achList {
width: 100%;
padding: 1em;

display: flex;
justify-content: center;
flex-wrap: wrap;

.ach {
width: 250px;
height: 300px;
margin: 30px;
// background-color: rebeccapurple;
.achImg {
height: 70%;

background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
.achName {
padding-top: 10px;
height: 30%;
text-align: center;
}
}
height: calc(100% + 120px);
background-size: cover;
background-position: center top;
background-repeat: no-repeat;
will-change: transform;
}

.bgOverlay {
position: absolute;
inset: 0;
background: linear-gradient(
to bottom,
rgba(0, 0, 0, 0.55) 0%,
rgba(0, 0, 0, 0.45) 40%,
rgba(0, 0, 0, 0.65) 100%
);
}

// ── Content layer sits above the sticky background ─────────────────
.content {
position: relative;
z-index: 1;
background: rgba(0, 0, 0, 0.6);
}

// ── Page header ────────────────────────────────────────────────────
.pageHeader {
padding: 140px 40px 80px;
text-align: center;
background: transparent;

@media (max-width: 768px) {
padding: 120px 24px 60px;
}
}

.eyebrow {
font-family: $font-apple;
font-size: 12px;
font-weight: 600;
color: #6e6e73;
letter-spacing: 0.08em;
text-transform: uppercase;
margin: 0 0 16px;
}

.pageTitle {
font-family: $font-apple;
font-size: 56px;
font-weight: 700;
color: #f5f5f7;
letter-spacing: -0.003em;
line-height: 1.07;
text-shadow: 0 4px 24px rgba(0, 0, 0, 0.55);
margin: 0 0 20px;

@media (max-width: 768px) {
font-size: 36px;
}
}

.pageSubtitle {
font-family: $font-apple;
font-size: 20px;
font-weight: 400;
color: #a1a1a6;
margin: 0;

@media (max-width: 768px) {
font-size: 17px;
}
}

// ── Year sections ──────────────────────────────────────────────────
.achievements {
padding: 0 40px 120px;
max-width: 1400px;
margin: 0 auto;

@media (max-width: 850px) {
padding: 0 24px 80px;
}
}

.achYear {
margin-bottom: 72px;
}

.yearLabel {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 36px;
}

.yearLine {
flex: 1;
height: 1px;
background: rgba(255, 255, 255, 0.12);
}

.yearText {
font-family: $font-apple;
font-size: 18px;
font-weight: 600;
color: #6e6e73;
letter-spacing: 0.1em;
text-transform: uppercase;
white-space: nowrap;
}

// ── Card grid ──────────────────────────────────────────────────────
.achGrid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 24px;

@media (max-width: 1200px) {
grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 850px) {
grid-template-columns: repeat(2, 1fr);
}

@media (max-width: 480px) {
grid-template-columns: 1fr;
}
}

// ── Individual achievement card ────────────────────────────────────
.achCard {
border-radius: 10px;
overflow: hidden;
background: rgba(26, 26, 26, 0.6);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
transition: background 0.3s ease;
display: flex;
flex-direction: column;

&:hover {
background: rgba(26, 26, 26, 0.9);
}
}

.achImg {
width: 100%;
aspect-ratio: 4 / 3;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #0d0d0d;
}

.achName {
font-family: $font-apple;
font-size: 0.9rem;
font-weight: 500;
color: #f5f5f5;
letter-spacing: -0.003em;
text-align: center;
padding: 16px 14px 20px;
line-height: 1.45;
}
Loading