Skip to content

new conf design — testimonials #2003

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: source
Choose a base branch
from
Open
2 changes: 1 addition & 1 deletion src/app/conf/2024/venue.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TrainIcon, AroundIcon, ParkingIcon, BusIcon } from "@/icons"
import { TrainIcon, AroundIcon, ParkingIcon } from "@/icons"
import NextImage from "next-image-export-optimizer"
import cityViewImage from "./sf-city-view.jpeg"

Expand Down
9 changes: 5 additions & 4 deletions src/app/conf/2025/components/call-for-proposals.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"use client"
import clsx from "clsx"

import { useState, useEffect, ReactNode, Fragment } from "react"
import clsx from "clsx"
import { useState, useEffect, Fragment } from "react"
import Link from "next/link"
import { Button } from "../../_design-system/button"
import ArrowDownIcon from "../pixelarticons/arrow-down.svg?svgr"

import ArrowDownIcon from "@/app/conf/_design-system/pixelarticons/arrow-down.svg?svgr"
import { Button } from "@/app/conf/_design-system/button"

function DatesTab() {
return (
Expand Down
2 changes: 1 addition & 1 deletion src/app/conf/2025/components/cta-card-section/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function CtaCardSection({
}}
>
<StripesDecoration
thin
stripeWidth="5.2px"
oddClassName="bg-[linear-gradient(180deg,var(--start)_0%,var(--end)_100%)]"
/>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/app/conf/2025/components/hero/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Image from "next-image-export-optimizer"

import { Button } from "../../../_design-system/button"
import { CalendarIcon } from "../../pixelarticons/calendar-icon"
import { CalendarIcon } from "../../../_design-system/pixelarticons/calendar-icon"
import { GET_TICKETS_LINK } from "../../links"
import { PinIcon } from "../../pixelarticons/pin-icon"
import { PinIcon } from "../../../_design-system/pixelarticons/pin-icon"
import graphqlFoundationWordmarkSvg from "../../assets/graphql-foundation-wordmark.svg"

import { ImageLoaded } from "../image-loaded"
Expand Down
7 changes: 3 additions & 4 deletions src/app/conf/2025/components/marquee-rows/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { clsx } from "clsx"
import { Fragment, ReactNode } from "react"

import { Marquee } from "@/app/conf/_design-system/marquee"

import CodeIcon from "../../pixelarticons/code.svg?svgr"
import CodeIcon from "@/app/conf/_design-system/pixelarticons/code.svg?svgr"
import { StripesDecoration } from "@/app/conf/_design-system/stripes-decoration"

import blurWave from "./blur.webp"
import { StripesDecoration } from "@/app/conf/_design-system/stripes-decoration"
import { clsx } from "clsx"

export interface MarqueeRowsProps extends React.HTMLAttributes<HTMLDivElement> {
items: ReactNode[][]
Expand Down
5 changes: 2 additions & 3 deletions src/app/conf/2025/components/navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
"use client"

import { ReactElement, useCallback, useEffect, useState } from "react"
import NextLink from "next/link"
import { clsx } from "clsx"
import { usePathname } from "next/navigation"

import { Badge } from "../../_components/badge"

import MenuIcon from "../pixelarticons/menu.svg?svgr"
import CloseIcon from "../pixelarticons/close.svg?svgr"
import MenuIcon from "@/app/conf/_design-system/pixelarticons/menu.svg?svgr"
import CloseIcon from "@/app/conf/_design-system/pixelarticons/close.svg?svgr"
import { GraphQLConfLogoLink } from "./graphql-conf-logo-link"
import { Anchor } from "../../_design-system/anchor"

Expand Down
2 changes: 1 addition & 1 deletion src/app/conf/2025/components/sponsors.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Grafbase from "public/img/conf/Sponsors/Grafbase.svg?svgr"

import { clsx } from "clsx"
import { ChevronRight } from "../pixelarticons/chevron-right"
import { ChevronRight } from "../../_design-system/pixelarticons/chevron-right"

interface Sponsor {
icon: React.FC<React.SVGProps<SVGElement>>
Expand Down
145 changes: 145 additions & 0 deletions src/app/conf/2025/components/testimonials/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { StripesDecoration } from "@/app/conf/_design-system/stripes-decoration"
import { clsx } from "clsx"
import Image from "next-image-export-optimizer"

import maskBlur from "./mask.webp"

export interface TestimonialsProps extends React.HTMLAttributes<HTMLElement> {}

interface Testimonial {
quote: string
author: {
name: string
role: string
avatar: string
}
}

const testimonials: Testimonial[] = [
{
quote:
"GraphQL is evolving to new use cases every day and it's really a competitive advantage to experience them first hand with everyone that matters. I look forward the next edition!",
author: {
name: "Vincent Desmares",
role: "Teamstarter, CTO",
avatar:
"https://avatars.sched.co/d/cc/21066875/avatar.jpg.320x320px.jpg?f80",
},
},
{
quote:
"As a beginner in GraphQL, it was very helpful to see real use cases and honest accounts of the challenges along the way. I learned a lot about performance and security and had a great opportunity to network with other participants and potential vendors.",
author: {
name: "Nicolai Draslov",
role: "Danish Agency for Digital Government",
avatar:
"https://media.licdn.com/dms/image/v2/C4E03AQGlrdt3GpJI9w/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1528203207471?e=1753920000&v=beta&t=H6CMhDZFoXJxGUu4XYwC_rEX9Jjwh7OdPIDm8JaeXAU",
},
},
{
quote:
"GraphQLConf 24 was well organized event which empowers new and existing organizations to adopt GraphQL and help navigate how to rollout within their organizations by building understanding of ecosystem.",
author: {
name: "Satish Chitnis",
role: "Paramount, Principal Architect",
avatar:
"https://avatars.sched.co/1/c3/21496512/avatar.jpg.320x320px.jpg?0c2",
},
},
]

export function Testimonials({ className, ...rest }: TestimonialsProps) {
return (
<section
className={clsx(
"gql-conf-container py-8 max-md:px-4 md:pb-16 md:pt-24 md:[mask-image:linear-gradient(to_right,transparent,black_5%,black_95%,transparent)]",
className,
)}
{...rest}
>
<h2 className="text-center text-neu-800 typography-h2">
How was the previous edition?
</h2>
<div className="flex w-full snap-x snap-mandatory flex-row gap-10 overflow-x-auto px-4 py-6 lg:mt-16 lg:py-16">
{testimonials.map((testimonial, i) => (
<div
key={i}
className="flex shrink-0 snap-start flex-row-reverse items-center gap-6 max-md:flex-col md:px-10"
>
<div>
<p className="max-w-[calc(100vw-32px)] !leading-[1.1] typography-body-lg max-md:text-center md:max-w-[544px]">
{testimonial.quote}
</p>
<AuthorNameAndRole
author={testimonial.author}
className="mt-4 max-md:hidden"
/>
</div>
<TestimonialAuthor author={testimonial.author} />
</div>
))}
</div>
</section>
)
}

function TestimonialAuthor({ author }: { author: Testimonial["author"] }) {
return (
<div className="relative flex shrink-0 flex-col items-center justify-center whitespace-pre md:px-6 lg:h-full lg:px-8">
<div className="relative bg-neu-500 dark:bg-neu-200 dark:opacity-90">
<Image
src={author.avatar}
alt={author.name}
width={128}
height={128}
className="size-16 saturate-0 xl:size-32"
/>
<div className="absolute inset-0 z-[1] bg-pri-darker mix-blend-plus-lighter" />
<Stripes />
</div>
<AuthorNameAndRole author={author} className="contents md:hidden" />
<div
// the separator
className="absolute inset-y-0 right-0 w-px bg-gradient-to-b from-transparent via-pri-lighter to-transparent max-md:hidden"
/>
</div>
)
}

function AuthorNameAndRole({
author,
className,
}: {
author: Testimonial["author"]
className?: string
}) {
return (
<div className={className}>
<div className="mt-3 typography-body-sm">{author.name}</div>
<div className="text-neu-700 typography-body-xs">{author.role}</div>
</div>
)
}

function Stripes() {
const mask = `url(${maskBlur.src})`
return (
<div
role="presentation"
className="pointer-events-none absolute inset-0"
style={{
maskImage: mask,
WebkitMaskImage: mask,
maskSize: "cover",
WebkitMaskSize: "cover",
maskPosition: "left",
WebkitMaskPosition: "left",
}}
>
<StripesDecoration
evenClassName="bg-gradient-to-b from-pri-light/0 to-pri-lighter/25"
stripeWidth="8px"
/>
</div>
)
}
Binary file not shown.
152 changes: 152 additions & 0 deletions src/app/conf/2025/components/venue/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { clsx } from "clsx"

import { Button } from "@/app/conf/_design-system/button"
import { Accordion } from "@/app/conf/_design-system/accordion"

import locationPhoto from "./location-photo.webp"

export interface VenueProps extends React.HTMLAttributes<HTMLElement> {}

export function Venue(props: VenueProps) {
return (
<section
{...props}
style={{
...({ "--photo": `url(${locationPhoto.src})` } as {}),
...props.style,
backgroundBlendMode: "overlay, normal",
}}
className={clsx(
"gql-conf-section relative bg-[linear-gradient(0deg,hsl(var(--color-sec-light))_0%,hsl(var(--color-sec-light))_100%),var(--photo)] dark:bg-[linear-gradient(180deg,#344303_0%,#344303_120%),var(--photo)] md:bg-cover",
props.className,
)}
>
<div className="relative flex gap-x-12 gap-y-10 bg-white/10 p-4 dark:bg-blk/10 max-lg:flex-col lg:p-16 xl:*:flex-1">
<div
className="absolute inset-0 backdrop-blur-3xl"
style={{
maskImage:
"radial-gradient(circle at center, #fff 65%, rgb(255 0 0/.8) 99%)",
WebkitMaskImage:
"radial-gradient(circle at center, #fff 65%, rgb(255 0 0/.8) 99%)",
}}
/>
<article className="relative flex shrink-0 flex-col gap-6 max-xl:max-w-[476px]">
<h2 className="typography-h2">
A place of innovation &&nbsp;creation
</h2>
<p className="typography-body-lg">
A former warehouse, located in an industrial area near the Amsterdam
city centre, changed into a place of culture & business.
</p>
<div className="flex-1" />
<p className="typography-body-lg">
Pakhuis De Zwijger <br />
Piet Heinkade 179, 1019 HC <br />
Amsterdam, Netherlands
</p>
<Button href="https://maps.app.goo.gl/W7nX1NejhWw9PqxF7">
Google Maps
</Button>
</article>
<div className="relative flex-1">
<h3 className="mb-6 typography-h3">How to get to the venue?</h3>
<Accordion
className="[&_svg]:fill-neu-900"
items={[
{
title: "Public Transportation",
description: (
<>
Take tram 26 from Amsterdam Central Station to the
"Kattenburgerstraat" stop.
<br />
The venue is in front of the tram stop.
</>
),
},
{
title: "Airport Information",
description:
"Amsterdam Airport Schiphol is about 20 km from the venue. Take a direct train to Amsterdam Central Station, then follow the public transportation instructions.",
},
{
title: "Parking at venue",
description: (
<>
Limited parking is available at the venue. We recommend
using public transportation when possible. Learn more about
parking at{" "}
<a
className="typography-link"
href="https://dezwijger.nl/about-us-en/contact"
target="_blank"
>
Pakhuis de Zwijger
</a>
. If&nbsp;you require an accessible parking spot, park at
Vriesseveem 4 or Withoedenveem 16 where you can park if you
have a Disability Parking Card.
</>
),
},
]}
/>
<h3 className="my-6 typography-h3">Where to stay?</h3>
<Accordion
className="[&_svg]:fill-neu-900"
items={[
{
title: "Mövenpick Hotel Amsterdam City Centre",
link: "https://movenpick.accor.com/en/europe/netherlands/amsterdam/hotel-amsterdam.html?utm_source=google&utm_medium=local&utm_campaign=hotel-MHR-Amsterdam-city-center&y_source=1_MTUzNjI2OTgtNzE1LWxvY2F0aW9uLndlYnNpdGU%3D",
description: (
<>
Piet Heinkade 11
<br />
1019 BR Amsterdam, Netherlands
<br />
Phone:{" "}
<a className="typography-link" href="tel:+31 20 519 1200">
+31 20 519 1200
</a>
</>
),
},
{
title: "Inntel Hotels Amsterdam Landmark",
link: "https://www.inntelhotelsamsterdamlandmark.nl/",
description: (
<>
VOC-kade 600
<br />
1018 LG Amsterdam, Netherlands
<br />
Phone:{" "}
<a className="typography-link" href="tel:+31 20 227 2550">
+31 20 227 2550
</a>
</>
),
},
{
title: "DoubleTree by Hilton Amsterdam Central Station",
link: "https://www.hilton.com/en/hotels/amscsdi-doubletree-amsterdam-centraal-station/?SEO_id=GMB-EMEA-DI-AMSCSDI",
description: (
<>
Oosterdoksstraat 4 <br />
1011 DK Amsterdam, Netherlands
<br />
Phone:{" "}
<a className="typography-link" href="tel:+31 20 530 0800">
+31 20 530 0800
</a>
</>
),
},
]}
/>
</div>
</div>
</section>
)
}
Binary file not shown.
6 changes: 3 additions & 3 deletions src/app/conf/2025/components/what-to-expect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ export default function WhatToExpectSection({
>
<h3 className="typography-h2 md:flex-1">What to expect</h3>
<ul className="flex flex-col gap-6 uppercase md:flex-1">
<ListItem number="3" text="days" />
<ListItem number="23" text="speakers" />
<ListItem number="36" text="panels & workshops" />
<ListItem number="75+" text="talks" />
<ListItem number="42" text="sessions" />
<ListItem number="7" text="workshops" />
<ListItem number="1" text="unique venue" />
</ul>
</section>
Expand Down
Loading