Skip to content
Merged
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
20 changes: 20 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,21 @@ const LatestContentPreview = dynamic(() => import("@/components/home/LatestConte
ssr: false
});

// New: SponsorsSection on Home
const SponsorsSection = dynamic(() => import("@/components/home/SponsorsSection").then(mod => ({ default: mod.SponsorsSection })), {
loading: () => (
<div className="py-16">
<div className="container px-4 mx-auto">
<div className="animate-pulse">
<div className="h-8 bg-gray-200 rounded w-1/3 mx-auto mb-4"></div>
<div className="h-4 bg-gray-200 rounded w-1/2 mx-auto"></div>
</div>
</div>
</div>
),
ssr: false
});

const Footer = dynamic(() => import("@/components/footer"), {
loading: () => (
<footer className="border-t border-border/40 bg-gradient-to-b from-background/95 via-background to-background/95">
Expand Down Expand Up @@ -89,6 +104,11 @@ export default function Home() {
<CommunitySpotlight />
</Suspense>

{/* New: Sponsors Section on Home */}
<Suspense fallback={<div className="py-16"><div className="container px-4 mx-auto"><div className="animate-pulse"><div className="h-8 bg-gray-200 rounded w-1/3 mx-auto mb-4"></div><div className="h-4 bg-gray-200 rounded w-1/2 mx-auto"></div></div></div></div>}>
<SponsorsSection />
</Suspense>

<Suspense fallback={<div className="py-24"><div className="container px-4 mx-auto"><div className="animate-pulse"><div className="h-8 bg-gray-200 rounded w-1/3 mx-auto mb-4"></div><div className="h-4 bg-gray-200 rounded w-1/2 mx-auto"></div></div></div></div>}>
<LatestContentPreview />
</Suspense>
Expand Down
234 changes: 234 additions & 0 deletions components/home/SponsorsSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
"use client";

import { motion } from "framer-motion";
import { Handshake } from "lucide-react";
import Image from "next/image";

const sponsors = [
{
name: "Webytes",
title: "Community Engagement Partner",
logo: "/images/sponsors/webytes.png",
link: "https://www.webytes.club/"
},
{
name: "GeeksforGeeks",
title: "Knowledge & Learning Partner",
logo: "/images/sponsors/geekforgeeks.png",
link: "https://www.geeksforgeeks.org/"
},
{
name: "GeeksforGeeks Student Chapter- Chandigarh University",
title: "Community Engagement Partner",
logo: "/images/sponsors/studentchaptercu.png",
link: "https://www.linkedin.com/company/gfgstudentchaptercu/"
},
{
name: "Alexa Developer Community- Chandigarh University",
title: "Community Engagement Partner",
logo: "/images/sponsors/alexadevcommunity.png",
link: "https://www.linkedin.com/company/alexa-developer-community-cu/"
},
{
name: "Innovxus",
title: "Community Partner",
logo: "/images/sponsors/Innovxus.png",
link: "https://www.innovxus.com/"
},
{
name: "Rotaract - Chandigarh University",
title: "Community Engagement Partner",
logo: "/images/sponsors/rotaract.png",
link: "https://www.instagram.com/rotaract.cu/"
},
{
name: "Unstop",
title: "Technology Partner",
logo: "/images/sponsors/unstop.png",
link: "https://unstop.com/"
},
{
name: "Code Crafters",
title: "Upskilling Partner",
logo: "/images/sponsors/codecrafter.png",
link: "https://codecrafters.io/"
},
];

export function SponsorsSection() {
return (
<section className="py-20 relative overflow-hidden">
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,rgba(99,102,241,0.05),transparent_70%)]"></div>
<div className="container px-4 mx-auto relative z-10">
<div className="max-w-4xl mx-auto space-y-12">
<motion.div
className="text-center space-y-6"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
>
<div className="flex flex-col items-center justify-center gap-4">
<button className="bg-slate-800 no-underline group relative shadow-2xl shadow-zinc-900 rounded-full p-px text-sm font-semibold leading-6 text-white inline-block cursor-default">
<span className="absolute inset-0 overflow-hidden rounded-full">
<span className="absolute inset-0 rounded-full bg-[image:radial-gradient(75%_100%_at_50%_0%,rgba(56,189,248,0.6)_0%,rgba(56,189,248,0)_75%)] opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</span>
<div className="relative flex space-x-2 items-center z-10 rounded-full bg-zinc-950 py-0.5 px-4 ring-1 ring-white/10">
<span>Our Sponsors</span>
<span>
<Handshake className="w-3 h-3" />
</span>
</div>
<span className="absolute -bottom-0 left-[1.125rem] h-px w-[calc(100%-2.25rem)] bg-gradient-to-r from-emerald-400/0 via-emerald-400/90 to-emerald-400/0 transition-opacity duration-500 group-hover:opacity-40" />
</button>
</div>
Comment on lines +71 to +84
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Non-interactive “button” hurts accessibility; use a non-focusable element.

This badge is decorative and not clickable. A is focusable and announced as interactive.

Apply:

-              <button className="bg-slate-800 no-underline group relative shadow-2xl shadow-zinc-900 rounded-full p-px text-sm font-semibold leading-6 text-white inline-block cursor-default">
+              <div aria-hidden="true" className="bg-slate-800 no-underline group relative shadow-2xl shadow-zinc-900 rounded-full p-px text-sm font-semibold leading-6 text-white inline-block">-              </button>
+              </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="flex flex-col items-center justify-center gap-4">
<button className="bg-slate-800 no-underline group relative shadow-2xl shadow-zinc-900 rounded-full p-px text-sm font-semibold leading-6 text-white inline-block cursor-default">
<span className="absolute inset-0 overflow-hidden rounded-full">
<span className="absolute inset-0 rounded-full bg-[image:radial-gradient(75%_100%_at_50%_0%,rgba(56,189,248,0.6)_0%,rgba(56,189,248,0)_75%)] opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</span>
<div className="relative flex space-x-2 items-center z-10 rounded-full bg-zinc-950 py-0.5 px-4 ring-1 ring-white/10">
<span>Our Sponsors</span>
<span>
<Handshake className="w-3 h-3" />
</span>
</div>
<span className="absolute -bottom-0 left-[1.125rem] h-px w-[calc(100%-2.25rem)] bg-gradient-to-r from-emerald-400/0 via-emerald-400/90 to-emerald-400/0 transition-opacity duration-500 group-hover:opacity-40" />
</button>
</div>
<div className="flex flex-col items-center justify-center gap-4">
<div aria-hidden="true" className="bg-slate-800 no-underline group relative shadow-2xl shadow-zinc-900 rounded-full p-px text-sm font-semibold leading-6 text-white inline-block">
<span className="absolute inset-0 overflow-hidden rounded-full">
<span className="absolute inset-0 rounded-full bg-[image:radial-gradient(75%_100%_at_50%_0%,rgba(56,189,248,0.6)_0%,rgba(56,189,248,0)_75%)] opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</span>
<div className="relative flex space-x-2 items-center z-10 rounded-full bg-zinc-950 py-0.5 px-4 ring-1 ring-white/10">
<span>Our Sponsors</span>
<span>
<Handshake className="w-3 h-3" />
</span>
</div>
<span className="absolute -bottom-0 left-[1.125rem] h-px w-[calc(100%-2.25rem)] bg-gradient-to-r from-emerald-400/0 via-emerald-400/90 to-emerald-400/0 transition-opacity duration-500 group-hover:opacity-40" />
</div>
</div>
🤖 Prompt for AI Agents
In components/home/SponsorsSection.tsx around lines 71-84, the badge is
implemented as a <button> which is focusable and exposed as interactive though
it is decorative; replace the <button> with a non-interactive element (e.g.,
<div> or <span>) keeping the same className and structure, remove any
button-specific semantics, and mark it decorative with aria-hidden="true" so it
is not announced or focusable by assistive tech (ensure no tabIndex is set).

<h2 className="text-3xl md:text-4xl font-bold">
Proudly Supported by{" "}
<span className="gradient-text">Industry Leaders</span>
</h2>
<p className="text-xl text-muted-foreground">
We&apos;re grateful for the support of these amazing companies who share our vision for accessible coding education.
</p>
</motion.div>

<div className="relative w-full overflow-hidden">
<div
className="flex animate-scroll gap-8 py-4"
style={{ minWidth: `${sponsors.length * 2 * 332}px` }}
>
{sponsors.map((sponsor, idx) => (
sponsor.link ? (
<a
key={`first-${idx}`}
href={sponsor.link}
target="_blank"
rel="noopener noreferrer"
className="no-underline"
>
<motion.div
className="flex-shrink-0 w-[300px] h-[200px] rounded-xl border border-primary/10 bg-background/50 backdrop-blur-sm p-2 flex flex-col items-center justify-center gap-4 hover:border-primary/20 transition-all duration-300 hover:shadow-lg group"
whileHover={{ y: -5 }}
>
<div className={"relative w-full h-48 flex items-center justify-center"}>
<Image
src={sponsor.logo}
alt={sponsor.name}
fill
className={
sponsor.name === "Unstop"
? "object-contain p-4"
: sponsor.name === "Code Crafters"
? "object-contain w-32 h-16 mx-auto"
: sponsor.name === "Innovxus"
? "object-contain w-24 h-10 mx-auto flex items-center justify-center"
: "object-cover"
}
/>
Comment on lines +112 to +126
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Next/Image: avoid mixing fill with width/height utility classes.

When using fill, width/height classes like w-32 h-16 are ignored/conflict. Also, using object-cover may crop logos.

  • Use consistent object-contain and padding for all logos.
  • Provide sizes="300px" to improve image selection.
    Apply:
-                        <Image
+                        <Image
                           src={sponsor.logo}
                           alt={sponsor.name}
-                          fill
-                          className={
-                            sponsor.name === "Unstop"
-                              ? "object-contain p-4"
-                              : sponsor.name === "Code Crafters"
-                              ? "object-contain w-32 h-16 mx-auto"
-                              : sponsor.name === "Innovxus"
-                              ? "object-contain w-24 h-10 mx-auto flex items-center justify-center"
-                              : "object-cover"
-                          }
+                          fill
+                          sizes="300px"
+                          className="object-contain p-4"
                         />

If you need per-brand tweaks, adjust the wrapping container (add extra padding) rather than overriding Image width/height.

Also applies to: 140-154, 177-191, 205-219

🤖 Prompt for AI Agents
In components/home/SponsorsSection.tsx around lines 112-126 (also apply same
pattern at 140-154, 177-191, 205-219): the Image components use Next/Image with
the fill prop while conditionally applying width/height utility classes and
object-cover, which conflict with fill and can crop logos. Replace per-brand
width/height utilities on the Image with a consistent object-contain and
optional padding class, move any size/spacing tweaks into the wrapping div
(adjust padding/margins or set explicit width/height on the wrapper), and add
sizes="300px" to the Image props so the browser can pick an appropriate src;
ensure no width/height Tailwind classes remain on Image when using fill.

</div>
<div className="text-center">
<h3 className="font-semibold text-lg">{sponsor.name}</h3>
<p className="text-sm text-muted-foreground">{sponsor.title}</p>
</div>
</motion.div>
</a>
) : (
<motion.div
key={`first-${idx}`}
className="flex-shrink-0 w-[300px] h-[200px] rounded-xl border border-primary/10 bg-background/50 backdrop-blur-sm p-2 flex flex-col items-center justify-center gap-4 hover:border-primary/20 transition-all duration-300 hover:shadow-lg group"
whileHover={{ y: -5 }}
>
<div className={"relative w-full h-48 flex items-center justify-center"}>
<Image
src={sponsor.logo}
alt={sponsor.name}
fill
className={
sponsor.name === "Unstop"
? "object-contain p-4"
: sponsor.name === "Code Crafters"
? "object-contain w-32 h-16 mx-auto"
: sponsor.name === "Innovxus"
? "object-contain w-24 h-10 mx-auto flex items-center justify-center"
: "object-cover"
}
/>
</div>
<div className="text-center">
<h3 className="font-semibold text-lg">{sponsor.name}</h3>
<p className="text-sm text-muted-foreground">{sponsor.title}</p>
</div>
</motion.div>
)
))}

{sponsors.map((sponsor, idx) => (
sponsor.link ? (
<a
key={`second-${idx}`}
href={sponsor.link}
target="_blank"
rel="noopener noreferrer"
className="no-underline"
>
<motion.div
className="flex-shrink-0 w-[300px] h-[200px] rounded-xl border border-primary/10 bg-background/50 backdrop-blur-sm p-2 flex flex-col items-center justify-center gap-4 hover:border-primary/20 transition-all duration-300 hover:shadow-lg group"
whileHover={{ y: -5 }}
>
<div className={"relative w-full h-48 flex items-center justify-center"}>
<Image
src={sponsor.logo}
alt={sponsor.name}
fill
className={
sponsor.name === "Unstop"
? "object-contain p-4"
: sponsor.name === "Code Crafters"
? "object-contain w-32 h-16 mx-auto"
: sponsor.name === "Innovxus"
? "object-contain w-24 h-10 mx-auto flex items-center justify-center"
: "object-cover"
}
/>
</div>
<div className="text-center">
<h3 className="font-semibold text-lg">{sponsor.name}</h3>
<p className="text-sm text-muted-foreground">{sponsor.title}</p>
</div>
</motion.div>
</a>
) : (
<motion.div
key={`second-${idx}`}
className="flex-shrink-0 w-[300px] h-[200px] rounded-xl border border-primary/10 bg-background/50 backdrop-blur-sm p-2 flex flex-col items-center justify-center gap-4 hover:border-primary/20 transition-all duration-300 hover:shadow-lg group"
whileHover={{ y: -5 }}
>
<div className={"relative w-full h-48 flex items-center justify-center"}>
<Image
src={sponsor.logo}
alt={sponsor.name}
fill
className={
sponsor.name === "Unstop"
? "object-contain p-4"
: sponsor.name === "Code Crafters"
? "object-contain w-32 h-16 mx-auto"
: sponsor.name === "Innovxus"
? "object-contain w-24 h-10 mx-auto flex items-center justify-center"
: "object-cover"
}
/>
</div>
<div className="text-center">
<h3 className="font-semibold text-lg">{sponsor.name}</h3>
<p className="text-sm text-muted-foreground">{sponsor.title}</p>
</div>
</motion.div>
)
))}
Comment on lines +164 to +227
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Duplicate strip should be hidden from screen readers.

The second mapping is for continuous scrolling only; it repeats content for AT.

Apply aria-hidden on duplicate items:

-                  <a
+                  <a
+                    aria-hidden="true"
                     key={`second-${idx}`}
                     href={sponsor.link}
                     target="_blank"
                     rel="noopener noreferrer"
                     className="no-underline"
                   >
-                  <motion.div
+                  <motion.div
+                    aria-hidden="true"
                     key={`second-${idx}`}
                     className="flex-shrink-0 w-[300px] h-[200px] rounded-xl border border-primary/10 bg-background/50 backdrop-blur-sm p-2 flex flex-col items-center justify-center gap-4 hover:border-primary/20 transition-all duration-300 hover:shadow-lg group"
                     whileHover={{ y: -5 }}
                   >

Do the same for the non-link branch within the duplicate set.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{sponsors.map((sponsor, idx) => (
sponsor.link ? (
<a
key={`second-${idx}`}
href={sponsor.link}
target="_blank"
rel="noopener noreferrer"
className="no-underline"
>
<motion.div
className="flex-shrink-0 w-[300px] h-[200px] rounded-xl border border-primary/10 bg-background/50 backdrop-blur-sm p-2 flex flex-col items-center justify-center gap-4 hover:border-primary/20 transition-all duration-300 hover:shadow-lg group"
whileHover={{ y: -5 }}
>
<div className={"relative w-full h-48 flex items-center justify-center"}>
<Image
src={sponsor.logo}
alt={sponsor.name}
fill
className={
sponsor.name === "Unstop"
? "object-contain p-4"
: sponsor.name === "Code Crafters"
? "object-contain w-32 h-16 mx-auto"
: sponsor.name === "Innovxus"
? "object-contain w-24 h-10 mx-auto flex items-center justify-center"
: "object-cover"
}
/>
</div>
<div className="text-center">
<h3 className="font-semibold text-lg">{sponsor.name}</h3>
<p className="text-sm text-muted-foreground">{sponsor.title}</p>
</div>
</motion.div>
</a>
) : (
<motion.div
key={`second-${idx}`}
className="flex-shrink-0 w-[300px] h-[200px] rounded-xl border border-primary/10 bg-background/50 backdrop-blur-sm p-2 flex flex-col items-center justify-center gap-4 hover:border-primary/20 transition-all duration-300 hover:shadow-lg group"
whileHover={{ y: -5 }}
>
<div className={"relative w-full h-48 flex items-center justify-center"}>
<Image
src={sponsor.logo}
alt={sponsor.name}
fill
className={
sponsor.name === "Unstop"
? "object-contain p-4"
: sponsor.name === "Code Crafters"
? "object-contain w-32 h-16 mx-auto"
: sponsor.name === "Innovxus"
? "object-contain w-24 h-10 mx-auto flex items-center justify-center"
: "object-cover"
}
/>
</div>
<div className="text-center">
<h3 className="font-semibold text-lg">{sponsor.name}</h3>
<p className="text-sm text-muted-foreground">{sponsor.title}</p>
</div>
</motion.div>
)
))}
{sponsors.map((sponsor, idx) => (
sponsor.link ? (
<a
aria-hidden="true"
key={`second-${idx}`}
href={sponsor.link}
target="_blank"
rel="noopener noreferrer"
className="no-underline"
>
<motion.div
aria-hidden="true"
key={`second-${idx}`}
className="flex-shrink-0 w-[300px] h-[200px] rounded-xl border border-primary/10 bg-background/50 backdrop-blur-sm p-2 flex flex-col items-center justify-center gap-4 hover:border-primary/20 transition-all duration-300 hover:shadow-lg group"
whileHover={{ y: -5 }}
>
<div className={"relative w-full h-48 flex items-center justify-center"}>
<Image
src={sponsor.logo}
alt={sponsor.name}
fill
className={
sponsor.name === "Unstop"
? "object-contain p-4"
: sponsor.name === "Code Crafters"
? "object-contain w-32 h-16 mx-auto"
: sponsor.name === "Innovxus"
? "object-contain w-24 h-10 mx-auto flex items-center justify-center"
: "object-cover"
}
/>
</div>
<div className="text-center">
<h3 className="font-semibold text-lg">{sponsor.name}</h3>
<p className="text-sm text-muted-foreground">{sponsor.title}</p>
</div>
</motion.div>
</a>
) : (
<motion.div
aria-hidden="true"
key={`second-${idx}`}
className="flex-shrink-0 w-[300px] h-[200px] rounded-xl border border-primary/10 bg-background/50 backdrop-blur-sm p-2 flex flex-col items-center justify-center gap-4 hover:border-primary/20 transition-all duration-300 hover:shadow-lg group"
whileHover={{ y: -5 }}
>
<div className={"relative w-full h-48 flex items-center justify-center"}>
<Image
src={sponsor.logo}
alt={sponsor.name}
fill
className={
sponsor.name === "Unstop"
? "object-contain p-4"
: sponsor.name === "Code Crafters"
? "object-contain w-32 h-16 mx-auto"
: sponsor.name === "Innovxus"
? "object-contain w-24 h-10 mx-auto flex items-center justify-center"
: "object-cover"
}
/>
</div>
<div className="text-center">
<h3 className="font-semibold text-lg">{sponsor.name}</h3>
<p className="text-sm text-muted-foreground">{sponsor.title}</p>
</div>
</motion.div>
)
))}
🤖 Prompt for AI Agents
In components/home/SponsorsSection.tsx around lines 164 to 227, the duplicated
sponsor items used for continuous scrolling should be hidden from assistive
technologies; add aria-hidden="true" to the duplicate branches: set
aria-hidden="true" on the outer <a> element wrapping the duplicate linked branch
and on the root <motion.div> of the duplicate non-link branch (and if you prefer
consistency, also add aria-hidden="true" to the duplicate <motion.div> inside
the linked branch), keeping existing attributes intact.

</div>
</div>
</div>
</div>
</section>
);
}
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading