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
26 changes: 10 additions & 16 deletions app/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Suspense } from "react";
import type { Metadata } from "next";
import CoverBackground from "../components/CoverBackground";
import Menu from "../components/Menu.client";
import PageHero from "../components/PageHero";
import FluidContainer from "../../components/FluidContainer";
import BlogCard from "../components/BlogCard";
import Pagination from "../components/Pagination";
Expand Down Expand Up @@ -46,20 +45,15 @@ interface BlogPageProps {
export default function BlogPage({ searchParams }: BlogPageProps) {
return (
<main>
<div className="relative">
<Menu />
<CoverBackground>
<div className="w-full max-w-screen-2xl px-4 pt-28 pb-16 md:pt-32 md:pb-20 lg:px-24 xl:px-32">
<h1 className="font-serif text-4xl font-bold text-white md:text-5xl">
Nos articles
</h1>
<p className="max-w-xl pt-3 text-white/60">
Retours d&#39;expérience, guides techniques et bonnes pratiques de
notre équipe.
</p>
</div>
</CoverBackground>
</div>
<PageHero
title="Nos articles"
subtitle={
<>
Retours d&#39;expérience, guides techniques et bonnes pratiques de
notre équipe.
</>
}
/>

<FluidContainer>
<div className="-mt-8 pb-24">
Expand Down
18 changes: 11 additions & 7 deletions app/components/CallToAction.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import SectionTitle from "../../components/SectionTitle";

export default function CallToAction() {
interface CallToActionProps {
title?: string;
subtitle?: string;
}

export default function CallToAction({
title = "On en discute ?",
subtitle = "Reservez un creneau de 30 minutes pour parler de votre projet.",
}: CallToActionProps) {
return (
<div className="flex flex-col items-center gap-8 py-20 text-center">
<SectionTitle className="from-white to-white/70">
On en discute ?
</SectionTitle>
<p className="max-w-lg text-lg text-white/80">
Reservez un creneau de 30 minutes pour parler de votre projet.
</p>
<SectionTitle className="from-white to-white/70">{title}</SectionTitle>
<p className="max-w-lg text-lg text-white/80">{subtitle}</p>
<a
href="https://cal.com/nicolasrouanne/30min"
target="_blank"
Expand Down
95 changes: 95 additions & 0 deletions app/components/CoworkGallery.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"use client";

import { useState, type CSSProperties } from "react";
import Image, { StaticImageData } from "next/image";
import { Dialog } from "@headlessui/react";
import { XMarkIcon } from "@heroicons/react/24/solid";

interface Photo {
src: StaticImageData;
alt: string;
}

const GALLERY_SIZES = "(min-width: 1024px) 1100px, 90vw";
const PER_ROW = 3;

export default function CoworkGallery({ photos }: { photos: Photo[] }) {
const [active, setActive] = useState<Photo | null>(null);

const rows: Photo[][] = [];
for (let i = 0; i < photos.length; i += PER_ROW) {
rows.push(photos.slice(i, i + PER_ROW));
}

return (
<>
<div className="mt-8 flex flex-col gap-4">
{rows.map((row) => (
<div
key={row.map((photo) => photo.alt).join("|")}
className="flex flex-col gap-4 sm:flex-row"
>
{row.map((photo) => (
<button
key={photo.alt}
type="button"
onClick={() => setActive(photo)}
aria-label={`Agrandir : ${photo.alt}`}
style={
{ "--r": photo.src.width / photo.src.height } as CSSProperties
}
className="group relative w-full overflow-hidden [aspect-ratio:var(--r)] sm:w-auto sm:[flex-basis:0] sm:[flex-grow:var(--r)]"
>
<Image
src={photo.src}
alt={photo.alt}
fill
sizes={GALLERY_SIZES}
placeholder="blur"
className="object-cover transition-transform duration-300 group-hover:scale-105"
/>
</button>
))}
</div>
))}
</div>

<Dialog
open={active !== null}
onClose={() => setActive(null)}
className="relative z-50"
>
<div className="fixed inset-0 bg-black/80" aria-hidden="true" />
<div className="fixed inset-0 flex items-center justify-center p-4">
{active && (
<Dialog.Panel
className="relative"
style={{
aspectRatio: active.src.width / active.src.height,
width: `min(90vw, ${
(85 * active.src.width) / active.src.height
}vh)`,
}}
>
<button
type="button"
onClick={() => setActive(null)}
aria-label="Fermer"
className="absolute -top-10 right-0 text-white hover:text-white/70"
>
<XMarkIcon className="h-8 w-8" />
</button>
<Image
src={active.src}
alt={active.alt}
fill
sizes={GALLERY_SIZES}
className="object-cover"
/>
</Dialog.Panel>
)}
</div>
</Dialog>
</>
);
}
5 changes: 4 additions & 1 deletion app/components/Menu.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import Link from "next/link";
import clsx from "clsx";
import { XMarkIcon, Bars3Icon } from "@heroicons/react/20/solid";

import { SITE_CONTAINER } from "../../lib/site";

import ContactUs from "./ContactUs";

const menuItems = [
Expand All @@ -13,6 +15,7 @@ const menuItems = [
{ id: "stack", label: "Stack" },
{ id: "team", label: "Équipe" },
{ id: "portfolio", label: "Portfolio" },
{ id: "cowork", label: "Cowork", href: "/cowork" },
{ id: "blog", label: "Blog", href: "/blog" },
];

Expand All @@ -35,7 +38,7 @@ export default function Menu({ variant = "dark" }: MenuProps) {
)}
onClick={mobileOpen ? () => setMobileOpen(false) : () => {}}
>
<div className="max-w-screen-2xl px-4 pt-6 lg:px-24 xl:px-32">
<div className={clsx(SITE_CONTAINER, "pt-6")}>
<div
className={clsx(
"flex flex-col",
Expand Down
38 changes: 38 additions & 0 deletions app/components/PageHero.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { ReactNode } from "react";
import clsx from "clsx";

import { SITE_CONTAINER } from "../../lib/site";

import Menu from "./Menu.client";
import CoverBackground from "./CoverBackground";

interface PageHeroProps {
title: string;
subtitle: ReactNode;
menuVariant?: "dark" | "light";
}

export default function PageHero({
title,
subtitle,
menuVariant,
}: PageHeroProps) {
return (
<div className="relative">
<Menu variant={menuVariant} />
<CoverBackground>
<div
className={clsx(
"w-full pt-28 pb-16 md:pt-32 md:pb-20",
SITE_CONTAINER
)}
>
<h1 className="font-serif text-4xl font-bold text-white md:text-5xl">
{title}
</h1>
<p className="max-w-xl pt-3 text-white/60">{subtitle}</p>
</div>
</CoverBackground>
</div>
);
}
Loading
Loading