From d16aafe3cdec263029dc26a94d7f54a3962b82fd Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 9 May 2025 10:41:09 -0400 Subject: [PATCH 1/5] Progress re-adding news --- .../design-system/src/lib/Components/HomeHeader/index.tsx | 7 ++++--- src/ui/design-system/src/lib/Pages/HomePage/index.tsx | 5 ++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ui/design-system/src/lib/Components/HomeHeader/index.tsx b/src/ui/design-system/src/lib/Components/HomeHeader/index.tsx index 3420828ea1..e800af8409 100644 --- a/src/ui/design-system/src/lib/Components/HomeHeader/index.tsx +++ b/src/ui/design-system/src/lib/Components/HomeHeader/index.tsx @@ -7,12 +7,13 @@ export const HomeHeader: React.FC = () => {
-
+
-
+ {/* TODO: Add back in after iteration */} + {/*
-
+
*/}
diff --git a/src/ui/design-system/src/lib/Pages/HomePage/index.tsx b/src/ui/design-system/src/lib/Pages/HomePage/index.tsx index c1d1eda4dd..84de77b09c 100644 --- a/src/ui/design-system/src/lib/Pages/HomePage/index.tsx +++ b/src/ui/design-system/src/lib/Pages/HomePage/index.tsx @@ -10,7 +10,7 @@ import PageBackground from '../shared/PageBackground'; import ActionCardGrid from '@site/src/components/ActionCardGrid'; import { buildGridData } from './GridData/BuildGridData'; import { growGridData } from './GridData/GrowGridData'; -// import { HomeHeader } from '../../Components/HomeHeader'; +import { HomeHeader } from '../../Components/HomeHeader'; export type HomePageProps = SocialLinksSignupProps & { concepts?: TutorialCardProps[]; @@ -21,8 +21,7 @@ export type HomePageProps = SocialLinksSignupProps & { const HomePage = ({ discordUrl, githubUrl }: HomePageProps): JSX.Element => { return ( - {/* TODO: Add back in after iteration */} - {/* */} + From 2dc97aaf4d53d239ae0392c97e284d2da1ed3fac Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 9 May 2025 16:31:14 -0400 Subject: [PATCH 2/5] Tweak and add cards for current events --- .../src/lib/Components/NewsCarousel/index.tsx | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx b/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx index 19675cbd46..1f8b2bb08f 100644 --- a/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx +++ b/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx @@ -13,31 +13,49 @@ interface CarouselCard { const CAROUSEL_CARDS: CarouselCard[] = [ { - heading: 'We got a castle!', - description: 'Apply to be a Flow Scholar to work alongside our team, join us at the Flow Hacker Castle, and represent the Flow community—all on us!', + heading: 'Get the newsletter!', + description: 'We send out a newsletter every week with the latest news for Flow developers. Sign up to get it in your inbox!', iconColor: 'green', cardColor: 'black', - href: 'https://x.com/flow_blockchain/status/1880405924407587173', + href: 'https://break.link', variant: 'horizontal' as const, - // icon: 'flow-castle' + icon: 'learn' }, { - heading: 'Cadence Tutorials', - description: 'We\'ve updated the first set of Cadence tutorials to be more approachable. Let us know what you think!', - iconColor: 'blue', + heading: 'May the Flow be with You!', + description: 'Join us for a month-long vibe coding challenge on Flow! Starting May 4th, participate in our four themed weeks.', + iconColor: 'green', + cardColor: 'black', + href: '/ecosystem/Hackathons%20and%20Events/may-the-flow-be-with-you', + variant: 'horizontal' as const, + icon: 'vcs-&-funds' + }, + { + heading: 'Web3 Founder x VC meetup', + description: 'Calling all Web3 founders from Consensus! 🧠 Join us for an epic event of networking, learning, and fun.', + iconColor: 'green', cardColor: 'black', - href: 'https://cadence-lang.org/docs/tutorial/first-steps', + href: 'https://lu.ma/vicz07zu', variant: 'horizontal' as const, - icon: 'tutorials' + icon: 'vcs-&-funds' }, { - heading: 'Flow is Live on Axelar', - description: '"With this integration, Flow users, builders and dApps get access to best-in-class interoperability, opening up liquidity from 70+ chains 🦾 🤝"', + heading: 'ETH Global Prague', + description: 'Earn up to $10,000 in prizes for building on Flow at one of the biggest hackathons in Europe!', iconColor: 'purple', cardColor: 'black', - href: 'https://x.com/axelar/status/1882066175175360998', + href: 'https://ethglobal.com/events/prague/prizes/flow', + variant: 'horizontal' as const, + icon: 'grants' + }, + { + heading: 'EthCC Cannes', + description: 'Earn up to $20,000 in prizes at the largest annual Ethereum conference in Europe!', + iconColor: 'blue', + cardColor: 'black', + href: 'https://ethglobal.com/events/cannes/prizes/flow', variant: 'horizontal' as const, - icon: 'cross-vm-bridge' + icon: 'grants' }, ]; From f2c72b3f585633903b5823151cf9f50b6c1ee147 Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 9 May 2025 17:40:03 -0400 Subject: [PATCH 3/5] Partial: Carousel works but animation is broken --- .../src/lib/Components/NewsCarousel/index.tsx | 54 ++++++++++++++++--- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx b/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx index 1f8b2bb08f..3655f940ce 100644 --- a/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx +++ b/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx @@ -61,32 +61,65 @@ const CAROUSEL_CARDS: CarouselCard[] = [ export const NewsCarousel: React.FC = () => { const [currentIndex, setCurrentIndex] = useState(0); + const [animating, setAnimating] = useState(false); + const [direction, setDirection] = useState<'left' | 'right' | null>(null); const nextSlide = () => { - setCurrentIndex((prevIndex) => (prevIndex + 1) % CAROUSEL_CARDS.length); + if (animating) return; + setDirection('right'); + setAnimating(true); + setTimeout(() => { + setCurrentIndex((prevIndex) => (prevIndex + 1) % CAROUSEL_CARDS.length); + setAnimating(false); + setDirection(null); + }, 400); }; const prevSlide = () => { - setCurrentIndex((prevIndex) => - prevIndex - 1 < 0 ? CAROUSEL_CARDS.length - 1 : prevIndex - 1 - ); + if (animating) return; + setDirection('left'); + setAnimating(true); + setTimeout(() => { + setCurrentIndex((prevIndex) => + prevIndex - 1 < 0 ? CAROUSEL_CARDS.length - 1 : prevIndex - 1 + ); + setAnimating(false); + setDirection(null); + }, 400); }; const getVisibleCards = () => { if (CAROUSEL_CARDS.length < 2) return [CAROUSEL_CARDS[0]]; - const secondIndex = (currentIndex + 1) % CAROUSEL_CARDS.length; return [CAROUSEL_CARDS[currentIndex], CAROUSEL_CARDS[secondIndex]]; }; + // Animation classes + const getCardClass = (index: number) => { + if (!animating) return 'transition-transform duration-400'; + if (direction === 'right') { + // Slide out to right, slide in from left + return index === 0 + ? 'transition-transform duration-400 transform translate-x-full' + : 'transition-transform duration-400 transform -translate-x-full'; + } else if (direction === 'left') { + // Slide out to left, slide in from right + return index === 0 + ? 'transition-transform duration-400 transform -translate-x-full' + : 'transition-transform duration-400 transform translate-x-full'; + } + return 'transition-transform duration-400'; + }; + return (
{/* Navigation Buttons */} -
+
{/* Cards Grid */} -
+
{getVisibleCards().map((card, index) => ( -
+
Date: Thu, 22 May 2025 16:39:27 -0300 Subject: [PATCH 4/5] Redo logic for carousel, it's state management and transition effect --- .../src/lib/Components/NewsCarousel/index.tsx | 270 ++++++++++++------ 1 file changed, 188 insertions(+), 82 deletions(-) diff --git a/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx b/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx index 3655f940ce..05afa3a66c 100644 --- a/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx +++ b/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import ActionCard from '@site/src/components/ActionCard'; interface CarouselCard { @@ -60,66 +60,126 @@ const CAROUSEL_CARDS: CarouselCard[] = [ ]; export const NewsCarousel: React.FC = () => { - const [currentIndex, setCurrentIndex] = useState(0); - const [animating, setAnimating] = useState(false); - const [direction, setDirection] = useState<'left' | 'right' | null>(null); + const [activeIndex, setActiveIndex] = useState(0); + const [isTransitioning, setIsTransitioning] = useState(false); + const [cardsToShow, setCardsToShow] = useState(1); + const totalCards = CAROUSEL_CARDS.length; + // Calculate maxIndex properly to prevent empty segments + const maxIndex = Math.max(0, totalCards - cardsToShow); - const nextSlide = () => { - if (animating) return; - setDirection('right'); - setAnimating(true); - setTimeout(() => { - setCurrentIndex((prevIndex) => (prevIndex + 1) % CAROUSEL_CARDS.length); - setAnimating(false); - setDirection(null); - }, 400); - }; + // Initialize cardsToShow based on screen width + useEffect(() => { + const updateCardsToShow = () => { + setCardsToShow(window.innerWidth >= 1024 ? 2 : 1); + }; + + updateCardsToShow(); + window.addEventListener('resize', updateCardsToShow); + return () => window.removeEventListener('resize', updateCardsToShow); + }, []); - const prevSlide = () => { - if (animating) return; - setDirection('left'); - setAnimating(true); - setTimeout(() => { - setCurrentIndex((prevIndex) => - prevIndex - 1 < 0 ? CAROUSEL_CARDS.length - 1 : prevIndex - 1 - ); - setAnimating(false); - setDirection(null); - }, 400); - }; + // Handle automatic sliding + useEffect(() => { + const timer = setInterval(() => { + if (!isTransitioning) { + handleNext(); + } + }, 5000); // Auto slide every 5 seconds + + return () => clearInterval(timer); + }, [activeIndex, isTransitioning]); - const getVisibleCards = () => { - if (CAROUSEL_CARDS.length < 2) return [CAROUSEL_CARDS[0]]; - const secondIndex = (currentIndex + 1) % CAROUSEL_CARDS.length; - return [CAROUSEL_CARDS[currentIndex], CAROUSEL_CARDS[secondIndex]]; - }; + const handleNext = useCallback(() => { + if (isTransitioning) return; + + setIsTransitioning(true); + + // Loop back to beginning if at the end + if (activeIndex >= maxIndex) { + setActiveIndex(0); + } else { + setActiveIndex(prev => prev + 1); + } + + setTimeout(() => { + setIsTransitioning(false); + }, 600); + }, [activeIndex, isTransitioning, maxIndex]); - // Animation classes - const getCardClass = (index: number) => { - if (!animating) return 'transition-transform duration-400'; - if (direction === 'right') { - // Slide out to right, slide in from left - return index === 0 - ? 'transition-transform duration-400 transform translate-x-full' - : 'transition-transform duration-400 transform -translate-x-full'; - } else if (direction === 'left') { - // Slide out to left, slide in from right - return index === 0 - ? 'transition-transform duration-400 transform -translate-x-full' - : 'transition-transform duration-400 transform translate-x-full'; + const handlePrev = useCallback(() => { + if (isTransitioning) return; + + setIsTransitioning(true); + + // Loop to the end if at the beginning + if (activeIndex <= 0) { + setActiveIndex(maxIndex); + } else { + setActiveIndex(prev => prev - 1); } - return 'transition-transform duration-400'; - }; + + setTimeout(() => { + setIsTransitioning(false); + }, 600); + }, [activeIndex, isTransitioning, maxIndex]); + + const handleDotClick = useCallback((index: number) => { + if (isTransitioning || index === activeIndex) return; + + setIsTransitioning(true); + setActiveIndex(index); + + setTimeout(() => { + setIsTransitioning(false); + }, 600); + }, [activeIndex, isTransitioning]); return ( -
+
+ {/* Card Container */} +
+
+ {CAROUSEL_CARDS.map((card, index) => ( +
+ { + if (card.href.startsWith('https://')) { + window.open(card.href, '_blank'); + } else { + window.location.href = card.href; + } + }} + /> +
+ ))} +
+
+ {/* Navigation Buttons */} -
+
- {/* Cards Grid */} -
- {getVisibleCards().map((card, index) => ( -
+ + + {/* Dots indicator for mobile */} +
+ {Array.from({ length: maxIndex + 1 }).map((_, index) => ( +
+ ))} +
+ + +
+ + {/* Desktop progress indicator */} +
+ {Array.from({ length: maxIndex + 1 }).map((_, index) => ( +
From 09cc8c30148f53458acb2d3c4511003e287e018e Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Thu, 29 May 2025 10:38:16 -0400 Subject: [PATCH 5/5] Update cards --- .../src/lib/Components/NewsCarousel/index.tsx | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx b/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx index 05afa3a66c..9340798e13 100644 --- a/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx +++ b/src/ui/design-system/src/lib/Components/NewsCarousel/index.tsx @@ -17,28 +17,19 @@ const CAROUSEL_CARDS: CarouselCard[] = [ description: 'We send out a newsletter every week with the latest news for Flow developers. Sign up to get it in your inbox!', iconColor: 'green', cardColor: 'black', - href: 'https://break.link', + href: 'https://e.customeriomail.com/manage_subscription_preferences/dgTdoQoDAI7HAY3HAQGWxJT9wbM-Af61EgxuM6E=', variant: 'horizontal' as const, icon: 'learn' }, { heading: 'May the Flow be with You!', - description: 'Join us for a month-long vibe coding challenge on Flow! Starting May 4th, participate in our four themed weeks.', + description: 'We are wrapping up our month-long vibe coding challenge on Flow! Check out the winners, or submit for the last week!', iconColor: 'green', cardColor: 'black', href: '/ecosystem/Hackathons%20and%20Events/may-the-flow-be-with-you', variant: 'horizontal' as const, icon: 'vcs-&-funds' }, - { - heading: 'Web3 Founder x VC meetup', - description: 'Calling all Web3 founders from Consensus! 🧠 Join us for an epic event of networking, learning, and fun.', - iconColor: 'green', - cardColor: 'black', - href: 'https://lu.ma/vicz07zu', - variant: 'horizontal' as const, - icon: 'vcs-&-funds' - }, { heading: 'ETH Global Prague', description: 'Earn up to $10,000 in prizes for building on Flow at one of the biggest hackathons in Europe!',