From 9efe88d9ebf169fd5ba673613b08cf96986713e0 Mon Sep 17 00:00:00 2001 From: diubi Date: Wed, 2 Sep 2026 19:15:10 +0200 Subject: [PATCH 01/11] feat: homepage bg --- src/app/layout.tsx | 9 +-- src/app/page.tsx | 10 ++- src/assets/shapes/hero-glow.svg | 30 +++++++++ src/components/conditional-global-shapes.tsx | 26 ++++++++ src/components/home/hero.tsx | 5 +- src/components/home/shapes.tsx | 66 ++++++++++++++++++++ 6 files changed, 135 insertions(+), 11 deletions(-) create mode 100644 src/assets/shapes/hero-glow.svg create mode 100644 src/components/conditional-global-shapes.tsx create mode 100644 src/components/home/shapes.tsx diff --git a/src/app/layout.tsx b/src/app/layout.tsx index c6156ef..909ee12 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,6 @@ import { ConditionalFooter } from "@/components/conditional-footer" +import { ConditionalGlobalShapes } from "@/components/conditional-global-shapes" import { Header } from "@/components/header/header" -import { Shape } from "@/components/shapes" import { ThemeProvider } from "@/components/theme-provider" import "@/styles/globals.css" import type { Metadata } from "next" @@ -75,12 +75,7 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac // storageKey="polinetwork_darkmode_temp" // TODO: enable when dark mode design is ready disableTransitionOnChange > -
- - - - -
+
{children} diff --git a/src/app/page.tsx b/src/app/page.tsx index 0296908..ddc53c1 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,14 +2,18 @@ import { AboutUs } from "@/components/home/about-us" import { Hero } from "@/components/home/hero" import { Materials } from "@/components/home/materials" import { Projects } from "@/components/home/projects" +import { MiddleShapes } from "@/components/home/shapes" export default function Home() { return (
- - - +
+ + + + +
) } diff --git a/src/assets/shapes/hero-glow.svg b/src/assets/shapes/hero-glow.svg new file mode 100644 index 0000000..98a159b --- /dev/null +++ b/src/assets/shapes/hero-glow.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/conditional-global-shapes.tsx b/src/components/conditional-global-shapes.tsx new file mode 100644 index 0000000..d034b7e --- /dev/null +++ b/src/components/conditional-global-shapes.tsx @@ -0,0 +1,26 @@ +"use client" + +import { usePathname } from "next/navigation" +import { Shape } from "@/components/shapes" + +const HIDDEN_EXACT = ["/"] + +/** + * Generic top-of-page decorative shapes, reused on every page that doesn't + * define its own (e.g. the homepage, which has a Figma-accurate composition). + */ +export function ConditionalGlobalShapes() { + const pathname = usePathname() + if (HIDDEN_EXACT.includes(pathname)) return null + + return ( +
+
+ + + + +
+
+ ) +} diff --git a/src/components/home/hero.tsx b/src/components/home/hero.tsx index ff1152f..ab9d378 100644 --- a/src/components/home/hero.tsx +++ b/src/components/home/hero.tsx @@ -2,10 +2,13 @@ import Link from "next/link" import { FiNavigation, FiUserPlus } from "react-icons/fi" import { Button } from "../ui/button" import { GroupSearch } from "./group-search" +import { HeroShapes } from "./shapes" export function Hero() { return ( -
+
+ +

Trova gruppi, risorse e supporto tra gli studenti del Polimi diff --git a/src/components/home/shapes.tsx b/src/components/home/shapes.tsx new file mode 100644 index 0000000..01b2407 --- /dev/null +++ b/src/components/home/shapes.tsx @@ -0,0 +1,66 @@ +import Image from "next/image" +import heroGlowSvg from "@/assets/shapes/hero-glow.svg" +import { Shape } from "@/components/shapes" + +/** + * `left` offsets below are expressed as `calc(50% + Npx)`, i.e. relative to the + * horizontal center of the section rather than its left edge. The homepage + * content is itself center-anchored (not width-capped), so anchoring shapes to + * the edge would make them drift away from the content on screens wider or + * narrower than the 1728px/402px Figma reference frames. + */ + +/** + * Decorative shapes for the Hero section, matching the Figma homepage design. + * Renders a mobile composition (< sm) and a desktop composition (>= sm). + */ +export function HeroShapes() { + return ( +
+ + + + + + +
+ ) +} + +/** + * Decorative shapes bleeding across the Materials, Projects and About Us sections, + * matching the Figma homepage design. Mount this once behind those three sections. + */ +export function MiddleShapes() { + return ( +
+ + + + + + + + + + + + + + +
+ ) +} From 255f6802b0e2bdcbac7081da8192463f2a5e43f7 Mon Sep 17 00:00:00 2001 From: diubi Date: Thu, 3 Sep 2026 19:26:16 +0200 Subject: [PATCH 02/11] feat: finished homepage bg --- src/components/home/shapes.tsx | 61 +++++++++++++--------------------- src/components/shapes.tsx | 9 +++-- 2 files changed, 30 insertions(+), 40 deletions(-) diff --git a/src/components/home/shapes.tsx b/src/components/home/shapes.tsx index 01b2407..cc8c004 100644 --- a/src/components/home/shapes.tsx +++ b/src/components/home/shapes.tsx @@ -1,5 +1,3 @@ -import Image from "next/image" -import heroGlowSvg from "@/assets/shapes/hero-glow.svg" import { Shape } from "@/components/shapes" /** @@ -10,57 +8,44 @@ import { Shape } from "@/components/shapes" * narrower than the 1728px/402px Figma reference frames. */ -/** - * Decorative shapes for the Hero section, matching the Figma homepage design. - * Renders a mobile composition (< sm) and a desktop composition (>= sm). - */ export function HeroShapes() { return (
- - - + {/* Mobile Shapes */} + + + - - + {/* Desktop Shapes */} + +
) } -/** - * Decorative shapes bleeding across the Materials, Projects and About Us sections, - * matching the Figma homepage design. Mount this once behind those three sections. - */ export function MiddleShapes() { return (
- - - - - - - - + {/* Mobile Shapes */} + + + + + + + + + - + {/* Desktop Shapes */} + - - - + + +
) } diff --git a/src/components/shapes.tsx b/src/components/shapes.tsx index 19dd3e2..7f78ba5 100644 --- a/src/components/shapes.tsx +++ b/src/components/shapes.tsx @@ -1,11 +1,12 @@ import Image from "next/image" import bigBlueSvg from "@/assets/shapes/big-blue.svg" import bigTealSvg from "@/assets/shapes/big-teal.svg" +import heroGlowSvg from "@/assets/shapes/hero-glow.svg" import looperSvg from "@/assets/shapes/looper.svg" import smallBlueSvg from "@/assets/shapes/small-blue.svg" import { cn } from "@/lib/utils" -export type ShapeVariant = "big-blue" | "big-teal" | "small-blue" | "looper" +export type ShapeVariant = "big-blue" | "big-teal" | "small-blue" | "hero-glow" | "looper" export type ShapeProps = { variant: ShapeVariant @@ -21,6 +22,8 @@ export const Shape: React.FC = ({ variant, className }) => { return bigTealSvg case "small-blue": return smallBlueSvg + case "hero-glow": + return heroGlowSvg case "looper": return looperSvg default: @@ -28,5 +31,7 @@ export const Shape: React.FC = ({ variant, className }) => { } } - return + return ( + + ) } From 52254e5217c7bfa3aeb98b5d901c6b6502dec0d4 Mon Sep 17 00:00:00 2001 From: diubi Date: Thu, 3 Sep 2026 19:28:10 +0200 Subject: [PATCH 03/11] refactor: edit homepage exported shapes names --- src/app/page.tsx | 4 ++-- src/components/footer/shapes.tsx | 0 src/components/home/hero.tsx | 4 ++-- src/components/home/shapes.tsx | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 src/components/footer/shapes.tsx diff --git a/src/app/page.tsx b/src/app/page.tsx index ddc53c1..d7b541e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,14 +2,14 @@ import { AboutUs } from "@/components/home/about-us" import { Hero } from "@/components/home/hero" import { Materials } from "@/components/home/materials" import { Projects } from "@/components/home/projects" -import { MiddleShapes } from "@/components/home/shapes" +import { HomeMiddleShapes } from "@/components/home/shapes" export default function Home() { return (
- + diff --git a/src/components/footer/shapes.tsx b/src/components/footer/shapes.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/home/hero.tsx b/src/components/home/hero.tsx index ab9d378..22bfccb 100644 --- a/src/components/home/hero.tsx +++ b/src/components/home/hero.tsx @@ -2,12 +2,12 @@ import Link from "next/link" import { FiNavigation, FiUserPlus } from "react-icons/fi" import { Button } from "../ui/button" import { GroupSearch } from "./group-search" -import { HeroShapes } from "./shapes" +import { HomeHeroShapes } from "./shapes" export function Hero() { return (
- +

diff --git a/src/components/home/shapes.tsx b/src/components/home/shapes.tsx index cc8c004..52f5ad3 100644 --- a/src/components/home/shapes.tsx +++ b/src/components/home/shapes.tsx @@ -8,7 +8,7 @@ import { Shape } from "@/components/shapes" * narrower than the 1728px/402px Figma reference frames. */ -export function HeroShapes() { +export function HomeHeroShapes() { return (
{/* Mobile Shapes */} @@ -23,7 +23,7 @@ export function HeroShapes() { ) } -export function MiddleShapes() { +export function HomeMiddleShapes() { return (
{/* Mobile Shapes */} From 0a5f92c85ee3d47b64f15c8c6dd0753d7bf8437b Mon Sep 17 00:00:00 2001 From: diubi Date: Thu, 3 Sep 2026 20:05:31 +0200 Subject: [PATCH 04/11] feat: footer shapes --- src/components/footer/index.tsx | 8 +++++--- src/components/footer/shapes.tsx | 12 ++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/components/footer/index.tsx b/src/components/footer/index.tsx index f403e40..7ccad65 100644 --- a/src/components/footer/index.tsx +++ b/src/components/footer/index.tsx @@ -4,11 +4,13 @@ import { FiFacebook, FiGithub, FiInstagram, FiLinkedin } from "react-icons/fi" import discord from "@/assets/icons/discord.svg" import telegram from "@/assets/icons/telegram.svg" import { CardMultipleIcons } from "../card-multiple-icons" +import { FooterShapes } from "./shapes" export function Footer() { return ( -
-

+
+ +

Keep in touch!

@@ -40,7 +42,7 @@ export function Footer() {

-
+
diff --git a/src/components/footer/shapes.tsx b/src/components/footer/shapes.tsx index e69de29..6299352 100644 --- a/src/components/footer/shapes.tsx +++ b/src/components/footer/shapes.tsx @@ -0,0 +1,12 @@ +import { Shape } from "@/components/shapes" + +export function FooterShapes() { + return ( +
+ {/* Desktop Shapes */} + + + +
+ ) +} From ccd04559f8a603517bb9e996c6812fa0dfbbedab Mon Sep 17 00:00:00 2001 From: diubi Date: Fri, 4 Sep 2026 20:40:26 +0200 Subject: [PATCH 05/11] feat: projects shapes --- src/app/layout.tsx | 3 +- src/app/page.tsx | 9 ++- src/app/projects/page.tsx | 21 +++++-- src/app/projects/shapes.tsx | 97 +++++++++++++++++++++++++++++ src/assets/shapes/projects-glow.svg | 12 ++++ src/components/home/shapes.tsx | 39 +++++++++--- src/components/shapes.tsx | 5 +- 7 files changed, 167 insertions(+), 19 deletions(-) create mode 100644 src/app/projects/shapes.tsx create mode 100644 src/assets/shapes/projects-glow.svg diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 909ee12..c1b9db0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,4 @@ import { ConditionalFooter } from "@/components/conditional-footer" -import { ConditionalGlobalShapes } from "@/components/conditional-global-shapes" import { Header } from "@/components/header/header" import { ThemeProvider } from "@/components/theme-provider" import "@/styles/globals.css" @@ -75,7 +74,7 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac // storageKey="polinetwork_darkmode_temp" // TODO: enable when dark mode design is ready disableTransitionOnChange > - + {/* */}
{children} diff --git a/src/app/page.tsx b/src/app/page.tsx index d7b541e..66b8b37 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,18 +2,21 @@ import { AboutUs } from "@/components/home/about-us" import { Hero } from "@/components/home/hero" import { Materials } from "@/components/home/materials" import { Projects } from "@/components/home/projects" -import { HomeMiddleShapes } from "@/components/home/shapes" +import { HomeMaterialsShapes, HomeProjectsShapes } from "@/components/home/shapes" export default function Home() { return (
- + +
+
+ -
+
) } diff --git a/src/app/projects/page.tsx b/src/app/projects/page.tsx index fbfb0d7..a431936 100644 --- a/src/app/projects/page.tsx +++ b/src/app/projects/page.tsx @@ -3,6 +3,7 @@ import { CommunityNews } from "@/components/projects/community-news" import { Deprecated } from "@/components/projects/deprecated" import { Upload } from "@/components/projects/upload" import { getAllProjects } from "@/queries/projects" +import { CollectionShapes, CommunityNewsShapes, DeprecatedShapes, UploadShapes } from "./shapes" export const metadata = { title: "Progetti", @@ -20,10 +21,22 @@ export default async function Home() { return (
- - - - +
+ + +
+
+ + +
+
+ + +
+
+ + +
) } diff --git a/src/app/projects/shapes.tsx b/src/app/projects/shapes.tsx new file mode 100644 index 0000000..35d9031 --- /dev/null +++ b/src/app/projects/shapes.tsx @@ -0,0 +1,97 @@ +import { Shape } from "@/components/shapes" + +/** + * `left` offsets below are expressed as `calc(50% + Npx)`, i.e. relative to the + * horizontal center of the section rather than its left edge. The projects + * content is itself center-anchored (not width-capped), so anchoring shapes to + * the edge would make them drift away from the content on screens wider or + * narrower than the 1728px/402px Figma reference frames. + * + * `top` is relative to the top of the section each component is mounted in + * (CommunityNews, Collection, Upload, Deprecated), not to the page. Every + * section on this page uses `min-h-screen` (fluid height, depends on the viewport) + * — each shape below is therefore scoped and `top`-anchored to the section it + * visually belongs to, rather than using cumulative page offsets. + */ + +export function CommunityNewsShapes() { + return ( +
+ {/* Mobile Shapes */} + + + + + + + + {/* Desktop Shapes */} + + + + + +
+ ) +} + +export function CollectionShapes() { + return ( +
+ {/* Mobile Shapes */} + + + + {/* Desktop Shapes */} + + + +
+ ) +} + +export function UploadShapes() { + return ( +
+ {/* Mobile Shapes */} + + + + {/* Desktop Shapes */} + + + +
+ ) +} + +export function DeprecatedShapes() { + return ( +
+ {/* Mobile Shapes */} + + + + + {/* Desktop Shapes */} + + + +
+ ) +} diff --git a/src/assets/shapes/projects-glow.svg b/src/assets/shapes/projects-glow.svg new file mode 100644 index 0000000..07df19c --- /dev/null +++ b/src/assets/shapes/projects-glow.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/components/home/shapes.tsx b/src/components/home/shapes.tsx index 52f5ad3..a1667be 100644 --- a/src/components/home/shapes.tsx +++ b/src/components/home/shapes.tsx @@ -6,6 +6,17 @@ import { Shape } from "@/components/shapes" * content is itself center-anchored (not width-capped), so anchoring shapes to * the edge would make them drift away from the content on screens wider or * narrower than the 1728px/402px Figma reference frames. + * + * `top` is relative to the top of the section each component is mounted in + * (Materials or Projects), not to the page. Materials and Projects/AboutUs + * used to share one absolute layer with cumulative offsets, but AboutUs uses + * `min-h-screen` (fluid height, depends on the viewport) — if a shape ever + * needs to sit inside AboutUs, mount it scoped to that section too, the same + * way this file already splits Materials from Projects. Otherwise any + * mismatch between a fluid section's real height and Figma's fixed height + * assumption compounds into every shape positioned after it (e.g. shapes + * drifting away from their section when the browser is zoomed out — see + * src/app/projects/shapes.tsx, which had exactly this bug). */ export function HomeHeroShapes() { @@ -23,7 +34,7 @@ export function HomeHeroShapes() { ) } -export function HomeMiddleShapes() { +export function HomeMaterialsShapes() { return (
{/* Mobile Shapes */} @@ -32,20 +43,30 @@ export function HomeMiddleShapes() { - - - {/* Desktop Shapes */} - -
) } + +export function HomeProjectsShapes() { + return ( +
+ {/* Mobile Shapes */} + + + + + {/* Desktop Shapes */} + + +
+ ) +} diff --git a/src/components/shapes.tsx b/src/components/shapes.tsx index 7f78ba5..683100e 100644 --- a/src/components/shapes.tsx +++ b/src/components/shapes.tsx @@ -3,10 +3,11 @@ import bigBlueSvg from "@/assets/shapes/big-blue.svg" import bigTealSvg from "@/assets/shapes/big-teal.svg" import heroGlowSvg from "@/assets/shapes/hero-glow.svg" import looperSvg from "@/assets/shapes/looper.svg" +import projectsGlowSvg from "@/assets/shapes/projects-glow.svg" import smallBlueSvg from "@/assets/shapes/small-blue.svg" import { cn } from "@/lib/utils" -export type ShapeVariant = "big-blue" | "big-teal" | "small-blue" | "hero-glow" | "looper" +export type ShapeVariant = "big-blue" | "big-teal" | "small-blue" | "hero-glow" | "projects-glow" | "looper" export type ShapeProps = { variant: ShapeVariant @@ -24,6 +25,8 @@ export const Shape: React.FC = ({ variant, className }) => { return smallBlueSvg case "hero-glow": return heroGlowSvg + case "projects-glow": + return projectsGlowSvg case "looper": return looperSvg default: From bbe4c1426c4ce09b6aa930b6ed9d57996d450791 Mon Sep 17 00:00:00 2001 From: diubi Date: Thu, 10 Sep 2026 17:37:53 +0200 Subject: [PATCH 06/11] feat: matricole page shapes --- src/app/matricole/page.tsx | 16 ++++- src/app/matricole/shapes.tsx | 85 ++++++++++++++++++++++++ src/app/projects/shapes.tsx | 18 ++--- src/assets/shapes/matricole-glow-1.svg | 12 ++++ src/assets/shapes/matricole-glow-2.svg | 12 ++++ src/assets/shapes/matricole-top-glow.svg | 36 ++++++++++ src/components/footer/shapes.tsx | 6 +- src/components/home/shapes.tsx | 14 ++-- src/components/shapes.tsx | 45 ++++++++++++- 9 files changed, 221 insertions(+), 23 deletions(-) create mode 100644 src/app/matricole/shapes.tsx create mode 100644 src/assets/shapes/matricole-glow-1.svg create mode 100644 src/assets/shapes/matricole-glow-2.svg create mode 100644 src/assets/shapes/matricole-top-glow.svg diff --git a/src/app/matricole/page.tsx b/src/app/matricole/page.tsx index 9d1e36d..b9ac6f1 100644 --- a/src/app/matricole/page.tsx +++ b/src/app/matricole/page.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next" import { FAQsPage } from "@/components/matricole/faqs" import { MatricoleGuides } from "@/components/matricole/guides" import { MatricoleIntro } from "@/components/matricole/intro" +import { MatricoleFAQsShapes, MatricoleGuidesShapes, MatricoleIntroShapes } from "./shapes" export const metadata: Metadata = { title: "Matricole", @@ -11,9 +12,18 @@ export const metadata: Metadata = { export default function MatricolePage() { return (
- - - +
+ + +
+
+ + +
+
+ + +
) } diff --git a/src/app/matricole/shapes.tsx b/src/app/matricole/shapes.tsx new file mode 100644 index 0000000..c86d0a9 --- /dev/null +++ b/src/app/matricole/shapes.tsx @@ -0,0 +1,85 @@ +import { Shape, ShapeLayer } from "@/components/shapes" + +/** + * `left` offsets are `calc(50% + Npx)`, relative to the horizontal center of + * the 1728px-wide (desktop) / 402px-wide (mobile) Figma reference frames — + * see src/components/home/shapes.tsx for why. + * + * `top` is relative to the top of the section each component is mounted in + * (MatricoleIntro, MatricoleGuides, FAQsPage), matching how the section + * boundaries are grouped in the Figma file, not to the page as a whole. + */ + +export function MatricoleIntroShapes() { + return ( + + {/* Mobile Shapes */} + + + + + + {/* Desktop Shapes */} + + + + + + ) +} + +export function MatricoleGuidesShapes() { + return ( + + {/* Mobile Shapes */} + + + + + + + + + + + + + + {/* Desktop Shapes */} + + + + + + + ) +} + +export function MatricoleFAQsShapes() { + return ( + + {/* Mobile Shapes (this section has no shapes on desktop) */} + + + + + ) +} diff --git a/src/app/projects/shapes.tsx b/src/app/projects/shapes.tsx index 35d9031..90ec5bb 100644 --- a/src/app/projects/shapes.tsx +++ b/src/app/projects/shapes.tsx @@ -1,4 +1,4 @@ -import { Shape } from "@/components/shapes" +import { Shape, ShapeLayer } from "@/components/shapes" /** * `left` offsets below are expressed as `calc(50% + Npx)`, i.e. relative to the @@ -16,7 +16,7 @@ import { Shape } from "@/components/shapes" export function CommunityNewsShapes() { return ( -
+ {/* Mobile Shapes */} @@ -37,13 +37,13 @@ export function CommunityNewsShapes() { variant="looper" className="top-[-280.4px] left-[calc(50%-27.41px)] hidden h-[1584.39px] w-[1464.51px] md:block" /> -
+ ) } export function CollectionShapes() { return ( -
+ {/* Mobile Shapes */} @@ -55,13 +55,13 @@ export function CollectionShapes() { variant="looper" className="top-[-205.37px] left-[calc(50%-763.83px)] hidden h-[1560.48px] w-[1609.71px] md:block" /> -
+ ) } export function UploadShapes() { return ( -
+ {/* Mobile Shapes */} @@ -73,13 +73,13 @@ export function UploadShapes() { variant="looper" className="-top-15.25 left-[calc(50%-1096.09px)] hidden h-[1560.48px] w-[1609.71px] md:block" /> -
+ ) } export function DeprecatedShapes() { return ( -
+ {/* Mobile Shapes */} @@ -92,6 +92,6 @@ export function DeprecatedShapes() { variant="looper" className="top-[-147.41px] left-[calc(50%-268.41px)] hidden h-[1560.62px] w-[1609.84px] rotate-180 md:block" /> -
+ ) } diff --git a/src/assets/shapes/matricole-glow-1.svg b/src/assets/shapes/matricole-glow-1.svg new file mode 100644 index 0000000..1c9425e --- /dev/null +++ b/src/assets/shapes/matricole-glow-1.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/assets/shapes/matricole-glow-2.svg b/src/assets/shapes/matricole-glow-2.svg new file mode 100644 index 0000000..23e7c87 --- /dev/null +++ b/src/assets/shapes/matricole-glow-2.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/assets/shapes/matricole-top-glow.svg b/src/assets/shapes/matricole-top-glow.svg new file mode 100644 index 0000000..36e654d --- /dev/null +++ b/src/assets/shapes/matricole-top-glow.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/footer/shapes.tsx b/src/components/footer/shapes.tsx index 6299352..018629d 100644 --- a/src/components/footer/shapes.tsx +++ b/src/components/footer/shapes.tsx @@ -1,12 +1,12 @@ -import { Shape } from "@/components/shapes" +import { Shape, ShapeLayer } from "@/components/shapes" export function FooterShapes() { return ( -
+ {/* Desktop Shapes */} -
+ ) } diff --git a/src/components/home/shapes.tsx b/src/components/home/shapes.tsx index a1667be..8307868 100644 --- a/src/components/home/shapes.tsx +++ b/src/components/home/shapes.tsx @@ -1,4 +1,4 @@ -import { Shape } from "@/components/shapes" +import { Shape, ShapeLayer } from "@/components/shapes" /** * `left` offsets below are expressed as `calc(50% + Npx)`, i.e. relative to the @@ -21,7 +21,7 @@ import { Shape } from "@/components/shapes" export function HomeHeroShapes() { return ( -
+ {/* Mobile Shapes */} @@ -30,13 +30,13 @@ export function HomeHeroShapes() { {/* Desktop Shapes */} -
+ ) } export function HomeMaterialsShapes() { return ( -
+ {/* Mobile Shapes */} @@ -49,13 +49,13 @@ export function HomeMaterialsShapes() { -
+ ) } export function HomeProjectsShapes() { return ( -
+ {/* Mobile Shapes */} @@ -67,6 +67,6 @@ export function HomeProjectsShapes() { variant="small-blue" className="top-[287.32px] left-[calc(50%+340.32px)] hidden size-[477.48px] md:block" /> -
+ ) } diff --git a/src/components/shapes.tsx b/src/components/shapes.tsx index 683100e..5843202 100644 --- a/src/components/shapes.tsx +++ b/src/components/shapes.tsx @@ -3,11 +3,23 @@ import bigBlueSvg from "@/assets/shapes/big-blue.svg" import bigTealSvg from "@/assets/shapes/big-teal.svg" import heroGlowSvg from "@/assets/shapes/hero-glow.svg" import looperSvg from "@/assets/shapes/looper.svg" +import matricoleGlow1Svg from "@/assets/shapes/matricole-glow-1.svg" +import matricoleGlow2Svg from "@/assets/shapes/matricole-glow-2.svg" +import matricoleTopGlowSvg from "@/assets/shapes/matricole-top-glow.svg" import projectsGlowSvg from "@/assets/shapes/projects-glow.svg" import smallBlueSvg from "@/assets/shapes/small-blue.svg" import { cn } from "@/lib/utils" -export type ShapeVariant = "big-blue" | "big-teal" | "small-blue" | "hero-glow" | "projects-glow" | "looper" +export type ShapeVariant = + | "big-blue" + | "big-teal" + | "small-blue" + | "hero-glow" + | "projects-glow" + | "matricole-glow-1" + | "matricole-glow-2" + | "matricole-top-glow" + | "looper" export type ShapeProps = { variant: ShapeVariant @@ -27,6 +39,12 @@ export const Shape: React.FC = ({ variant, className }) => { return heroGlowSvg case "projects-glow": return projectsGlowSvg + case "matricole-glow-1": + return matricoleGlow1Svg + case "matricole-glow-2": + return matricoleGlow2Svg + case "matricole-top-glow": + return matricoleTopGlowSvg case "looper": return looperSvg default: @@ -38,3 +56,28 @@ export const Shape: React.FC = ({ variant, className }) => { ) } + +export type ShapeLayerProps = { + children: React.ReactNode + className?: string +} + +/** + * Wraps a group of ``s positioned behind a section. `overflow-x-clip` + * (not `overflow-hidden`/`overflow-x-hidden`) is required: pairing it with + * `overflow-y-visible` clips horizontal bleed only — CSS forces the "visible" + * axis to compute as `auto` (which still clips, just via an invisible + * scrollbar) whenever the other axis is `hidden`/`auto`/`scroll`, but not + * when it's `clip`, since `clip` doesn't create a scroll container. This lets + * shapes bleed vertically into the next section (as several are designed to) + * without shapes positioned off-canvas horizontally causing a page-wide + * horizontal scrollbar. + */ +export const ShapeLayer: React.FC = ({ children, className }) => ( +
+ {children} +
+) From 92769de3461f8e7a51d6a12ec8e19c615e8ecbda Mon Sep 17 00:00:00 2001 From: diubi Date: Fri, 11 Sep 2026 20:02:28 +0200 Subject: [PATCH 07/11] feat: associations page shape --- src/app/associations/page.tsx | 4 ++- src/app/associations/shapes.tsx | 57 +++++++++++++++++++++++++++++++++ src/app/matricole/shapes.tsx | 2 +- 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/app/associations/shapes.tsx diff --git a/src/app/associations/page.tsx b/src/app/associations/page.tsx index aa70906..58304b1 100644 --- a/src/app/associations/page.tsx +++ b/src/app/associations/page.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next" import { AssociationsList } from "@/components/associations/associations-list" import { Hero } from "@/components/ui/hero" import { getAllAssociations } from "@/queries/associations" +import { AssociationsShapes } from "./shapes" export const metadata: Metadata = { title: "Associazioni", @@ -14,7 +15,8 @@ export default async function AssociationsPage() { const associations = await getAllAssociations() return ( -
+
+
diff --git a/src/app/associations/shapes.tsx b/src/app/associations/shapes.tsx new file mode 100644 index 0000000..d0520da --- /dev/null +++ b/src/app/associations/shapes.tsx @@ -0,0 +1,57 @@ +import { Shape, ShapeLayer } from "@/components/shapes" + +/** + * `left` offsets are `calc(50% + Npx)`, relative to the horizontal center of + * the 1728px-wide (desktop) / 402px-wide (mobile) Figma reference frames — + * see src/components/home/shapes.tsx for why. + * + * This page is a single `
` section (no sub-sections like Projects or + * Matricole), so `top` is simply the Figma-reported `y`, relative to the top + * of the page/`
` — no per-section remapping needed. + * + * Exception: the last looper is `bottom`-anchored instead. It's meant to sit + * near the end of the card list / bleed into the footer transition, but the + * list length (and so `
`'s real height) is data-dependent — the + * associations list can be empty or have any number of cards. A fixed `top` + * would only land near the end of the content at the exact card count Figma + * assumed; anchoring from the bottom (proportionally, using the Figma + * container height as the reference) keeps it near the end of the *real* + * content regardless of how many cards actually render. + */ + +export function AssociationsShapes() { + return ( + + {/* Mobile Shapes */} + + + + + + + + + + + {/* Desktop Shapes */} + + {/* */} + + {/* */} + + {/* */} + + ) +} diff --git a/src/app/matricole/shapes.tsx b/src/app/matricole/shapes.tsx index c86d0a9..f9bf48c 100644 --- a/src/app/matricole/shapes.tsx +++ b/src/app/matricole/shapes.tsx @@ -57,7 +57,7 @@ export function MatricoleGuidesShapes() { - + {/* Desktop Shapes */} From 97de30c3840c31ad604b0be82ca481d1285ad0bc Mon Sep 17 00:00:00 2001 From: diubi Date: Fri, 11 Sep 2026 20:03:07 +0200 Subject: [PATCH 08/11] refactor: remove comments --- src/app/associations/shapes.tsx | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/app/associations/shapes.tsx b/src/app/associations/shapes.tsx index d0520da..448fd48 100644 --- a/src/app/associations/shapes.tsx +++ b/src/app/associations/shapes.tsx @@ -1,24 +1,5 @@ import { Shape, ShapeLayer } from "@/components/shapes" -/** - * `left` offsets are `calc(50% + Npx)`, relative to the horizontal center of - * the 1728px-wide (desktop) / 402px-wide (mobile) Figma reference frames — - * see src/components/home/shapes.tsx for why. - * - * This page is a single `
` section (no sub-sections like Projects or - * Matricole), so `top` is simply the Figma-reported `y`, relative to the top - * of the page/`
` — no per-section remapping needed. - * - * Exception: the last looper is `bottom`-anchored instead. It's meant to sit - * near the end of the card list / bleed into the footer transition, but the - * list length (and so `
`'s real height) is data-dependent — the - * associations list can be empty or have any number of cards. A fixed `top` - * would only land near the end of the content at the exact card count Figma - * assumed; anchoring from the bottom (proportionally, using the Figma - * container height as the reference) keeps it near the end of the *real* - * content regardless of how many cards actually render. - */ - export function AssociationsShapes() { return ( From e67ae96ae3587fbe1b7fe7b777f8e037a03b353d Mon Sep 17 00:00:00 2001 From: diubi Date: Wed, 16 Sep 2026 19:27:25 +0200 Subject: [PATCH 09/11] feat: groups shapes --- src/app/groups/page.tsx | 4 +++- src/app/groups/shapes.tsx | 23 +++++++++++++++++++++++ src/components/shapes.tsx | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/app/groups/shapes.tsx diff --git a/src/app/groups/page.tsx b/src/app/groups/page.tsx index 1b6a4e1..58970af 100644 --- a/src/app/groups/page.tsx +++ b/src/app/groups/page.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next" import { FiBook, FiStar } from "react-icons/fi" import { CardIcon } from "@/components/card-icon" import { GroupSearch } from "@/components/home/group-search" +import { GroupsShapes } from "./shapes" const groups = [ { @@ -28,7 +29,8 @@ export const metadata: Metadata = { export default function Home() { return (
-
+
+

Groups diff --git a/src/app/groups/shapes.tsx b/src/app/groups/shapes.tsx new file mode 100644 index 0000000..84e4083 --- /dev/null +++ b/src/app/groups/shapes.tsx @@ -0,0 +1,23 @@ +import { Shape, ShapeLayer } from "@/components/shapes" + +export function GroupsShapes() { + return ( + + {/* Mobile Shapes */} + + + + + + + + {/* Desktop Shapes */} + + + + + + + + ) +} diff --git a/src/components/shapes.tsx b/src/components/shapes.tsx index 5843202..f69949f 100644 --- a/src/components/shapes.tsx +++ b/src/components/shapes.tsx @@ -15,7 +15,7 @@ export type ShapeVariant = | "big-teal" | "small-blue" | "hero-glow" - | "projects-glow" + | "projects-glow" //TODO: remove these page specific shapes | "matricole-glow-1" | "matricole-glow-2" | "matricole-top-glow" From b71ca041659e812f30fe97a3c9d6bbf02f90f51c Mon Sep 17 00:00:00 2001 From: diubi Date: Wed, 23 Sep 2026 20:58:44 +0200 Subject: [PATCH 10/11] refactor: moved common shapes to new file; feat: faqs shapes --- src/app/faqs/page.tsx | 4 +- src/app/matricole/guida/page.tsx | 2 + src/app/matricole/page.tsx | 5 ++- src/app/matricole/shapes.tsx | 35 +---------------- ...ricole-glow-2.svg => resources-glow-2.svg} | 0 ...le-top-glow.svg => resources-top-glow.svg} | 0 src/components/resources/shapes.tsx | 38 +++++++++++++++++++ src/components/shapes.tsx | 16 ++++---- 8 files changed, 55 insertions(+), 45 deletions(-) rename src/assets/shapes/{matricole-glow-2.svg => resources-glow-2.svg} (100%) rename src/assets/shapes/{matricole-top-glow.svg => resources-top-glow.svg} (100%) create mode 100644 src/components/resources/shapes.tsx diff --git a/src/app/faqs/page.tsx b/src/app/faqs/page.tsx index d029fee..02b6ab2 100644 --- a/src/app/faqs/page.tsx +++ b/src/app/faqs/page.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next" import { FaqsTabs } from "@/components/faqs/faqs-tabs" +import { ResourcesHeroShapes } from "@/components/resources/shapes" import { Hero } from "@/components/ui/hero" import { getAllFaqs } from "@/queries/faqs" @@ -14,7 +15,8 @@ export default async function FAQsPage() { const categories = await getAllFaqs() return ( -
+
+
diff --git a/src/app/matricole/guida/page.tsx b/src/app/matricole/guida/page.tsx index 91334bf..f6a2506 100644 --- a/src/app/matricole/guida/page.tsx +++ b/src/app/matricole/guida/page.tsx @@ -3,6 +3,7 @@ import { FiDownload } from "react-icons/fi" import { CardSplit } from "@/components/card-split" import { Button } from "@/components/ui/button" import { getLatestGuidaMatricola } from "@/queries/guida-matricola" +import { ResourcesHeroShapes } from "@/components/resources/shapes" export const metadata: Metadata = { title: "Guida della Matricola", @@ -23,6 +24,7 @@ export default async function GuidaMatricolaPage() { return (
+

Guida della Matricola diff --git a/src/app/matricole/page.tsx b/src/app/matricole/page.tsx index b9ac6f1..7b7575a 100644 --- a/src/app/matricole/page.tsx +++ b/src/app/matricole/page.tsx @@ -2,7 +2,8 @@ import type { Metadata } from "next" import { FAQsPage } from "@/components/matricole/faqs" import { MatricoleGuides } from "@/components/matricole/guides" import { MatricoleIntro } from "@/components/matricole/intro" -import { MatricoleFAQsShapes, MatricoleGuidesShapes, MatricoleIntroShapes } from "./shapes" +import { ResourcesHeroShapes } from "@/components/resources/shapes" +import { MatricoleFAQsShapes, MatricoleGuidesShapes } from "./shapes" export const metadata: Metadata = { title: "Matricole", @@ -13,7 +14,7 @@ export default function MatricolePage() { return (
- +
diff --git a/src/app/matricole/shapes.tsx b/src/app/matricole/shapes.tsx index f9bf48c..9372982 100644 --- a/src/app/matricole/shapes.tsx +++ b/src/app/matricole/shapes.tsx @@ -6,43 +6,10 @@ import { Shape, ShapeLayer } from "@/components/shapes" * see src/components/home/shapes.tsx for why. * * `top` is relative to the top of the section each component is mounted in - * (MatricoleIntro, MatricoleGuides, FAQsPage), matching how the section + * (MatricoleGuides, FAQsPage), matching how the section * boundaries are grouped in the Figma file, not to the page as a whole. */ -export function MatricoleIntroShapes() { - return ( - - {/* Mobile Shapes */} - - - - - - {/* Desktop Shapes */} - - - - - - ) -} - export function MatricoleGuidesShapes() { return ( diff --git a/src/assets/shapes/matricole-glow-2.svg b/src/assets/shapes/resources-glow-2.svg similarity index 100% rename from src/assets/shapes/matricole-glow-2.svg rename to src/assets/shapes/resources-glow-2.svg diff --git a/src/assets/shapes/matricole-top-glow.svg b/src/assets/shapes/resources-top-glow.svg similarity index 100% rename from src/assets/shapes/matricole-top-glow.svg rename to src/assets/shapes/resources-top-glow.svg diff --git a/src/components/resources/shapes.tsx b/src/components/resources/shapes.tsx new file mode 100644 index 0000000..33c0144 --- /dev/null +++ b/src/components/resources/shapes.tsx @@ -0,0 +1,38 @@ +import { Shape, ShapeLayer } from "@/components/shapes" + +/** + * Hero background shared by the Matricole and FAQs pages (same Figma design). + */ + +export function ResourcesHeroShapes() { + return ( + + {/* Mobile Shapes */} + + + + + + {/* Desktop Shapes */} + + + + + + ) +} diff --git a/src/components/shapes.tsx b/src/components/shapes.tsx index f69949f..3650ab0 100644 --- a/src/components/shapes.tsx +++ b/src/components/shapes.tsx @@ -4,9 +4,9 @@ import bigTealSvg from "@/assets/shapes/big-teal.svg" import heroGlowSvg from "@/assets/shapes/hero-glow.svg" import looperSvg from "@/assets/shapes/looper.svg" import matricoleGlow1Svg from "@/assets/shapes/matricole-glow-1.svg" -import matricoleGlow2Svg from "@/assets/shapes/matricole-glow-2.svg" -import matricoleTopGlowSvg from "@/assets/shapes/matricole-top-glow.svg" import projectsGlowSvg from "@/assets/shapes/projects-glow.svg" +import resourcesGlow2Svg from "@/assets/shapes/resources-glow-2.svg" +import resourcesTopGlowSvg from "@/assets/shapes/resources-top-glow.svg" import smallBlueSvg from "@/assets/shapes/small-blue.svg" import { cn } from "@/lib/utils" @@ -17,8 +17,8 @@ export type ShapeVariant = | "hero-glow" | "projects-glow" //TODO: remove these page specific shapes | "matricole-glow-1" - | "matricole-glow-2" - | "matricole-top-glow" + | "resources-glow-2" + | "resources-top-glow" | "looper" export type ShapeProps = { @@ -41,10 +41,10 @@ export const Shape: React.FC = ({ variant, className }) => { return projectsGlowSvg case "matricole-glow-1": return matricoleGlow1Svg - case "matricole-glow-2": - return matricoleGlow2Svg - case "matricole-top-glow": - return matricoleTopGlowSvg + case "resources-glow-2": + return resourcesGlow2Svg + case "resources-top-glow": + return resourcesTopGlowSvg case "looper": return looperSvg default: From d71bd8863d34a0b35f94fe9ecb8fe1d5b2591949 Mon Sep 17 00:00:00 2001 From: diubi Date: Wed, 23 Sep 2026 21:01:28 +0200 Subject: [PATCH 11/11] chore: biome --- src/app/matricole/guida/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/matricole/guida/page.tsx b/src/app/matricole/guida/page.tsx index f6a2506..729e925 100644 --- a/src/app/matricole/guida/page.tsx +++ b/src/app/matricole/guida/page.tsx @@ -1,9 +1,9 @@ import type { Metadata } from "next" import { FiDownload } from "react-icons/fi" import { CardSplit } from "@/components/card-split" +import { ResourcesHeroShapes } from "@/components/resources/shapes" import { Button } from "@/components/ui/button" import { getLatestGuidaMatricola } from "@/queries/guida-matricola" -import { ResourcesHeroShapes } from "@/components/resources/shapes" export const metadata: Metadata = { title: "Guida della Matricola",