Skip to content

Conversation

@katoue
Copy link

@katoue katoue commented Jan 26, 2026

Summary

  • Add scroll-triggered animations using Framer Motion to Homepage, Projects, and Team pages
  • Improve layout consistency across all pages with standardized spacing and container widths
  • Enhance card components with hover effects

Changes

New Components

  • /components/animations/FadeIn.jsx - Reusable scroll-triggered fade-in animation with direction (up/down/left/right), delay, and duration props
  • /components/animations/StaggerContainer.jsx - Container that automatically staggers children animations
  • /components/Section.jsx - Standardized section wrapper with consistent padding and max-width

Pages with Animations

  • Homepage - Hero elements fade from opposite sides, about section fades up, factboxes stagger in, recent projects animate on scroll, sponsor/company sections fade in
  • Projects index - Current and past project cards stagger in with fade animations
  • Team - Group titles fade in, member cards stagger in

Layout Improvements (All Pages)

  • Consistent section padding: py-16 lg:py-24 px-4 lg:px-6
  • Container max-width: max-w-screen-xl
  • Card gaps: gap-6 lg:gap-8
  • Heading margins: mb-6 lg:mb-8

Card Enhancements

  • projectCard - Added hover:scale-105 and hover:shadow-lg
  • sponsorCard - Added hover glow effect with hover:shadow-primary/20
  • companyCard - Consistent styling with sponsorCard

Test Plan

  • Verify homepage scroll animations work smoothly
  • Test project cards stagger animation on Projects page
  • Test team member cards stagger animation on Team page
  • Check card hover effects (scale and shadow)
  • Test responsive layouts at 640px, 768px, 1024px, 1280px breakpoints
  • Verify no animation jank/stutter on scroll

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds scroll-triggered animations and standardizes spacing/layout across multiple pages using Framer Motion wrappers and a shared Section component.

Changes:

  • Introduces reusable animation components (FadeIn, StaggerContainer) and a layout wrapper (Section).
  • Updates Home, Projects, Team, and other pages to use consistent section padding/container widths and add scroll/hover effects.
  • Adds framer-motion dependency to support the new animation behavior.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pages/team.jsx Adds fade-in heading/description and staggered member-card animations; updates spacing and hover effects.
pages/sponsors.jsx Updates section spacing/container width for sponsors intro copy.
pages/projects/index.jsx Adds fade-in headings and staggered project card animations; standardizes spacing.
pages/projects/[...slug].jsx Refines project aggregation logic and adjusts writeup page layout/image presentation.
pages/links.jsx Standardizes spacing and adds hover/transition effects to link cards.
pages/join.jsx Converts content blocks into standardized padded sections and updates spacing/gaps.
pages/index.jsx Adds scroll-triggered animations throughout homepage and adopts new Section wrapper for sponsor/company sections.
pages/contact.jsx Renames component and standardizes layout spacing; adds hover scaling for contact links.
pages/calendar.jsx Standardizes calendar page spacing and layout structure.
components/sponsorCard.jsx Enhances sponsor cards with transitions, hover shadow, and image hover scale.
components/projectCard.jsx Enhances project cards with transitions, hover scale/shadow, and link hover transitions.
components/companyCard.jsx Aligns company card styling with sponsor cards (hover shadow/scale).
components/animations/StaggerContainer.jsx New reusable stagger-on-scroll wrapper component (Framer Motion).
components/animations/FadeIn.jsx New reusable fade-in-on-scroll wrapper component (Framer Motion).
components/Section.jsx New standardized section wrapper with optional animated title/subtitle.
package.json Adds framer-motion dependency.
package-lock.json Locks framer-motion and its transitive dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +29 to +38
<div ref={ref} className={className}>
{Children.map(children, (child, index) => {
if (!isValidElement(child)) return child;

return (
<motion.div
initial={{ opacity: 0, x: offset.x, y: offset.y }}
animate={
isInView
? { opacity: 1, x: 0, y: 0 }
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StaggerContainer wraps each child in an unstyled motion.div. When the container is used with display: flex/flex-wrap, the wrapper becomes the flex item, so width utilities on the child component (e.g. w-full sm:w-60 in cards) no longer affect layout and can cause items to shrink-to-content.

Consider adding an itemClassName/itemStyle prop (or similar) applied to the wrapper motion.div, with a sensible default that preserves typical card sizing, and update call sites to pass the intended item sizing classes when needed.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +12
export default function Section({
children,
title,
subtitle,
background = "",
className = "",
titleClassName = "",
animate = true,
animateTitle = true,
}) {
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

animate is exposed as a prop but never used. This makes the Section API misleading (callers can’t actually disable the FadeIn behavior except via animateTitle). Either remove animate or implement it (e.g., use it to disable all FadeIn wrappers / animated behavior in this component).

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +44
<div className="py-16 lg:py-24 px-4 lg:px-6 max-w-screen-xl mx-auto">
<Markdown className="markdown">{content}</Markdown>
{images.map((img, idx) => (
<Image key={idx} src={img} width={500} height={500} alt={title} />
))}
<div className="mt-6 lg:mt-8 flex flex-wrap gap-6 lg:gap-8">
{images.map((img, idx) => (
<Image key={idx} src={img} width={500} height={500} alt={title} className="rounded-lg" />
))}
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This page computes basePath from useRouter() but doesn’t use it anywhere. If images are meant to work when the site is deployed under a Next.js basePath, the src values (currently absolute like /images/projects/...) should be prefixed; otherwise remove the unused basePath variable to avoid lint/build failures.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant