Skip to content

new conf design — get your ticket #10

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 7 commits into
base: new-conf-design--top-minds
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@graphql-tools/schema": "10.0.15",
"@headlessui/react": "^1.7.17",
"@radix-ui/react-radio-group": "^1.1.3",
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
"@tailwindcss/typography": "^0.5.10",
"autoprefixer": "^10.4.17",
Expand Down
12 changes: 12 additions & 0 deletions pnpm-lock.yaml

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

5 changes: 3 additions & 2 deletions src/app/colors.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
:root {
:root,
.light {
--color-pri-lighter: 319 100% 90%;
--color-pri-light: 319 100% 90%;
--color-pri-base: 319 100% 44%;
Expand All @@ -24,7 +25,7 @@
--color-neu-900: 75 15% 5%;
}

html.dark {
.dark {
--color-neu-900: 0 0% 100%;
--color-neu-800: 75 57% 97%;
--color-neu-700: 75 15% 95%;
Expand Down
Binary file not shown.
74 changes: 74 additions & 0 deletions src/app/conf/2025/components/get-your-ticket/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { clsx } from "clsx"

import { ImageLoaded } from "../image-loaded"

import { TicketPeriods } from "./ticket-periods"

import blurBean from "./blur-bean.webp"

export function GetYourTicket({ className }: { className?: string }) {
return (
<section
className={clsx(
"dark relative overflow-hidden bg-pri-dark px-4 py-8 lg:py-16 xl:py-24",
className,
)}
>
<Stripes />
<div className="gql-conf-container gql-conf-section relative">
<header className="flex flex-wrap justify-between gap-6 md:items-end">
<h2 className="whitespace-pre text-white typography-h2">
Get your ticket
</h2>
<p className="text-neu-800 typography-body-lg">
The registration deadline is 23:59 CET on the respective date.
</p>
</header>

<div className="mt-6 grid gap-px backdrop-blur-[6px] md:mt-10 md:grid-cols-3">
<TicketPeriods />
</div>
</div>
</section>
)
}

const maskEven =
"repeating-linear-gradient(to right, transparent, transparent 12px, black 12px, black 24px)"
const maskOdd =
"repeating-linear-gradient(to right, black, black 12px, transparent 12px, transparent 24px)"

function Stripes() {
return (
<ImageLoaded
role="presentation"
image={blurBean}
className="pointer-events-none absolute inset-x-0 bottom-[-385px] top-[-203px] translate-y-12 opacity-0 transition duration-[400ms] ease-linear [mask-position:70%_60%] *:opacity-100 data-[loaded=true]:translate-y-0 data-[loaded=true]:opacity-100 max-3xl:[mask-size:220%] max-md:[mask-size:800%] md:*:opacity-30 lg:*:opacity-50 xl:*:opacity-60 3xl:[mask-position:70%_39%]"
style={{
maskImage: `url(${blurBean.src})`,
WebkitMaskImage: `url(${blurBean.src})`,
maskRepeat: "no-repeat",
WebkitMaskRepeat: "no-repeat",
}}
>
<div
className="absolute inset-0"
style={{
backgroundImage:
"linear-gradient(180deg, hsl(var(--color-pri-light)) 0%, hsl(var(--color-pri-lighter)) 100%)",
maskImage: maskEven,
WebkitMaskImage: maskEven,
}}
/>
<div
className="absolute inset-0"
style={{
backgroundImage:
"linear-gradient(180deg,hsl(319deg 100% 90% / 0.2) 0%, hsl(var(--color-pri-base)) 100%)",
maskImage: maskOdd,
WebkitMaskImage: maskOdd,
}}
/>
</ImageLoaded>
)
}
91 changes: 91 additions & 0 deletions src/app/conf/2025/components/get-your-ticket/ticket-period.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Button } from "@/app/conf/_design-system/button"
import { clsx } from "clsx"
import { GET_TICKETS_LINK } from "../../links"

export interface TicketPeriodProps {
price: string
date: Date | [Date, Date]
isLoading?: boolean
soldOut?: boolean
comingSoon?: boolean
name: string
}

export function TicketPeriod({
price,
date,
isLoading,
soldOut,
comingSoon,
name,
}: TicketPeriodProps) {
const disabled = soldOut || comingSoon || isLoading

return (
<article
data-disabled={disabled}
className={clsx(
"flex flex-col border border-pri-lighter bg-pri-light/[0.24] backdrop-blur-md transition @container/card max-md:[&+&]:border-t-0 md:[&+&]:border-l-0",
disabled
? "opacity-50 max-md:[&:has(+article[data-disabled=false])]:border-b-0 md:[&:has(+article[data-disabled=false])]:border-r-0"
: "!border",
)}
>
<header className="border-b border-pri-lighter p-6">
<h3 className="text-white typography-h3">{name}</h3>
</header>
<div className="flex h-full flex-col justify-end gap-6 p-6">
<div className="flex items-end justify-between gap-2">
<span className="text-white typography-h3 @[356px]:typography-h2">
{price}
</span>
{/* eslint-disable-next-line tailwindcss/no-custom-classname */}
<span className="ticket-period--date text-right text-white typography-body-md">
{Array.isArray(date) ? (
<>
<Time date={date[0]} />
{" - "}
<Time date={date[1]} />
</>
) : (
<>
<span>Through </span>
<Time date={date} />
</>
)}
</span>
</div>
<Button
variant="primary"
disabled={disabled}
className="light w-full"
href={GET_TICKETS_LINK}
>
{isLoading
? "Get a ticket"
: soldOut
? "Sold out"
: comingSoon
? "Coming soon"
: "Get a ticket"}
</Button>
</div>
</article>
)
}

function Time({ date }: { date: Date }) {
return (
<time
dateTime={date.toISOString()}
dangerouslySetInnerHTML={{
__html: date
.toLocaleDateString("en-GB", {
month: "long",
day: "numeric",
})
.replace(" ", "&nbsp"),
}}
/>
)
}
55 changes: 55 additions & 0 deletions src/app/conf/2025/components/get-your-ticket/ticket-periods.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client"

import { useState, useEffect } from "react"

import { TicketPeriod } from "./ticket-period"

// Ticket period end dates (using zero-indexed months)
// Dates are specified in CET (UTC+1/UTC+2 for CEST) and converted to UTC
// Example: July 13th 23:59 CEST (UTC+2) becomes July 13th 21:59 UTC
const EARLY_BIRD_END_DATE = new Date(Date.UTC(2025, 6, 13, 21, 59)) // July 13th 23:59 CEST
const STANDARD_END_DATE = new Date(Date.UTC(2025, 7, 31, 21, 59)) // August 31st 23:59 CEST
const LATE_END_DATE = new Date(Date.UTC(2025, 8, 10, 21, 59)) // September 10th 23:59 CEST

export function TicketPeriods() {
const now = useCurrentDate()

return (
<>
<TicketPeriod
name="Early Bird"
price="$599"
date={EARLY_BIRD_END_DATE}
comingSoon={false}
isLoading={!now}
soldOut={!!now && now > EARLY_BIRD_END_DATE}
/>
<TicketPeriod
name="Standard"
price="$799"
date={[new Date(2025, 6, 14), STANDARD_END_DATE]}
isLoading={!now}
comingSoon={!!now && now < EARLY_BIRD_END_DATE}
soldOut={!!now && now > STANDARD_END_DATE}
/>
<TicketPeriod
name="Late"
price="$899"
date={[new Date(2025, 8, 1), LATE_END_DATE]}
isLoading={!now}
comingSoon={!!now && now < STANDARD_END_DATE}
soldOut={!!now && now > LATE_END_DATE}
/>
</>
)
}

function useCurrentDate() {
const [date, setDate] = useState<Date | null>(null)

useEffect(() => {
setDate(new Date())
}, [])

return date
}
21 changes: 11 additions & 10 deletions src/app/conf/2025/components/hero/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { clsx } from "clsx"
import Image from "next-image-export-optimizer"

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

import { ImageLoaded } from "../image-loaded"
import blurBean from "./blur-bean-cropped.webp"
import { ImageLoaded } from "./image-loaded"
import heroPhoto from "./hero-photo.jpeg"

export function Hero() {
return (
Expand Down Expand Up @@ -71,12 +72,12 @@ function DateAndLocation() {
)
}

function Stripes() {
const maskEven =
"repeating-linear-gradient(to right, transparent, transparent 12px, black 12px, black 24px)"
const maskOdd =
"repeating-linear-gradient(to right, black, black 12px, transparent 12px, transparent 24px)"
const maskEven =
"repeating-linear-gradient(to right, transparent, transparent 12px, black 12px, black 24px)"
const maskOdd =
"repeating-linear-gradient(to right, black, black 12px, transparent 12px, transparent 24px)"

function Stripes() {
return (
<ImageLoaded
role="presentation"
Expand Down
4 changes: 2 additions & 2 deletions src/app/conf/2025/components/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ function GraphQLLogo(props: React.SVGProps<SVGSVGElement>) {
return (
<svg viewBox="0 0 100 100" fill="currentColor" {...props}>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M50 6.90308L87.323 28.4515V71.5484L50 93.0968L12.677 71.5484V28.4515L50 6.90308ZM16.8647 30.8693V62.5251L44.2795 15.0414L16.8647 30.8693ZM50 13.5086L18.3975 68.2457H81.6025L50 13.5086ZM77.4148 72.4334H22.5852L50 88.2613L77.4148 72.4334ZM83.1353 62.5251L55.7205 15.0414L83.1353 30.8693V62.5251Z"
/>
<circle cx="50" cy="9.3209" r="8.82" />
Expand Down
2 changes: 1 addition & 1 deletion src/app/conf/2025/components/register-today/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function RegisterToday({ className }: RegisterTodayProps) {
return (
<section
className={clsx(
"flex gap-10 px-4 py-8 max-lg:flex-col-reverse lg:px-12 xl:gap-x-24 xl:px-24",
"gql-conf-section flex gap-10 max-lg:flex-col-reverse",
className,
)}
>
Expand Down
2 changes: 1 addition & 1 deletion src/app/conf/2025/components/top-minds/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function TopMindsSection({
return (
<section
className={clsx(
"flex justify-center px-4 py-8 text-neu-900 max-md:flex-col lg:px-12 xl:gap-x-24 xl:px-24",
"gql-conf-section flex justify-center max-md:flex-col",
className,
)}
{...rest}
Expand Down
5 changes: 1 addition & 4 deletions src/app/conf/2025/components/what-to-expect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ export default function WhatToExpectSection({
}: WhatToExpectSectionProps) {
return (
<section
className={clsx(
"flex gap-6 px-4 py-8 text-neu-900 max-md:flex-col lg:px-12 xl:gap-x-24 xl:px-24",
className,
)}
className={clsx("gql-conf-section flex gap-6 max-md:flex-col", className)}
{...rest}
>
<h3 className="typography-h2 md:flex-1">What to expect</h3>
Expand Down
8 changes: 5 additions & 3 deletions src/app/conf/2025/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@ import { RegisterToday } from "./components/register-today"
import { Hero } from "./components/hero"
import WhatToExpectSection from "./components/what-to-expect"
import TopMindsSection from "./components/top-minds"

import { GetYourTicket } from "./components/get-your-ticket"
export const metadata: Metadata = {
title: "GraphQLConf 2025 — Sept 08-10",
}

export default function Page() {
return (
<main>
<main className="antialiased">
<Hero />
<div className="gql-conf-container mx-auto">
<div className="gql-conf-container mx-auto text-neu-900">
<RegisterToday className="md:mb-8 md:mt-24" />
<WhatToExpectSection className="md:mb-8 md:mt-24" />
<TopMindsSection className="md:mb-8 md:mt-24" hasSpeakersPage={false} />
</div>
<GetYourTicket />

<div className="container my-20 flex flex-col gap-20 md:my-32 md:gap-32 [.light_&_.text-white]:text-neu-900 [.light_&_[alt='Grafbase_logo']]:invert">
<Sponsors />
<Sponsor />
Expand Down
Loading
Loading