mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
feat(web): add Valentines Day theme to homepage
This commit is contained in:
parent
1da2b1c457
commit
76a13a1e87
6 changed files with 213 additions and 11 deletions
|
|
@ -70,3 +70,48 @@
|
|||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
|
||||
/* Valentine's Day Theme Animations */
|
||||
@keyframes heartbeat {
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
15% {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
30% {
|
||||
transform: scale(1);
|
||||
}
|
||||
45% {
|
||||
transform: scale(1.15);
|
||||
}
|
||||
60% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float-up {
|
||||
0% {
|
||||
transform: translateY(0) rotate(0deg);
|
||||
opacity: 0;
|
||||
}
|
||||
10% {
|
||||
opacity: 1;
|
||||
}
|
||||
90% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-100vh) rotate(360deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-heartbeat {
|
||||
animation: heartbeat 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-float-up {
|
||||
animation: float-up linear infinite;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,35 +7,81 @@ import {
|
|||
OptionOverviewSection,
|
||||
PillarsSection,
|
||||
UseExamplesSection,
|
||||
FloatingHearts,
|
||||
} from "@/components/homepage"
|
||||
import { EXTERNAL_LINKS } from "@/lib/constants"
|
||||
import { ArrowRight } from "lucide-react"
|
||||
import { ArrowRight, Heart } from "lucide-react"
|
||||
import { StructuredData } from "@/components/structured-data"
|
||||
|
||||
// Invalidate cache when a request comes in, at most once every hour.
|
||||
export const revalidate = 3600
|
||||
|
||||
// Check if current date is Valentine's season (Feb 1-15)
|
||||
function isValentinesSeason() {
|
||||
const now = new Date()
|
||||
const month = now.getMonth() // 0-indexed, so February is 1
|
||||
const day = now.getDate()
|
||||
return month === 1 && day >= 1 && day <= 15
|
||||
}
|
||||
|
||||
export default async function Home() {
|
||||
const isValentines = isValentinesSeason()
|
||||
|
||||
return (
|
||||
<>
|
||||
<StructuredData />
|
||||
<FloatingHearts />
|
||||
<section className="relative flex flex-col items-center overflow-hidden pt-20 pb-12 md:pt-32 md:pb-16">
|
||||
<div className="absolute inset-y-0 left-1/2 h-full w-full max-w-[1200px] -translate-x-1/2 z-1">
|
||||
<div className="absolute left-1/2 top-1/2 h-[400px] w-full -translate-x-1/2 -translate-y-1/2 rounded-full bg-violet-500/10 dark:bg-violet-700/20 blur-[140px]" />
|
||||
<div
|
||||
className={`absolute left-1/2 top-1/2 h-[400px] w-full -translate-x-1/2 -translate-y-1/2 rounded-full blur-[140px] ${
|
||||
isValentines
|
||||
? "bg-rose-500/15 dark:bg-rose-600/25"
|
||||
: "bg-violet-500/10 dark:bg-violet-700/20"
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
<div className="container relative z-10 mx-auto px-4 sm:px-6 lg:px-8 flex flex-col items-center text-center">
|
||||
<h1 className="text-3xl md:text-4xl font-bold tracking-tight text-foreground max-w-4xl mb-6">
|
||||
Your AI Software Engineering Team is here.
|
||||
<br />
|
||||
<span className="text-muted-foreground">Interactive in the IDE, autonomous in the cloud.</span>
|
||||
{isValentines ? (
|
||||
<>
|
||||
<span className="inline-flex items-center gap-2">
|
||||
Fall in{" "}
|
||||
<Heart className="inline size-8 md:size-10 text-rose-500 fill-rose-500 animate-heartbeat" />{" "}
|
||||
with coding again.
|
||||
</span>
|
||||
<br />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-pink-500 via-rose-500 to-red-500">
|
||||
Your AI pair that truly cares.
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
Your AI Software Engineering Team is here.
|
||||
<br />
|
||||
<span className="text-muted-foreground">
|
||||
Interactive in the IDE, autonomous in the cloud.
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</h1>
|
||||
<div className="mt-2 max-w-3xl text-lg text-muted-foreground mb-10 space-y-3">
|
||||
<p>
|
||||
Use the <strong className="text-nowrap">Roo Code Extension</strong> on your computer for
|
||||
full control, or delegate work to your{" "}
|
||||
<strong className="text-nowrap">Roo Code Cloud Agents</strong> from the web, Slack, Github
|
||||
or wherever your team is.
|
||||
</p>
|
||||
{isValentines ? (
|
||||
<p>
|
||||
This Valentine's season, let{" "}
|
||||
<strong className="text-rose-500 text-nowrap">Roo Code</strong> be your perfect coding
|
||||
companion. Use the <strong className="text-nowrap">Extension</strong> for hands-on
|
||||
collaboration, or let your <strong className="text-nowrap">Cloud Agents</strong> handle
|
||||
the heavy lifting while you focus on what you love.
|
||||
</p>
|
||||
) : (
|
||||
<p>
|
||||
Use the <strong className="text-nowrap">Roo Code Extension</strong> on your computer for
|
||||
full control, or delegate work to your{" "}
|
||||
<strong className="text-nowrap">Roo Code Cloud Agents</strong> from the web, Slack,
|
||||
Github or wherever your team is.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row gap-4 mb-16">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { getGitHubStars, getVSCodeDownloads } from "@/lib/stats"
|
||||
|
||||
import { NavBar, Footer } from "@/components/chromes"
|
||||
import { ValentinesBanner } from "@/components/homepage"
|
||||
|
||||
// Invalidate cache when a request comes in, at most once every hour.
|
||||
export const revalidate = 3600
|
||||
|
|
@ -10,6 +11,7 @@ export default async function Shell({ children }: { children: React.ReactNode })
|
|||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col bg-background text-foreground">
|
||||
<ValentinesBanner />
|
||||
<NavBar stars={stars} downloads={downloads} />
|
||||
<main className="flex-1">{children}</main>
|
||||
<Footer />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
"use client"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
interface FloatingHeart {
|
||||
id: number
|
||||
left: number
|
||||
size: number
|
||||
duration: number
|
||||
delay: number
|
||||
opacity: number
|
||||
}
|
||||
|
||||
export function FloatingHearts() {
|
||||
const [hearts, setHearts] = useState<FloatingHeart[]>([])
|
||||
const [isVisible, setIsVisible] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
// Check if we're in the Valentine's date range (Feb 1-15)
|
||||
const now = new Date()
|
||||
const month = now.getMonth() // 0-indexed, so February is 1
|
||||
const day = now.getDate()
|
||||
const isValentinesSeason = month === 1 && day >= 1 && day <= 15
|
||||
setIsVisible(isValentinesSeason)
|
||||
|
||||
if (!isValentinesSeason) return
|
||||
|
||||
// Generate random hearts
|
||||
const generatedHearts: FloatingHeart[] = Array.from({ length: 15 }, (_, i) => ({
|
||||
id: i,
|
||||
left: Math.random() * 100,
|
||||
size: 12 + Math.random() * 16,
|
||||
duration: 8 + Math.random() * 12,
|
||||
delay: Math.random() * 10,
|
||||
opacity: 0.1 + Math.random() * 0.2,
|
||||
}))
|
||||
setHearts(generatedHearts)
|
||||
}, [])
|
||||
|
||||
if (!isVisible || hearts.length === 0) return null
|
||||
|
||||
return (
|
||||
<div className="pointer-events-none fixed inset-0 z-0 overflow-hidden" aria-hidden="true">
|
||||
{hearts.map((heart) => (
|
||||
<div
|
||||
key={heart.id}
|
||||
className="absolute animate-float-up text-rose-500/50 dark:text-rose-400/30"
|
||||
style={{
|
||||
left: `${heart.left}%`,
|
||||
bottom: "-50px",
|
||||
fontSize: `${heart.size}px`,
|
||||
animationDuration: `${heart.duration}s`,
|
||||
animationDelay: `${heart.delay}s`,
|
||||
opacity: heart.opacity,
|
||||
}}>
|
||||
❤
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -12,3 +12,5 @@ export * from "./cloud-section"
|
|||
export * from "./ecosystem-section"
|
||||
export * from "./cta-section"
|
||||
export * from "./use-examples-section"
|
||||
export * from "./valentines-banner"
|
||||
export * from "./floating-hearts"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
"use client"
|
||||
|
||||
import { Heart, Sparkles } from "lucide-react"
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
export function ValentinesBanner() {
|
||||
const [isVisible, setIsVisible] = useState(true)
|
||||
|
||||
// Check if we're in the Valentine's date range (Feb 1-15)
|
||||
useEffect(() => {
|
||||
const now = new Date()
|
||||
const month = now.getMonth() // 0-indexed, so February is 1
|
||||
const day = now.getDate()
|
||||
// Show banner from Feb 1-15
|
||||
const isValentinesSeason = month === 1 && day >= 1 && day <= 15
|
||||
setIsVisible(isValentinesSeason)
|
||||
}, [])
|
||||
|
||||
if (!isVisible) return null
|
||||
|
||||
return (
|
||||
<div className="relative overflow-hidden bg-gradient-to-r from-pink-500 via-rose-500 to-red-500 py-2.5 text-white">
|
||||
{/* Animated sparkles background */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
{[...Array(6)].map((_, i) => (
|
||||
<Sparkles
|
||||
key={i}
|
||||
className="absolute animate-pulse text-white/30"
|
||||
style={{
|
||||
left: `${15 + i * 15}%`,
|
||||
top: `${20 + (i % 3) * 20}%`,
|
||||
animationDelay: `${i * 0.3}s`,
|
||||
transform: `scale(${0.6 + (i % 3) * 0.2})`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="container relative mx-auto flex items-center justify-center gap-3 px-4 text-center text-sm font-medium">
|
||||
<Heart className="size-4 animate-heartbeat fill-current" />
|
||||
<span>Happy Valentine's Day! Spread the love and build something amazing with Roo Code</span>
|
||||
<Heart className="size-4 animate-heartbeat fill-current" style={{ animationDelay: "0.5s" }} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue