Skip to content

Commit 4df853f

Browse files
authored
Merge pull request #6 from AndroidMontreal/feat/site-updates-changes
Feat/site updates changes
2 parents 36d68fe + 7f04f7a commit 4df853f

19 files changed

Lines changed: 273 additions & 73 deletions

File tree

public/assets/images/sponsors/gold_davidson_canada.svg

Lines changed: 1 addition & 1 deletion
Loading

src/app/[locale]/layout.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ export default async function LocaleLayout({
8383
className={`${inter.variable} ${jetBrainsMono.variable} ${spaceGrotesk.variable}`}
8484
>
8585
<NextIntlClientProvider messages={messages}>
86-
<div className="flex flex-col min-h-screen">
86+
<div className="relative isolate flex min-h-screen flex-col">
87+
<div className="pointer-events-none fixed inset-0 -z-10 bg-background">
88+
<div className="blueprint-subgrid absolute inset-0" />
89+
<div className="blueprint-grid absolute inset-0" />
90+
</div>
8791
<SiteHeaderShell header={header} nav={nav} />
8892
<main className="relative z-0 flex-grow">{children}</main>
8993
<SiteFooter />

src/app/[locale]/schedule/page.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ComingSoonPage } from '@/components/common/coming-soon-page';
2+
import { getTranslations, setRequestLocale } from 'next-intl/server';
3+
4+
export default async function SchedulePage({
5+
params,
6+
}: {
7+
params: Promise<{ locale: string }>;
8+
}) {
9+
const { locale } = await params;
10+
setRequestLocale(locale);
11+
12+
const t = await getTranslations({ locale, namespace: 'SchedulePage' });
13+
14+
return (
15+
<ComingSoonPage
16+
subheading={t('subheading')}
17+
headingLine1={t('heading.line1')}
18+
headingLine2={t('heading.line2')}
19+
message={t('message')}
20+
/>
21+
);
22+
}

src/app/[locale]/speakers/page.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ComingSoonPage } from '@/components/common/coming-soon-page';
2+
import { getTranslations, setRequestLocale } from 'next-intl/server';
3+
4+
export default async function SpeakersPage({
5+
params,
6+
}: {
7+
params: Promise<{ locale: string }>;
8+
}) {
9+
const { locale } = await params;
10+
setRequestLocale(locale);
11+
12+
const t = await getTranslations({ locale, namespace: 'SpeakersPage' });
13+
14+
return (
15+
<ComingSoonPage
16+
subheading={t('subheading')}
17+
headingLine1={t('heading.line1')}
18+
headingLine2={t('heading.line2')}
19+
message={t('message')}
20+
/>
21+
);
22+
}

src/app/[locale]/team/page.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ComingSoonPage } from '@/components/common/coming-soon-page';
2+
import { getTranslations, setRequestLocale } from 'next-intl/server';
3+
4+
export default async function TeamPage({
5+
params,
6+
}: {
7+
params: Promise<{ locale: string }>;
8+
}) {
9+
const { locale } = await params;
10+
setRequestLocale(locale);
11+
12+
const t = await getTranslations({ locale, namespace: 'TeamPage' });
13+
14+
return (
15+
<ComingSoonPage
16+
subheading={t('subheading')}
17+
headingLine1={t('heading.line1')}
18+
headingLine2={t('heading.line2')}
19+
message={t('message')}
20+
/>
21+
);
22+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { SectionHeader } from './section-header';
2+
3+
type ComingSoonPageProps = {
4+
subheading: string;
5+
headingLine1: string;
6+
headingLine2: string;
7+
message: string;
8+
};
9+
10+
export function ComingSoonPage({
11+
subheading,
12+
headingLine1,
13+
headingLine2,
14+
message,
15+
}: ComingSoonPageProps) {
16+
return (
17+
<section className="mx-auto w-full max-w-[1440px] px-6 py-32 md:px-12">
18+
<SectionHeader
19+
subheading={subheading}
20+
headingLine1={headingLine1}
21+
headingLine2={headingLine2}
22+
/>
23+
<div className="max-w-3xl">
24+
<p className="font-mono-tech text-sm uppercase tracking-[0.22em] text-white/70">
25+
{message}
26+
</p>
27+
</div>
28+
</section>
29+
);
30+
}
31+

src/components/common/site-header-shell.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useState } from 'react';
44
import { MobileMenu } from '@/components/home/mobile-menu';
55
import { SiteHeader } from '@/components/home/site-header';
6+
import { usePathname } from '@/i18n/navigation';
67

78
export type HeaderCopy = {
89
logoAlt: string;
@@ -23,6 +24,7 @@ type SiteHeaderShellProps = {
2324

2425
export function SiteHeaderShell({ header, nav }: SiteHeaderShellProps) {
2526
const [isMenuOpen, setIsMenuOpen] = useState(false);
27+
const pathname = usePathname();
2628

2729
const toggleMenu = () => {
2830
setIsMenuOpen((prev) => !prev);
@@ -33,11 +35,16 @@ export function SiteHeaderShell({ header, nav }: SiteHeaderShellProps) {
3335
<SiteHeader
3436
header={header}
3537
nav={nav}
38+
currentPathname={pathname}
3639
isMenuOpen={isMenuOpen}
3740
toggleMenu={toggleMenu}
3841
/>
39-
<MobileMenu nav={nav} isOpen={isMenuOpen} toggleMenu={toggleMenu} />
42+
<MobileMenu
43+
nav={nav}
44+
currentPathname={pathname}
45+
isOpen={isMenuOpen}
46+
toggleMenu={toggleMenu}
47+
/>
4048
</>
4149
);
4250
}
43-

src/components/home/home-landing.tsx

Lines changed: 46 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -16,63 +16,55 @@ type HomeLandingProps = {
1616

1717
export function HomeLanding({ copy }: HomeLandingProps) {
1818
return (
19-
<>
20-
{/* Global Grid Background */}
21-
<div className="fixed inset-0 -z-10 bg-background">
22-
<div className="blueprint-subgrid absolute inset-0" />
23-
<div className="blueprint-grid absolute inset-0" />
24-
</div>
25-
26-
<main>
27-
{/* Hero Section */}
28-
<section className="relative flex min-h-screen w-full flex-col overflow-hidden">
29-
{/* Hero-specific background elements */}
30-
<div className="absolute inset-0 z-0">
31-
<div className="absolute inset-0 overflow-hidden">
32-
<Image
33-
src="/assets/images/backgrounds/hero-skyline.png"
34-
alt=""
35-
fill
36-
priority
37-
className="object-cover object-bottom opacity-10"
38-
/>
39-
</div>
40-
<div className="absolute inset-0 bg-gradient-to-b from-[#050505] via-transparent to-[#050505]" />
41-
<div className="scanning-line" />
19+
<main>
20+
{/* Hero Section */}
21+
<section className="relative flex min-h-screen w-full flex-col overflow-hidden">
22+
{/* Hero-specific background elements */}
23+
<div className="absolute inset-0 z-0">
24+
<div className="absolute inset-0 overflow-hidden">
25+
<Image
26+
src="/assets/images/backgrounds/hero-skyline.png"
27+
alt=""
28+
fill
29+
priority
30+
className="object-cover object-bottom opacity-10"
31+
/>
4232
</div>
33+
<div className="absolute inset-0 bg-gradient-to-b from-[#050505] via-transparent to-[#050505]" />
34+
<div className="scanning-line" />
35+
</div>
4336

44-
{/* Hero Content Wrapper */}
45-
<div className="relative z-10 flex flex-grow flex-col">
46-
<HeroContent hero={copy.hero} stats={copy.stats} />
47-
<HeroBottomHud hud={copy.hud} />
48-
<HeroTicker ticker={copy.ticker} />
49-
</div>
50-
</section>
37+
{/* Hero Content Wrapper */}
38+
<div className="relative z-10 flex flex-grow flex-col">
39+
<HeroContent hero={copy.hero} stats={copy.stats} />
40+
<HeroBottomHud hud={copy.hud} />
41+
<HeroTicker ticker={copy.ticker} />
42+
</div>
43+
</section>
5144

52-
{/* Gallery Section */}
53-
<section className="mx-auto w-full max-w-[1440px] px-6 py-32 md:px-12">
54-
<SectionHeader
55-
subheading={copy.gallery.header.subheading}
56-
headingLine1={copy.gallery.header.heading.line1}
57-
headingLine2={copy.gallery.header.heading.line2}
58-
/>
59-
<GalleryGrid items={copy.gallery.items} />
60-
</section>
45+
{/* Gallery Section */}
46+
<section className="mx-auto w-full max-w-[1440px] px-6 py-32 md:px-12">
47+
<SectionHeader
48+
subheading={copy.gallery.header.subheading}
49+
headingLine1={copy.gallery.header.heading.line1}
50+
headingLine2={copy.gallery.header.heading.line2}
51+
/>
52+
<GalleryGrid items={copy.gallery.items} />
53+
</section>
6154

62-
{/* Sponsors Section */}
63-
<section className="mx-auto w-full max-w-[1440px] px-6 py-32 md:px-12">
64-
<SectionHeader
65-
subheading={copy.sponsors.header.subheading}
66-
headingLine1={copy.sponsors.header.heading.line1}
67-
headingLine2={copy.sponsors.header.heading.line2}
68-
headingLine2ClassName="text-google-yellow"
69-
/>
70-
<SponsorsTiers
71-
tiers={copy.sponsors.tiers}
72-
ctaLabel={copy.sponsors.cta.label}
73-
/>
74-
</section>
75-
</main>
76-
</>
55+
{/* Sponsors Section */}
56+
<section className="mx-auto w-full max-w-[1440px] px-6 py-32 md:px-12">
57+
<SectionHeader
58+
subheading={copy.sponsors.header.subheading}
59+
headingLine1={copy.sponsors.header.heading.line1}
60+
headingLine2={copy.sponsors.header.heading.line2}
61+
headingLine2ClassName="text-google-yellow"
62+
/>
63+
<SponsorsTiers
64+
tiers={copy.sponsors.tiers}
65+
ctaLabel={copy.sponsors.cta.label}
66+
/>
67+
</section>
68+
</main>
7769
);
7870
}

src/components/home/mobile-menu.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,25 @@ type HeaderNavItem = {
1111

1212
type MobileMenuProps = {
1313
nav: HeaderNavItem[];
14+
currentPathname: string;
1415
isOpen: boolean;
1516
toggleMenu: () => void;
1617
};
1718

18-
export function MobileMenu({ nav, isOpen, toggleMenu }: MobileMenuProps) {
19+
function normalizePath(path: string) {
20+
const localeFreePath = path.replace(/^\/(en|fr)(?=\/|$)/, '') || '/';
21+
if (localeFreePath === '/') return '/';
22+
return localeFreePath.replace(/\/+$/, '');
23+
}
24+
25+
function isActiveNavItem(currentPathname: string, href: string) {
26+
const current = normalizePath(currentPathname);
27+
const target = normalizePath(href);
28+
if (target === '/') return current === '/';
29+
return current === target || current.startsWith(`${target}/`);
30+
}
31+
32+
export function MobileMenu({ nav, currentPathname, isOpen, toggleMenu }: MobileMenuProps) {
1933
const menuVariants = {
2034
hidden: { x: '100%' },
2135
visible: { x: 0, transition: { duration: 0.3 } },
@@ -49,7 +63,11 @@ export function MobileMenu({ nav, isOpen, toggleMenu }: MobileMenuProps) {
4963
<Link
5064
key={item.href}
5165
onClick={toggleMenu}
52-
className="font-mono-tech text-xl uppercase"
66+
className={`font-mono-tech text-xl uppercase transition-colors ${
67+
isActiveNavItem(currentPathname, item.href)
68+
? 'text-google-yellow'
69+
: 'text-white/75 hover:text-white'
70+
}`}
5371
href={item.href}
5472
>
5573
{item.label}

src/components/home/site-header.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,31 @@ type HeaderNavItem = {
2121
type SiteHeaderProps = {
2222
header: HeaderCopy;
2323
nav: HeaderNavItem[];
24+
currentPathname: string;
2425
isMenuOpen: boolean;
2526
toggleMenu: () => void;
2627
};
2728

28-
export function SiteHeader({ header, nav, isMenuOpen, toggleMenu }: SiteHeaderProps) {
29+
function normalizePath(path: string) {
30+
const localeFreePath = path.replace(/^\/(en|fr)(?=\/|$)/, '') || '/';
31+
if (localeFreePath === '/') return '/';
32+
return localeFreePath.replace(/\/+$/, '');
33+
}
34+
35+
function isActiveNavItem(currentPathname: string, href: string) {
36+
const current = normalizePath(currentPathname);
37+
const target = normalizePath(href);
38+
if (target === '/') return current === '/';
39+
return current === target || current.startsWith(`${target}/`);
40+
}
41+
42+
export function SiteHeader({
43+
header,
44+
nav,
45+
currentPathname,
46+
isMenuOpen,
47+
toggleMenu,
48+
}: SiteHeaderProps) {
2949
const [scrolled, setScrolled] = useState(true);
3050

3151
useEffect(() => {
@@ -81,12 +101,14 @@ export function SiteHeader({ header, nav, isMenuOpen, toggleMenu }: SiteHeaderPr
81101
{nav.map((item, index) => {
82102
const colors = ['blue', 'red', 'yellow', 'green'];
83103
const colorClass = `hover:text-google-${colors[index % colors.length]}`;
84-
const opacityClass = index === 0 ? 'text-white' : 'text-white/50';
104+
const activeClass = isActiveNavItem(currentPathname, item.href)
105+
? 'text-white'
106+
: 'text-white/50';
85107

86108
return (
87109
<Link
88110
key={item.href}
89-
className={`font-mono-tech text-[12px] tracking-[0.32em] ${opacityClass} ${colorClass} uppercase transition-colors`}
111+
className={`font-mono-tech text-[12px] tracking-[0.32em] ${activeClass} ${colorClass} uppercase transition-colors`}
90112
href={item.href}
91113
>
92114
{item.label}

0 commit comments

Comments
 (0)